[svn r5] Initial commit. Most things are very rough.

This commit is contained in:
Tomas Lindquist Olsen
2007-09-01 21:43:27 +02:00
parent 1c23dd2cdc
commit 34699bbb07
227 changed files with 84269 additions and 0 deletions

1257
dmd/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

423
dmd/access.c Normal file
View File

@@ -0,0 +1,423 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "root.h"
#include "mem.h"
#include "enum.h"
#include "aggregate.h"
#include "init.h"
#include "attrib.h"
#include "scope.h"
#include "id.h"
#include "mtype.h"
#include "declaration.h"
#include "aggregate.h"
#include "expression.h"
#include "module.h"
#define LOG 0
/* Code to do access checks
*/
int hasPackageAccess(Scope *sc, Dsymbol *s);
/****************************************
* Return PROT access for Dsymbol smember in this declaration.
*/
enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
{
return PROTpublic;
}
enum PROT StructDeclaration::getAccess(Dsymbol *smember)
{
enum PROT access_ret = PROTnone;
#if LOG
printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
toChars(), smember->toChars());
#endif
if (smember->toParent() == this)
{
access_ret = smember->prot();
}
else if (smember->isDeclaration()->isStatic())
{
access_ret = smember->prot();
}
return access_ret;
}
enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
{
enum PROT access_ret = PROTnone;
#if LOG
printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
toChars(), smember->toChars());
#endif
if (smember->toParent() == this)
{
access_ret = smember->prot();
}
else
{
enum PROT access;
int i;
if (smember->isDeclaration()->isStatic())
{
access_ret = smember->prot();
}
for (i = 0; i < baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
access = b->base->getAccess(smember);
switch (access)
{
case PROTnone:
break;
case PROTprivate:
access = PROTnone; // private members of base class not accessible
break;
case PROTpackage:
case PROTprotected:
case PROTpublic:
case PROTexport:
// If access is to be tightened
if (b->protection < access)
access = b->protection;
// Pick path with loosest access
if (access > access_ret)
access_ret = access;
break;
default:
assert(0);
}
}
}
#if LOG
printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
toChars(), smember->toChars(), access_ret);
#endif
return access_ret;
}
/********************************************************
* Helper function for ClassDeclaration::accessCheck()
* Returns:
* 0 no access
* 1 access
*/
static int accessCheckX(
Dsymbol *smember,
Dsymbol *sfunc,
AggregateDeclaration *dthis,
AggregateDeclaration *cdscope)
{
assert(dthis);
#if 0
printf("accessCheckX for %s.%s in function %s() in scope %s\n",
dthis->toChars(), smember->toChars(),
sfunc ? sfunc->toChars() : "NULL",
cdscope ? cdscope->toChars() : "NULL");
#endif
if (dthis->hasPrivateAccess(sfunc) ||
dthis->isFriendOf(cdscope))
{
if (smember->toParent() == dthis)
return 1;
else
{
ClassDeclaration *cdthis = dthis->isClassDeclaration();
if (cdthis)
{
for (int i = 0; i < cdthis->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
enum PROT access;
access = b->base->getAccess(smember);
if (access >= PROTprotected ||
accessCheckX(smember, sfunc, b->base, cdscope)
)
return 1;
}
}
}
}
else
{
if (smember->toParent() != dthis)
{
ClassDeclaration *cdthis = dthis->isClassDeclaration();
if (cdthis)
{
for (int i = 0; i < cdthis->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
if (accessCheckX(smember, sfunc, b->base, cdscope))
return 1;
}
}
}
}
return 0;
}
/*******************************
* Do access check for member of this class, this class being the
* type of the 'this' pointer used to access smember.
*/
void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
{
int result;
FuncDeclaration *f = sc->func;
AggregateDeclaration *cdscope = sc->getStructClassScope();
enum PROT access;
#if LOG
printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
toChars(), smember->toChars(),
f ? f->toChars() : NULL,
cdscope ? cdscope->toChars() : NULL);
#endif
Dsymbol *smemberparent = smember->toParent();
if (!smemberparent || !smemberparent->isAggregateDeclaration())
{
#if LOG
printf("not an aggregate member\n");
#endif
return; // then it is accessible
}
// BUG: should enable this check
//assert(smember->parent->isBaseOf(this, NULL));
if (smemberparent == this)
{ enum PROT access = smember->prot();
result = access >= PROTpublic ||
hasPrivateAccess(f) ||
isFriendOf(cdscope) ||
(access == PROTpackage && hasPackageAccess(sc, this));
#if LOG
printf("result1 = %d\n", result);
#endif
}
else if ((access = this->getAccess(smember)) >= PROTpublic)
{
result = 1;
#if LOG
printf("result2 = %d\n", result);
#endif
}
else if (access == PROTpackage && hasPackageAccess(sc, this))
{
result = 1;
#if LOG
printf("result3 = %d\n", result);
#endif
}
else
{
result = accessCheckX(smember, f, this, cdscope);
#if LOG
printf("result4 = %d\n", result);
#endif
}
if (!result)
{
error(loc, "member %s is not accessible", smember->toChars());
}
}
/****************************************
* Determine if this is the same or friend of cd.
*/
int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
{
#if LOG
printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null");
#endif
if (this == cd)
return 1;
// Friends if both are in the same module
//if (toParent() == cd->toParent())
if (cd && getModule() == cd->getModule())
{
#if LOG
printf("\tin same module\n");
#endif
return 1;
}
#if LOG
printf("\tnot friend\n");
#endif
return 0;
}
/****************************************
* Determine if scope sc has package level access to s.
*/
int hasPackageAccess(Scope *sc, Dsymbol *s)
{
#if LOG
printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
#endif
for (; s; s = s->parent)
{
if (s->isPackage() && !s->isModule())
break;
}
#if LOG
if (s)
printf("\tthis is in package '%s'\n", s->toChars());
#endif
if (s && s == sc->module->parent)
{
#if LOG
printf("\ts is in same package as sc\n");
#endif
return 1;
}
#if LOG
printf("\tno package access\n");
#endif
return 0;
}
/**********************************
* Determine if smember has access to private members of this declaration.
*/
int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
{
if (smember)
{ AggregateDeclaration *cd = NULL;
Dsymbol *smemberparent = smember->toParent();
if (smemberparent)
cd = smemberparent->isAggregateDeclaration();
#if LOG
printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
toChars(), smember->toChars());
#endif
if (this == cd) // smember is a member of this class
{
#if LOG
printf("\tyes 1\n");
#endif
return 1; // so we get private access
}
// If both are members of the same module, grant access
while (1)
{ Dsymbol *sp = smember->toParent();
if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
smember = sp;
else
break;
}
if (!cd && toParent() == smember->toParent())
{
#if LOG
printf("\tyes 2\n");
#endif
return 1;
}
if (!cd && getModule() == smember->getModule())
{
#if LOG
printf("\tyes 3\n");
#endif
return 1;
}
}
#if LOG
printf("\tno\n");
#endif
return 0;
}
/****************************************
* Check access to d for expression e.d
*/
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
{
#if LOG
if (e)
{ printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
printf("\te->type = %s\n", e->type->toChars());
}
else
{
//printf("accessCheck(%s)\n", d->toChars());
}
#endif
if (!e)
{
if (d->prot() == PROTprivate && d->getModule() != sc->module ||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
error(loc, "%s %s.%s is not accessible from %s",
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
}
else if (e->type->ty == Tclass)
{ // Do access check
ClassDeclaration *cd;
cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
#if 1
if (e->op == TOKsuper)
{ ClassDeclaration *cd2;
cd2 = sc->func->toParent()->isClassDeclaration();
if (cd2)
cd = cd2;
}
#endif
cd->accessCheck(loc, sc, d);
}
else if (e->type->ty == Tstruct)
{ // Do access check
StructDeclaration *cd;
cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
cd->accessCheck(loc, sc, d);
}
}

256
dmd/aggregate.h Normal file
View File

@@ -0,0 +1,256 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_AGGREGATE_H
#define DMD_AGGREGATE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct Identifier;
struct Type;
struct TypeFunction;
struct Expression;
struct FuncDeclaration;
struct CtorDeclaration;
struct DtorDeclaration;
struct InvariantDeclaration;
struct NewDeclaration;
struct DeleteDeclaration;
struct InterfaceDeclaration;
struct ClassInfoDeclaration;
struct VarDeclaration;
struct dt_t;
namespace llvm
{
class Type;
class Value;
class Constant;
}
struct AggregateDeclaration : ScopeDsymbol
{
Type *type;
unsigned storage_class;
enum PROT protection;
Type *handle; // 'this' type
unsigned structsize; // size of struct
unsigned alignsize; // size of struct for alignment purposes
unsigned structalign; // struct member alignment in effect
int hasUnions; // set if aggregate has overlapping fields
Array fields; // VarDeclaration fields
unsigned sizeok; // set when structsize contains valid data
// 0: no size
// 1: size is correct
// 2: cannot determine size; fwd referenced
int isdeprecated; // !=0 if deprecated
Scope *scope; // !=NULL means context to use
// Special member functions
InvariantDeclaration *inv; // invariant
NewDeclaration *aggNew; // allocator
DeleteDeclaration *aggDelete; // deallocator
#ifdef IN_GCC
Array methods; // flat list of all methods for debug information
#endif
AggregateDeclaration(Loc loc, Identifier *id);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
unsigned size(Loc loc);
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
Type *getType();
void addField(Scope *sc, VarDeclaration *v);
int isDeprecated(); // is aggregate deprecated?
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
// For access checking
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
int isFriendOf(AggregateDeclaration *cd);
int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class?
void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
enum PROT prot();
// Back end
Symbol *stag; // tag symbol for debug data
Symbol *sinit;
Symbol *toInitializer();
bool llvmInProgress;
llvm::Type* llvmType;
llvm::Value* llvmVtbl;
llvm::Constant* llvmInitZ;
virtual unsigned offsetToIndex(unsigned os); // converts a DMD field offsets to LLVM struct index
AggregateDeclaration *isAggregateDeclaration() { return this; }
};
struct AnonymousAggregateDeclaration : AggregateDeclaration
{
AnonymousAggregateDeclaration()
: AggregateDeclaration(0, NULL)
{
}
AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
};
struct StructDeclaration : AggregateDeclaration
{
int zeroInit; // !=0 if initialize with 0 fill
StructDeclaration(Loc loc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
char *kind();
void toDocBuffer(OutBuffer *buf);
PROT getAccess(Dsymbol *smember); // determine access to smember
void toObjFile(); // compile to .obj file
void toDt(dt_t **pdt);
void toDebug(); // to symbolic debug info
StructDeclaration *isStructDeclaration() { return this; }
};
struct UnionDeclaration : StructDeclaration
{
UnionDeclaration(Loc loc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
char *kind();
UnionDeclaration *isUnionDeclaration() { return this; }
};
struct BaseClass
{
Type *type; // (before semantic processing)
enum PROT protection; // protection for the base interface
ClassDeclaration *base;
int offset; // 'this' pointer offset
Array vtbl; // for interfaces: Array of FuncDeclaration's
// making up the vtbl[]
int baseInterfaces_dim;
BaseClass *baseInterfaces; // if BaseClass is an interface, these
// are a copy of the InterfaceDeclaration::interfaces
BaseClass();
BaseClass(Type *type, enum PROT protection);
int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance);
void copyBaseInterfaces(BaseClasses *);
};
#define CLASSINFO_SIZE (0x3C+12) // value of ClassInfo.size
struct ClassDeclaration : AggregateDeclaration
{
static ClassDeclaration *object;
static ClassDeclaration *classinfo;
ClassDeclaration *baseClass; // NULL only if this is Object
CtorDeclaration *ctor;
CtorDeclaration *defaultCtor; // default constructor
FuncDeclarations dtors; // Array of destructors
FuncDeclaration *staticCtor;
FuncDeclaration *staticDtor;
Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
BaseClasses baseclasses; // Array of BaseClass's; first is super,
// rest are Interface's
int interfaces_dim;
BaseClass **interfaces; // interfaces[interfaces_dim] for this class
// (does not include baseClass)
BaseClasses *vtblInterfaces; // array of base interfaces that have
// their own vtbl[]
ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
int com; // !=0 if this is a COM class
int isauto; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class
int isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this class is nested
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isBaseOf2(ClassDeclaration *cd);
#define OFFSET_RUNTIME 0x76543210
virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
Dsymbol *search(Loc, Identifier *ident, int flags);
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
void interfaceSemantic(Scope *sc);
int isNested();
int isCOMclass();
int isAbstract();
virtual int vtblOffset();
char *kind();
char *mangle();
void toDocBuffer(OutBuffer *buf);
PROT getAccess(Dsymbol *smember); // determine access to smember
void addLocalClass(ClassDeclarations *);
// Back end
void toObjFile(); // compile to .obj file
void toDebug();
unsigned baseVtblOffset(BaseClass *bc);
Symbol *toSymbol();
Symbol *toVtblSymbol();
void toDt(dt_t **pdt);
void toDt2(dt_t **pdt, ClassDeclaration *cd);
Symbol *vtblsym;
virtual unsigned offsetToIndex(unsigned os);
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
};
struct InterfaceDeclaration : ClassDeclaration
{
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int isBaseOf(ClassDeclaration *cd, int *poffset);
int isBaseOf(BaseClass *bc, int *poffset);
char *kind();
int vtblOffset();
void toObjFile(); // compile to .obj file
Symbol *toSymbol();
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
};
#endif /* DMD_AGGREGATE_H */

220
dmd/array.c Normal file
View File

@@ -0,0 +1,220 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#if _MSC_VER
#include <malloc.h>
#endif
#if IN_GCC
#include "gdc_alloca.h"
#endif
#if _WIN32
#include <windows.h>
#endif
#ifndef _WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <utime.h>
#endif
#include "port.h"
#include "root.h"
#include "dchar.h"
#include "mem.h"
/********************************* Array ****************************/
Array::Array()
{
data = NULL;
dim = 0;
allocdim = 0;
}
Array::~Array()
{
mem.free(data);
}
void Array::mark()
{ unsigned u;
mem.mark(data);
for (u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's?
}
void Array::reserve(unsigned nentries)
{
//printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
if (allocdim - dim < nentries)
{
allocdim = dim + nentries;
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
}
}
void Array::setDim(unsigned newdim)
{
if (dim < newdim)
{
reserve(newdim - dim);
}
dim = newdim;
}
void Array::fixDim()
{
if (dim != allocdim)
{ data = (void **)mem.realloc(data, dim * sizeof(*data));
allocdim = dim;
}
}
void Array::push(void *ptr)
{
reserve(1);
data[dim++] = ptr;
}
void *Array::pop()
{
return data[--dim];
}
void Array::shift(void *ptr)
{
reserve(1);
memmove(data + 1, data, dim * sizeof(*data));
data[0] = ptr;
dim++;
}
void Array::insert(unsigned index, void *ptr)
{
reserve(1);
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
data[index] = ptr;
dim++;
}
void Array::insert(unsigned index, Array *a)
{
if (a)
{ unsigned d;
d = a->dim;
reserve(d);
if (dim != index)
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
memcpy(data + index, a->data, d * sizeof(*data));
dim += d;
}
}
/***********************************
* Append array a to this array.
*/
void Array::append(Array *a)
{
insert(dim, a);
}
void Array::remove(unsigned i)
{
memmove(data + i, data + i + 1, (dim - i) * sizeof(data[0]));
dim--;
}
char *Array::toChars()
{
unsigned len;
unsigned u;
char **buf;
char *str;
char *p;
buf = (char **)alloca(dim * sizeof(char *));
len = 2;
for (u = 0; u < dim; u++)
{
buf[u] = ((Object *)data[u])->toChars();
len += strlen(buf[u]) + 1;
}
str = (char *)mem.malloc(len);
str[0] = '[';
p = str + 1;
for (u = 0; u < dim; u++)
{
if (u)
*p++ = ',';
len = strlen(buf[u]);
memcpy(p,buf[u],len);
p += len;
}
*p++ = ']';
*p = 0;
return str;
}
void Array::zero()
{
memset(data,0,dim * sizeof(data[0]));
}
void *Array::tos()
{
return dim ? data[dim - 1] : NULL;
}
int
#if _WIN32
__cdecl
#endif
Array_sort_compare(const void *x, const void *y)
{
Object *ox = *(Object **)x;
Object *oy = *(Object **)y;
return ox->compare(oy);
}
void Array::sort()
{
if (dim)
{
qsort(data, dim, sizeof(Object *), Array_sort_compare);
}
}
Array *Array::copy()
{
Array *a = new Array();
a->setDim(dim);
memcpy(a->data, data, dim * sizeof(void *));
return a;
}

51
dmd/arraytypes.h Normal file
View File

@@ -0,0 +1,51 @@
// Compiler implementation of the D programming language
// Copyright (c) 2006-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_ARRAYTYPES_H
#define DMD_ARRAYTYPES_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
struct Expression;
struct Statement;
struct BaseClass;
struct TemplateParameter;
struct FuncDeclaration;
struct Identifier;
struct Initializer;
struct TemplateParameters : Array { };
struct Expressions : Array { };
struct Statements : Array { };
struct BaseClasses : Array { };
struct ClassDeclarations : Array { };
struct Dsymbols : Array { };
struct Objects : Array { };
struct FuncDeclarations : Array { };
struct Arguments : Array { };
struct Identifiers : Array { };
struct Initializers : Array { };
#endif

117
dmd/artistic.txt Normal file
View File

@@ -0,0 +1,117 @@
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The source code and object code supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package.
7. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
8. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End

1249
dmd/attrib.c Normal file

File diff suppressed because it is too large Load Diff

165
dmd/attrib.h Normal file
View File

@@ -0,0 +1,165 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_ATTRIB_H
#define DMD_ATTRIB_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Expression;
struct Statement;
struct LabelDsymbol;
struct Initializer;
struct Module;
struct Condition;
#ifdef _DH
struct HdrGenState;
#endif
/**************************************************************/
struct AttribDeclaration : Dsymbol
{
Array *decl; // array of Dsymbol's
AttribDeclaration(Array *decl);
virtual Array *include(Scope *sc, ScopeDsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
void addComment(unsigned char *comment);
void emitComment(Scope *sc);
char *kind();
int oneMember(Dsymbol **ps);
int hasPointers();
void checkCtorConstInit();
void addLocalClass(ClassDeclarations *);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
AttribDeclaration *isAttribDeclaration() { return this; }
void toObjFile(); // compile to .obj file
};
struct StorageClassDeclaration: AttribDeclaration
{
unsigned stc;
StorageClassDeclaration(unsigned stc, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct LinkDeclaration : AttribDeclaration
{
enum LINK linkage;
LinkDeclaration(enum LINK p, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void semantic3(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *toChars();
};
struct ProtDeclaration : AttribDeclaration
{
enum PROT protection;
ProtDeclaration(enum PROT p, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct AlignDeclaration : AttribDeclaration
{
unsigned salign;
AlignDeclaration(unsigned sa, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct AnonDeclaration : AttribDeclaration
{
int isunion;
Scope *scope; // !=NULL means context to use
int sem; // 1 if successful semantic()
AnonDeclaration(Loc loc, int isunion, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
};
struct PragmaDeclaration : AttribDeclaration
{
Expressions *args; // array of Expression's
PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
void toObjFile(); // compile to .obj file
};
struct ConditionalDeclaration : AttribDeclaration
{
Condition *condition;
Array *elsedecl; // array of Dsymbol's for else block
ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int oneMember(Dsymbol **ps);
void emitComment(Scope *sc);
Array *include(Scope *sc, ScopeDsymbol *s);
void addComment(unsigned char *comment);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct StaticIfDeclaration : ConditionalDeclaration
{
ScopeDsymbol *sd;
int addisdone;
StaticIfDeclaration(Condition *condition, Array *decl, Array *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semantic(Scope *sc);
char *kind();
};
// Mixin declarations
struct CompileDeclaration : AttribDeclaration
{
Expression *exp;
ScopeDsymbol *sd;
CompileDeclaration(Loc loc, Expression *exp);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif /* DMD_ATTRIB_H */

1419
dmd/cast.c Normal file

File diff suppressed because it is too large Load Diff

1267
dmd/class.c Normal file

File diff suppressed because it is too large Load Diff

74
dmd/complex_t.h Normal file
View File

@@ -0,0 +1,74 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright and Burton Radons
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_COMPLEX_T_H
#define DMD_COMPLEX_T_H
/* Roll our own complex type for compilers that don't support complex
*/
struct complex_t
{
long double re;
long double im;
complex_t() { this->re = 0; this->im = 0; }
complex_t(long double re) { this->re = re; this->im = 0; }
complex_t(long double re, long double im) { this->re = re; this->im = im; }
complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; }
complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; }
complex_t operator - () { complex_t r; r.re = -re; r.im = -im; return r; }
complex_t operator * (complex_t y) { return complex_t(re * y.re - im * y.im, im * y.re + re * y.im); }
complex_t operator / (complex_t y)
{
long double abs_y_re = y.re < 0 ? -y.re : y.re;
long double abs_y_im = y.im < 0 ? -y.im : y.im;
long double r, den;
if (abs_y_re < abs_y_im)
{
r = y.re / y.im;
den = y.im + r * y.re;
return complex_t((re * r + im) / den,
(im * r - re) / den);
}
else
{
r = y.im / y.re;
den = y.re + r * y.im;
return complex_t((re + r * im) / den,
(im - r * re) / den);
}
}
operator bool () { return re || im; }
int operator == (complex_t y) { return re == y.re && im == y.im; }
int operator != (complex_t y) { return re != y.re || im != y.im; }
};
inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; }
inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); }
inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); }
inline long double creall(complex_t x)
{
return x.re;
}
inline long double cimagl(complex_t x)
{
return x.im;
}
#endif

390
dmd/cond.c Normal file
View File

@@ -0,0 +1,390 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "id.h"
#include "init.h"
#include "declaration.h"
#include "identifier.h"
#include "expression.h"
#include "cond.h"
#include "module.h"
#include "template.h"
#include "lexer.h"
#ifdef _DH
#include "mtype.h"
#include "scope.h"
#endif
int findCondition(Array *ids, Identifier *ident)
{
if (ids)
{
for (int i = 0; i < ids->dim; i++)
{
char *id = (char *)ids->data[i];
if (strcmp(id, ident->toChars()) == 0)
return TRUE;
}
}
return FALSE;
}
/* ============================================================ */
Condition::Condition(Loc loc)
{
this->loc = loc;
inc = 0;
}
/* ============================================================ */
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
: Condition(0)
{
this->mod = mod;
this->level = level;
this->ident = ident;
}
Condition *DVCondition::syntaxCopy()
{
return this; // don't need to copy
}
/* ============================================================ */
void DebugCondition::setGlobalLevel(unsigned level)
{
global.params.debuglevel = level;
}
void DebugCondition::addGlobalIdent(char *ident)
{
if (!global.params.debugids)
global.params.debugids = new Array();
global.params.debugids->push(ident);
}
DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
: DVCondition(mod, level, ident)
{
}
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
{
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
if (inc == 0)
{
inc = 2;
if (ident)
{
if (findCondition(mod->debugids, ident))
inc = 1;
else if (findCondition(global.params.debugids, ident))
inc = 1;
else
{ if (!mod->debugidsNot)
mod->debugidsNot = new Array();
mod->debugidsNot->push(ident->toChars());
}
}
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
inc = 1;
}
return (inc == 1);
}
void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (ident)
buf->printf("debug (%s)", ident->toChars());
else
buf->printf("debug (%u)", level);
}
/* ============================================================ */
void VersionCondition::setGlobalLevel(unsigned level)
{
global.params.versionlevel = level;
}
void VersionCondition::checkPredefined(Loc loc, char *ident)
{
static char* reserved[] =
{
"DigitalMars", "X86", "X86_64",
"Windows", "Win32", "Win64",
"linux",
"LittleEndian", "BigEndian",
"all",
"none",
};
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
{
if (strcmp(ident, reserved[i]) == 0)
goto Lerror;
}
if (ident[0] == 'D' && ident[1] == '_')
goto Lerror;
return;
Lerror:
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
}
void VersionCondition::addGlobalIdent(char *ident)
{
checkPredefined(0, ident);
addPredefinedGlobalIdent(ident);
}
void VersionCondition::addPredefinedGlobalIdent(char *ident)
{
if (!global.params.versionids)
global.params.versionids = new Array();
global.params.versionids->push(ident);
}
VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
: DVCondition(mod, level, ident)
{
}
int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
{
//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
//if (ident) printf("\tident = '%s'\n", ident->toChars());
if (inc == 0)
{
inc = 2;
if (ident)
{
if (findCondition(mod->versionids, ident))
inc = 1;
else if (findCondition(global.params.versionids, ident))
inc = 1;
else
{
if (!mod->versionidsNot)
mod->versionidsNot = new Array();
mod->versionidsNot->push(ident->toChars());
}
}
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
inc = 1;
}
return (inc == 1);
}
void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (ident)
buf->printf("version (%s)", ident->toChars());
else
buf->printf("version (%u)", level);
}
/**************************** StaticIfCondition *******************************/
StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
: Condition(loc)
{
this->exp = exp;
}
Condition *StaticIfCondition::syntaxCopy()
{
return new StaticIfCondition(loc, exp->syntaxCopy());
}
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
{
#if 0
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
if (s)
{
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
}
#endif
if (inc == 0)
{
if (!sc)
{
error(loc, "static if conditional cannot be at global scope");
inc = 2;
return 0;
}
sc = sc->push(sc->scopesym);
sc->sd = s; // s gets any addMember()
sc->flags |= SCOPEstaticif;
Expression *e = exp->semantic(sc);
sc->pop();
e = e->optimize(WANTvalue | WANTinterpret);
if (e->isBool(TRUE))
inc = 1;
else if (e->isBool(FALSE))
inc = 2;
else
{
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
inc = 2;
}
}
return (inc == 1);
}
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("static if(");
exp->toCBuffer(buf, hgs);
buf->writeByte(')');
}
/**************************** IftypeCondition *******************************/
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
: Condition(loc)
{
this->targ = targ;
this->id = id;
this->tok = tok;
this->tspec = tspec;
}
Condition *IftypeCondition::syntaxCopy()
{
return new IftypeCondition(loc,
targ->syntaxCopy(),
id,
tok,
tspec ? tspec->syntaxCopy() : NULL);
}
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
{
//printf("IftypeCondition::include()\n");
if (inc == 0)
{
if (!sc)
{
error(loc, "iftype conditional cannot be at global scope");
inc = 2;
return 0;
}
unsigned errors = global.errors;
global.gag++; // suppress printing of error messages
targ = targ->semantic(loc, sc);
global.gag--;
if (errors != global.errors) // if any errors happened
{ inc = 2; // then condition is false
global.errors = errors;
}
else if (id && tspec)
{
/* Evaluate to TRUE if targ matches tspec.
* If TRUE, declare id as an alias for the specialized type.
*/
MATCH m;
TemplateTypeParameter tp(loc, id, NULL, NULL);
TemplateParameters parameters;
parameters.setDim(1);
parameters.data[0] = (void *)&tp;
Objects dedtypes;
dedtypes.setDim(1);
m = targ->deduceType(NULL, tspec, &parameters, &dedtypes);
if (m == MATCHnomatch ||
(m != MATCHexact && tok == TOKequal))
inc = 2;
else
{
inc = 1;
Type *tded = (Type *)dedtypes.data[0];
if (!tded)
tded = targ;
Dsymbol *s = new AliasDeclaration(loc, id, tded);
s->semantic(sc);
sc->insert(s);
if (sd)
s->addMember(sc, sd, 1);
}
}
else if (id)
{
/* Declare id as an alias for type targ. Evaluate to TRUE
*/
Dsymbol *s = new AliasDeclaration(loc, id, targ);
s->semantic(sc);
sc->insert(s);
if (sd)
s->addMember(sc, sd, 1);
inc = 1;
}
else if (tspec)
{
/* Evaluate to TRUE if targ matches tspec
*/
tspec = tspec->semantic(loc, sc);
//printf("targ = %s\n", targ->toChars());
//printf("tspec = %s\n", tspec->toChars());
if (tok == TOKcolon)
{ if (targ->implicitConvTo(tspec))
inc = 1;
else
inc = 2;
}
else /* == */
{ if (targ->equals(tspec))
inc = 1;
else
inc = 2;
}
}
else
inc = 1;
//printf("inc = %d\n", inc);
}
return (inc == 1);
}
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("iftype(");
targ->toCBuffer(buf, id, hgs);
if (tspec)
{
if (tok == TOKcolon)
buf->writestring(" : ");
else
buf->writestring(" == ");
tspec->toCBuffer(buf, NULL, hgs);
}
buf->writeByte(')');
}

106
dmd/cond.h Normal file
View File

@@ -0,0 +1,106 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_DEBCOND_H
#define DMD_DEBCOND_H
struct Expression;
struct Identifier;
struct OutBuffer;
struct Module;
struct Scope;
struct ScopeDsymbol;
#ifdef _DH
#include "lexer.h" // dmdhg
#endif
enum TOK;
#ifdef _DH
struct HdrGenState;
#endif
int findCondition(Array *ids, Identifier *ident);
struct Condition
{
Loc loc;
int inc; // 0: not computed yet
// 1: include
// 2: do not include
Condition(Loc loc);
virtual Condition *syntaxCopy() = 0;
virtual int include(Scope *sc, ScopeDsymbol *s) = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
};
struct DVCondition : Condition
{
unsigned level;
Identifier *ident;
Module *mod;
DVCondition(Module *mod, unsigned level, Identifier *ident);
Condition *syntaxCopy();
};
struct DebugCondition : DVCondition
{
static void setGlobalLevel(unsigned level);
static void addGlobalIdent(char *ident);
static void addPredefinedGlobalIdent(char *ident);
DebugCondition(Module *mod, unsigned level, Identifier *ident);
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct VersionCondition : DVCondition
{
static void setGlobalLevel(unsigned level);
static void checkPredefined(Loc loc, char *ident);
static void addGlobalIdent(char *ident);
static void addPredefinedGlobalIdent(char *ident);
VersionCondition(Module *mod, unsigned level, Identifier *ident);
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct StaticIfCondition : Condition
{
Expression *exp;
StaticIfCondition(Loc loc, Expression *exp);
Condition *syntaxCopy();
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct IftypeCondition : Condition
{
/* iftype (targ id tok tspec)
*/
Type *targ;
Identifier *id; // can be NULL
enum TOK tok; // ':' or '=='
Type *tspec; // can be NULL
IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec);
Condition *syntaxCopy();
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif

1461
dmd/constfold.c Normal file

File diff suppressed because it is too large Load Diff

482
dmd/dchar.c Normal file
View File

@@ -0,0 +1,482 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "dchar.h"
#include "mem.h"
#if M_UNICODE
// Converts a char string to Unicode
dchar *Dchar::dup(char *p)
{
dchar *s;
size_t len;
if (!p)
return NULL;
len = strlen(p);
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
for (unsigned i = 0; i < len; i++)
{
s[i] = (dchar)(p[i] & 0xFF);
}
s[len] = 0;
return s;
}
dchar *Dchar::memchr(dchar *p, int c, int count)
{
int u;
for (u = 0; u < count; u++)
{
if (p[u] == c)
return p + u;
}
return NULL;
}
#if _WIN32 && __DMC__
__declspec(naked)
unsigned Dchar::calcHash(const dchar *str, unsigned len)
{
__asm
{
mov ECX,4[ESP]
mov EDX,8[ESP]
xor EAX,EAX
test EDX,EDX
je L92
LC8: cmp EDX,1
je L98
cmp EDX,2
je LAE
add EAX,[ECX]
// imul EAX,EAX,025h
lea EAX,[EAX][EAX*8]
add ECX,4
sub EDX,2
jmp LC8
L98: mov DX,[ECX]
and EDX,0FFFFh
add EAX,EDX
ret
LAE: add EAX,[ECX]
L92: ret
}
}
#else
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
unsigned hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str;
return hash;
case 2:
hash += *(const uint32_t *)str;
return hash;
default:
hash += *(const uint32_t *)str;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#endif
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str | 0x20;
return hash;
case 2:
hash += *(const uint32_t *)str | 0x200020;
return hash;
default:
hash += *(const uint32_t *)str | 0x200020;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#elif MCBS
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str;
return hash;
case 3:
hash *= 37;
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str;
str += 4;
len -= 4;
break;
}
}
}
#elif UTF8
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
char Dchar::mblen[256] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
};
dchar *Dchar::dec(dchar *pstart, dchar *p)
{
while ((p[-1] & 0xC0) == 0x80)
p--;
return p;
}
int Dchar::get(dchar *p)
{
unsigned c;
unsigned char *q = (unsigned char *)p;
c = q[0];
switch (mblen[c])
{
case 2:
c = ((c - 0xC0) << 6) |
(q[1] - 0x80);
break;
case 3:
c = ((c - 0xE0) << 12) |
((q[1] - 0x80) << 6) |
(q[2] - 0x80);
break;
case 4:
c = ((c - 0xF0) << 18) |
((q[1] - 0x80) << 12) |
((q[2] - 0x80) << 6) |
(q[3] - 0x80);
break;
case 5:
c = ((c - 0xF8) << 24) |
((q[1] - 0x80) << 18) |
((q[2] - 0x80) << 12) |
((q[3] - 0x80) << 6) |
(q[4] - 0x80);
break;
case 6:
c = ((c - 0xFC) << 30) |
((q[1] - 0x80) << 24) |
((q[2] - 0x80) << 18) |
((q[3] - 0x80) << 12) |
((q[4] - 0x80) << 6) |
(q[5] - 0x80);
break;
}
return c;
}
dchar *Dchar::put(dchar *p, unsigned c)
{
if (c <= 0x7F)
{
*p++ = c;
}
else if (c <= 0x7FF)
{
p[0] = 0xC0 + (c >> 6);
p[1] = 0x80 + (c & 0x3F);
p += 2;
}
else if (c <= 0xFFFF)
{
p[0] = 0xE0 + (c >> 12);
p[1] = 0x80 + ((c >> 6) & 0x3F);
p[2] = 0x80 + (c & 0x3F);
p += 3;
}
else if (c <= 0x1FFFFF)
{
p[0] = 0xF0 + (c >> 18);
p[1] = 0x80 + ((c >> 12) & 0x3F);
p[2] = 0x80 + ((c >> 6) & 0x3F);
p[3] = 0x80 + (c & 0x3F);
p += 4;
}
else if (c <= 0x3FFFFFF)
{
p[0] = 0xF8 + (c >> 24);
p[1] = 0x80 + ((c >> 18) & 0x3F);
p[2] = 0x80 + ((c >> 12) & 0x3F);
p[3] = 0x80 + ((c >> 6) & 0x3F);
p[4] = 0x80 + (c & 0x3F);
p += 5;
}
else if (c <= 0x7FFFFFFF)
{
p[0] = 0xFC + (c >> 30);
p[1] = 0x80 + ((c >> 24) & 0x3F);
p[2] = 0x80 + ((c >> 18) & 0x3F);
p[3] = 0x80 + ((c >> 12) & 0x3F);
p[4] = 0x80 + ((c >> 6) & 0x3F);
p[5] = 0x80 + (c & 0x3F);
p += 6;
}
else
assert(0); // not a UCS-4 character
return p;
}
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if __I86__
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if __I86__
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if __I86__
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
#else // ascii
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if __I86__
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if __I86__
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if __I86__
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str | 0x20;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str | 0x2020;
return hash;
case 3:
hash *= 37;
hash += ((*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]) | 0x202020;
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str | 0x20202020;
str += 4;
len -= 4;
break;
}
}
}
#endif
#if 0
#include <stdio.h>
void main()
{
// Print out values to hardcode into Dchar::mblen[]
int c;
int s;
for (c = 0; c < 256; c++)
{
s = 1;
if (c >= 0xC0 && c <= 0xDF)
s = 2;
if (c >= 0xE0 && c <= 0xEF)
s = 3;
if (c >= 0xF0 && c <= 0xF7)
s = 4;
if (c >= 0xF8 && c <= 0xFB)
s = 5;
if (c >= 0xFC && c <= 0xFD)
s = 6;
printf("%d", s);
if ((c & 15) == 15)
printf(",\n");
else
printf(",");
}
}
#endif

194
dmd/dchar.h Normal file
View File

@@ -0,0 +1,194 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DCHAR_H
#define DCHAR_H
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#endif
#if _MSC_VER
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
#endif
//#include "root.h"
typedef size_t hash_t;
#undef TEXT
// NOTE: All functions accepting pointer arguments must not be NULL
#if M_UNICODE
#include <string.h>
#include <wchar.h>
typedef wchar_t dchar;
#define TEXT(x) L##x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return wcslen(p); }
static dchar get(dchar *p) { return *p; }
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2)
{
#if __DMC__
if (!*s1 && !*s2) // wcscmp is broken
return 0;
#endif
return wcscmp(s1, s2);
#if 0
return (*s1 == *s2)
? wcscmp(s1, s2)
: ((int)*s1 - (int)*s2);
#endif
}
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return iswalpha(c); }
static int isUpper(dchar c) { return iswupper(c); }
static int isLower(dchar c) { return iswlower(c); }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
static dchar *dup(char *p);
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
static dchar *memchr(dchar *p, int c, int count);
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#elif MCBS
#include <limits.h>
#include <mbstring.h>
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax MB_LEN_MAX
#elif UTF8
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 6
struct Dchar
{
static char mblen[256];
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
static dchar *dec(dchar *pstart, dchar *p);
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p);
static int getprev(dchar *pstart, dchar *p)
{ return *dec(pstart, p) & 0xFF; }
static dchar *put(dchar *p, unsigned c);
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
};
#else
#include <string.h>
#ifndef GCC_SAFE_DMD
#include <ctype.h>
#endif
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p) { return *p & 0xFF; }
static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
#ifndef GCC_SAFE_DMD
static int isAlpha(dchar c) { return isalpha(c); }
static int isUpper(dchar c) { return isupper(c); }
static int isLower(dchar c) { return islower(c); }
static int isLocaleUpper(dchar c) { return isupper(c); }
static int isLocaleLower(dchar c) { return islower(c); }
static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
#endif
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
#ifdef __GNUC__
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
#else
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
#endif
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#endif
#endif

1260
dmd/declaration.c Normal file

File diff suppressed because it is too large Load Diff

670
dmd/declaration.h Normal file
View File

@@ -0,0 +1,670 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_DECLARATION_H
#define DMD_DECLARATION_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
#include "lexer.h"
#include "mtype.h"
namespace llvm {
class Value;
}
struct Expression;
struct Statement;
struct LabelDsymbol;
struct Initializer;
struct Module;
struct InlineScanState;
struct ForeachStatement;
struct FuncDeclaration;
struct ExpInitializer;
struct StructDeclaration;
struct TupleType;
struct InterState;
enum PROT;
enum LINK;
enum TOK;
enum MATCH;
enum STC
{
STCundefined = 0,
STCstatic = 1,
STCextern = 2,
STCconst = 4,
STCfinal = 8,
STCabstract = 0x10,
STCparameter = 0x20,
STCfield = 0x40,
STCoverride = 0x80,
STCauto = 0x100,
STCsynchronized = 0x200,
STCdeprecated = 0x400,
STCin = 0x800, // in parameter
STCout = 0x1000, // out parameter
STClazy = 0x2000, // lazy parameter
STCforeach = 0x4000, // variable for foreach loop
STCcomdat = 0x8000, // should go into COMDAT record
STCvariadic = 0x10000, // variadic function argument
STCctorinit = 0x20000, // can only be set inside constructor
STCtemplateparameter = 0x40000, // template parameter
STCscope = 0x80000, // template parameter
STCinvariant = 0x100000,
STCref = 0x200000,
};
struct Match
{
int count; // number of matches found
MATCH last; // match level of lastf
FuncDeclaration *lastf; // last matching function we found
FuncDeclaration *nextf; // current matching function
FuncDeclaration *anyf; // pick a func, any func, to use for error recovery
};
void overloadResolveX(Match *m, FuncDeclaration *f, Expressions *arguments);
int overloadApply(FuncDeclaration *fstart,
int (*fp)(void *, FuncDeclaration *),
void *param);
/**************************************************************/
struct Declaration : Dsymbol
{
Type *type;
unsigned storage_class;
enum PROT protection;
enum LINK linkage;
Declaration(Identifier *id);
void semantic(Scope *sc);
char *kind();
unsigned size(Loc loc);
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
char *mangle();
int isStatic() { return storage_class & STCstatic; }
virtual int isStaticConstructor();
virtual int isStaticDestructor();
virtual int isDelete();
virtual int isDataseg();
virtual int isCodeseg();
int isCtorinit() { return storage_class & STCctorinit; }
int isFinal() { return storage_class & STCfinal; }
int isAbstract() { return storage_class & STCabstract; }
int isConst() { return storage_class & STCconst; }
int isAuto() { return storage_class & STCauto; }
int isScope() { return storage_class & (STCscope | STCauto); }
int isSynchronized() { return storage_class & STCsynchronized; }
int isParameter() { return storage_class & STCparameter; }
int isDeprecated() { return storage_class & STCdeprecated; }
int isOverride() { return storage_class & STCoverride; }
int isIn() { return storage_class & STCin; }
int isOut() { return storage_class & STCout; }
int isRef() { return storage_class & STCref; }
enum PROT prot();
Declaration *isDeclaration() { return this; }
virtual void toObjFile(); // compile to .obj file
// llvm stuff
llvm::Value* llvmValue;
};
/**************************************************************/
struct TupleDeclaration : Declaration
{
Objects *objects;
int isexp; // 1: expression tuple
TypeTuple *tupletype; // !=NULL if this is a type tuple
TupleDeclaration(Loc loc, Identifier *ident, Objects *objects);
Dsymbol *syntaxCopy(Dsymbol *);
char *kind();
Type *getType();
int needThis();
TupleDeclaration *isTupleDeclaration() { return this; }
};
/**************************************************************/
struct TypedefDeclaration : Declaration
{
Type *basetype;
Initializer *init;
int sem; // 0: semantic() has not been run
// 1: semantic() is in progress
// 2: semantic() has been run
// 3: semantic2() has been run
int inuse; // used to detect typedef cycles
TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void semantic2(Scope *sc);
char *mangle();
char *kind();
Type *getType();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#ifdef _DH
Type *htype;
Type *hbasetype;
#endif
void toDocBuffer(OutBuffer *buf);
void toObjFile(); // compile to .obj file
void toDebug();
int cvMember(unsigned char *p);
TypedefDeclaration *isTypedefDeclaration() { return this; }
Symbol *sinit;
Symbol *toInitializer();
};
/**************************************************************/
struct AliasDeclaration : Declaration
{
Dsymbol *aliassym;
Dsymbol *overnext; // next in overload list
int inSemantic;
AliasDeclaration(Loc loc, Identifier *ident, Type *type);
AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
int overloadInsert(Dsymbol *s);
char *kind();
Type *getType();
Dsymbol *toAlias();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#ifdef _DH
Type *htype;
Dsymbol *haliassym;
#endif
void toDocBuffer(OutBuffer *buf);
AliasDeclaration *isAliasDeclaration() { return this; }
};
/**************************************************************/
struct VarDeclaration : Declaration
{
Initializer *init;
unsigned offset;
int noauto; // no auto semantics
int nestedref; // referenced by a lexically nested function
int inuse;
int ctorinit; // it has been initialized in a ctor
int onstack; // 1: it has been allocated on the stack
// 2: on stack, run destructor anyway
int canassign; // it can be assigned to
Dsymbol *aliassym; // if redone as alias to another symbol
Expression *value; // when interpreting, this is the value
// (NULL if value not determinable)
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void semantic2(Scope *sc);
char *kind();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#ifdef _DH
Type *htype;
Initializer *hinit;
#endif
int needThis();
int isImportedSymbol();
int isDataseg();
int hasPointers();
Expression *callAutoDtor();
ExpInitializer *getExpInitializer();
void checkCtorConstInit();
void checkNestedReference(Scope *sc, Loc loc);
Dsymbol *toAlias();
Symbol *toSymbol();
void toObjFile(); // compile to .obj file
int cvMember(unsigned char *p);
// Eliminate need for dynamic_cast
VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
};
/**************************************************************/
// This is a shell around a back end symbol
struct SymbolDeclaration : Declaration
{
Symbol *sym;
StructDeclaration *dsym;
SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym);
Symbol *toSymbol();
// Eliminate need for dynamic_cast
SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; }
};
struct ClassInfoDeclaration : VarDeclaration
{
ClassDeclaration *cd;
ClassInfoDeclaration(ClassDeclaration *cd);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void emitComment(Scope *sc);
Symbol *toSymbol();
};
struct ModuleInfoDeclaration : VarDeclaration
{
Module *mod;
ModuleInfoDeclaration(Module *mod);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void emitComment(Scope *sc);
Symbol *toSymbol();
};
struct TypeInfoDeclaration : VarDeclaration
{
Type *tinfo;
TypeInfoDeclaration(Type *tinfo, int internal);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void emitComment(Scope *sc);
Symbol *toSymbol();
void toObjFile(); // compile to .obj file
virtual void toDt(dt_t **pdt);
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; }
};
struct TypeInfoStructDeclaration : TypeInfoDeclaration
{
TypeInfoStructDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoClassDeclaration : TypeInfoDeclaration
{
TypeInfoClassDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration
{
TypeInfoInterfaceDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoTypedefDeclaration : TypeInfoDeclaration
{
TypeInfoTypedefDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoPointerDeclaration : TypeInfoDeclaration
{
TypeInfoPointerDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoArrayDeclaration : TypeInfoDeclaration
{
TypeInfoArrayDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
{
TypeInfoStaticArrayDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
{
TypeInfoAssociativeArrayDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoEnumDeclaration : TypeInfoDeclaration
{
TypeInfoEnumDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoFunctionDeclaration : TypeInfoDeclaration
{
TypeInfoFunctionDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoDelegateDeclaration : TypeInfoDeclaration
{
TypeInfoDelegateDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct TypeInfoTupleDeclaration : TypeInfoDeclaration
{
TypeInfoTupleDeclaration(Type *tinfo);
void toDt(dt_t **pdt);
};
struct ThisDeclaration : VarDeclaration
{
ThisDeclaration(Type *t);
Dsymbol *syntaxCopy(Dsymbol *);
};
enum ILS
{
ILSuninitialized, // not computed yet
ILSno, // cannot inline
ILSyes, // can inline
};
/**************************************************************/
struct FuncDeclaration : Declaration
{
Array *fthrows; // Array of Type's of exceptions (not used)
Statement *frequire;
Statement *fensure;
Statement *fbody;
Identifier *outId; // identifier for out statement
VarDeclaration *vresult; // variable corresponding to outId
LabelDsymbol *returnLabel; // where the return goes
DsymbolTable *localsymtab; // used to prevent symbols in different
// scopes from having the same name
VarDeclaration *vthis; // 'this' parameter (member and nested)
VarDeclaration *v_arguments; // '_arguments' parameter
#if IN_GCC
VarDeclaration *v_argptr; // '_argptr' variable
#endif
Dsymbols *parameters; // Array of VarDeclaration's for parameters
DsymbolTable *labtab; // statement label symbol table
Declaration *overnext; // next in overload list
Loc endloc; // location of closing curly bracket
int vtblIndex; // for member functions, index into vtbl[]
int naked; // !=0 if naked
int inlineAsm; // !=0 if has inline assembler
ILS inlineStatus;
int inlineNest; // !=0 if nested inline
int cantInterpret; // !=0 if cannot interpret function
int semanticRun; // !=0 if semantic3() had been run
int nestedFrameRef; // !=0 if nested variables referenced frame ptr
ForeachStatement *fes; // if foreach body, this is the foreach
int introducing; // !=0 if 'introducing' function
Type *tintro; // if !=NULL, then this is the type
// of the 'introducing' function
// this one is overriding
int inferRetType; // !=0 if return type is to be inferred
Scope *scope; // !=NULL means context to use
// Things that should really go into Scope
int hasReturnExp; // 1 if there's a return exp; statement
// 2 if there's a throw statement
// 4 if there's an assert(0)
// 8 if there's inline asm
// Support for NRVO (named return value optimization)
int nrvo_can; // !=0 means we can do it
VarDeclaration *nrvo_var; // variable to replace with shidden
Symbol *shidden; // hidden pointer passed to function
FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
int overrides(FuncDeclaration *fd);
int overloadInsert(Dsymbol *s);
FuncDeclaration *overloadExactMatch(Type *t);
FuncDeclaration *overloadResolve(Loc loc, Expressions *arguments);
LabelDsymbol *searchLabel(Identifier *ident);
AggregateDeclaration *isThis();
AggregateDeclaration *isMember2();
int getLevel(Loc loc, FuncDeclaration *fd); // lexical nesting level difference
void appendExp(Expression *e);
void appendState(Statement *s);
char *mangle();
int isMain();
int isWinMain();
int isDllMain();
int isExport();
int isImportedSymbol();
int isAbstract();
int isCodeseg();
virtual int isNested();
int needThis();
virtual int isVirtual();
virtual int addPreInvariant();
virtual int addPostInvariant();
Expression *interpret(InterState *istate, Expressions *arguments);
void inlineScan();
int canInline(int hasthis, int hdrscan = 0);
Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
char *kind();
void toDocBuffer(OutBuffer *buf);
static FuncDeclaration *genCfunc(Type *treturn, char *name);
static FuncDeclaration *genCfunc(Type *treturn, Identifier *id);
Symbol *toSymbol();
Symbol *toThunkSymbol(int offset); // thunk version
void toObjFile(); // compile to .obj file
int cvMember(unsigned char *p);
FuncDeclaration *isFuncDeclaration() { return this; }
};
struct FuncAliasDeclaration : FuncDeclaration
{
FuncDeclaration *funcalias;
FuncAliasDeclaration(FuncDeclaration *funcalias);
FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
char *kind();
Symbol *toSymbol();
};
struct FuncLiteralDeclaration : FuncDeclaration
{
enum TOK tok; // TOKfunction or TOKdelegate
FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
ForeachStatement *fes);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Dsymbol *syntaxCopy(Dsymbol *);
int isNested();
FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
char *kind();
};
struct CtorDeclaration : FuncDeclaration
{ Arguments *arguments;
int varargs;
CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
char *toChars();
int isVirtual();
int addPreInvariant();
int addPostInvariant();
void toDocBuffer(OutBuffer *buf);
CtorDeclaration *isCtorDeclaration() { return this; }
};
struct DtorDeclaration : FuncDeclaration
{
DtorDeclaration(Loc loc, Loc endloc);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isVirtual();
int addPreInvariant();
int addPostInvariant();
int overloadInsert(Dsymbol *s);
void emitComment(Scope *sc);
DtorDeclaration *isDtorDeclaration() { return this; }
};
struct StaticCtorDeclaration : FuncDeclaration
{
StaticCtorDeclaration(Loc loc, Loc endloc);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
AggregateDeclaration *isThis();
int isStaticConstructor();
int isVirtual();
int addPreInvariant();
int addPostInvariant();
void emitComment(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
};
struct StaticDtorDeclaration : FuncDeclaration
{
StaticDtorDeclaration(Loc loc, Loc endloc);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
AggregateDeclaration *isThis();
int isStaticDestructor();
int isVirtual();
int addPreInvariant();
int addPostInvariant();
void emitComment(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
};
struct InvariantDeclaration : FuncDeclaration
{
InvariantDeclaration(Loc loc, Loc endloc);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
int isVirtual();
int addPreInvariant();
int addPostInvariant();
void emitComment(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
InvariantDeclaration *isInvariantDeclaration() { return this; }
};
struct UnitTestDeclaration : FuncDeclaration
{
UnitTestDeclaration(Loc loc, Loc endloc);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
AggregateDeclaration *isThis();
int isVirtual();
int addPreInvariant();
int addPostInvariant();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
UnitTestDeclaration *isUnitTestDeclaration() { return this; }
};
struct NewDeclaration : FuncDeclaration
{ Arguments *arguments;
int varargs;
NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
int isVirtual();
int addPreInvariant();
int addPostInvariant();
NewDeclaration *isNewDeclaration() { return this; }
};
struct DeleteDeclaration : FuncDeclaration
{ Arguments *arguments;
DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
int isDelete();
int isVirtual();
int addPreInvariant();
int addPostInvariant();
#ifdef _DH
DeleteDeclaration *isDeleteDeclaration() { return this; }
#endif
};
#endif /* DMD_DECLARATION_H */

214
dmd/delegatize.c Normal file
View File

@@ -0,0 +1,214 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "mars.h"
#include "expression.h"
#include "statement.h"
#include "mtype.h"
#include "utf.h"
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
/********************************************
* Convert from expression to delegate that returns the expression,
* i.e. convert:
* expr
* to:
* t delegate() { return expr; }
*/
Expression *Expression::toDelegate(Scope *sc, Type *t)
{
//printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars());
TypeFunction *tf = new TypeFunction(NULL, t, 0, LINKd);
FuncLiteralDeclaration *fld =
new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL);
Expression *e;
#if 1
sc = sc->push();
sc->parent = fld; // set current function to be the delegate
e = this;
e->scanForNestedRef(sc);
sc = sc->pop();
#else
e = this->syntaxCopy();
#endif
Statement *s = new ReturnStatement(loc, e);
fld->fbody = s;
e = new FuncExp(loc, fld);
e = e->semantic(sc);
return e;
}
/******************************
* Perform scanForNestedRef() on an array of Expressions.
*/
void arrayExpressionScanForNestedRef(Scope *sc, Expressions *a)
{
//printf("arrayExpressionScanForNestedRef(%p)\n", a);
if (a)
{
for (int i = 0; i < a->dim; i++)
{ Expression *e = (Expression *)a->data[i];
if (e)
{
e->scanForNestedRef(sc);
}
}
}
}
void Expression::scanForNestedRef(Scope *sc)
{
//printf("Expression::scanForNestedRef(%s)\n", toChars());
}
void SymOffExp::scanForNestedRef(Scope *sc)
{
//printf("SymOffExp::scanForNestedRef(%s)\n", toChars());
VarDeclaration *v = var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
}
void VarExp::scanForNestedRef(Scope *sc)
{
//printf("VarExp::scanForNestedRef(%s)\n", toChars());
VarDeclaration *v = var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
}
void ThisExp::scanForNestedRef(Scope *sc)
{
assert(var);
var->isVarDeclaration()->checkNestedReference(sc, 0);
}
void SuperExp::scanForNestedRef(Scope *sc)
{
ThisExp::scanForNestedRef(sc);
}
void FuncExp::scanForNestedRef(Scope *sc)
{
//printf("FuncExp::scanForNestedRef(%s)\n", toChars());
//fd->parent = sc->parent;
}
void DeclarationExp::scanForNestedRef(Scope *sc)
{
//printf("DeclarationExp::scanForNestedRef() %s\n", toChars());
declaration->parent = sc->parent;
}
void NewExp::scanForNestedRef(Scope *sc)
{
//printf("NewExp::scanForNestedRef(Scope *sc): %s\n", toChars());
if (thisexp)
thisexp->scanForNestedRef(sc);
arrayExpressionScanForNestedRef(sc, newargs);
arrayExpressionScanForNestedRef(sc, arguments);
}
void UnaExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
}
void BinExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
e2->scanForNestedRef(sc);
}
void CallExp::scanForNestedRef(Scope *sc)
{
//printf("CallExp::scanForNestedRef(Scope *sc): %s\n", toChars());
e1->scanForNestedRef(sc);
arrayExpressionScanForNestedRef(sc, arguments);
}
void IndexExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
if (lengthVar)
{ //printf("lengthVar\n");
lengthVar->parent = sc->parent;
}
e2->scanForNestedRef(sc);
}
void SliceExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
if (lengthVar)
{ //printf("lengthVar\n");
lengthVar->parent = sc->parent;
}
if (lwr)
lwr->scanForNestedRef(sc);
if (upr)
upr->scanForNestedRef(sc);
}
void ArrayLiteralExp::scanForNestedRef(Scope *sc)
{
arrayExpressionScanForNestedRef(sc, elements);
}
void AssocArrayLiteralExp::scanForNestedRef(Scope *sc)
{
arrayExpressionScanForNestedRef(sc, keys);
arrayExpressionScanForNestedRef(sc, values);
}
void StructLiteralExp::scanForNestedRef(Scope *sc)
{
arrayExpressionScanForNestedRef(sc, elements);
}
void TupleExp::scanForNestedRef(Scope *sc)
{
arrayExpressionScanForNestedRef(sc, exps);
}
void ArrayExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
arrayExpressionScanForNestedRef(sc, arguments);
}
void CondExp::scanForNestedRef(Scope *sc)
{
econd->scanForNestedRef(sc);
e1->scanForNestedRef(sc);
e2->scanForNestedRef(sc);
}

1925
dmd/doc.c Normal file

File diff suppressed because it is too large Load Diff

19
dmd/doc.h Normal file
View File

@@ -0,0 +1,19 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_DOC_H
#define DMD_DOC_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#endif

971
dmd/dsymbol.c Normal file
View File

@@ -0,0 +1,971 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "mem.h"
#include "mars.h"
#include "dsymbol.h"
#include "aggregate.h"
#include "identifier.h"
#include "module.h"
#include "mtype.h"
#include "expression.h"
#include "statement.h"
#include "declaration.h"
#include "id.h"
#include "scope.h"
#include "init.h"
#include "import.h"
#include "template.h"
#include "../gen/enums.h"
/****************************** Dsymbol ******************************/
Dsymbol::Dsymbol()
{
//printf("Dsymbol::Dsymbol(%p)\n", this);
this->ident = NULL;
this->c_ident = NULL;
this->parent = NULL;
this->csym = NULL;
this->isym = NULL;
this->loc = 0;
this->comment = NULL;
this->llvmInternal = LLVMnone;
this->llvmInternal1 = NULL;
this->llvmInternal2 = NULL;
this->llvmValue = NULL;
}
Dsymbol::Dsymbol(Identifier *ident)
{
//printf("Dsymbol::Dsymbol(%p, ident)\n", this);
this->ident = ident;
this->c_ident = NULL;
this->parent = NULL;
this->csym = NULL;
this->isym = NULL;
this->loc = 0;
this->comment = NULL;
this->llvmInternal = LLVMnone;
this->llvmInternal1 = NULL;
this->llvmInternal2 = NULL;
this->llvmValue = NULL;
this->llvmDModule = NULL;
}
int Dsymbol::equals(Object *o)
{ Dsymbol *s;
if (this == o)
return TRUE;
s = (Dsymbol *)(o);
if (s && ident->equals(s->ident))
return TRUE;
return FALSE;
}
/**************************************
* Copy the syntax.
* Used for template instantiations.
* If s is NULL, allocate the new object, otherwise fill it in.
*/
Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
{
print();
printf("%s %s\n", kind(), toChars());
assert(0);
return NULL;
}
/**************************************
* Determine if this symbol is only one.
* Returns:
* FALSE, *ps = NULL: There are 2 or more symbols
* TRUE, *ps = NULL: There are zero symbols
* TRUE, *ps = symbol: The one and only one symbol
*/
int Dsymbol::oneMember(Dsymbol **ps)
{
//printf("Dsymbol::oneMember()\n");
*ps = this;
return TRUE;
}
/*****************************************
* Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
*/
int Dsymbol::oneMembers(Array *members, Dsymbol **ps)
{
//printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
Dsymbol *s = NULL;
if (members)
{
for (int i = 0; i < members->dim; i++)
{ Dsymbol *sx = (Dsymbol *)members->data[i];
int x = sx->oneMember(ps);
//printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
if (!x)
{
//printf("\tfalse 1\n");
assert(*ps == NULL);
return FALSE;
}
if (*ps)
{
if (s) // more than one symbol
{ *ps = NULL;
//printf("\tfalse 2\n");
return FALSE;
}
s = *ps;
}
}
}
*ps = s; // s is the one symbol, NULL if none
//printf("\ttrue\n");
return TRUE;
}
/*****************************************
* Is Dsymbol a variable that contains pointers?
*/
int Dsymbol::hasPointers()
{
//printf("Dsymbol::hasPointers() %s\n", toChars());
return 0;
}
char *Dsymbol::toChars()
{
return ident ? ident->toChars() : (char *)"__anonymous";
}
char *Dsymbol::toPrettyChars()
{ Dsymbol *p;
char *s;
char *q;
size_t len;
//printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
if (!parent)
return toChars();
len = 0;
for (p = this; p; p = p->parent)
len += strlen(p->toChars()) + 1;
s = (char *)mem.malloc(len);
q = s + len - 1;
*q = 0;
for (p = this; p; p = p->parent)
{
char *t = p->toChars();
len = strlen(t);
q -= len;
memcpy(q, t, len);
if (q == s)
break;
q--;
*q = '.';
}
return s;
}
char *Dsymbol::locToChars()
{
OutBuffer buf;
char *p;
Module *m = getModule();
if (m && m->srcfile)
loc.filename = m->srcfile->toChars();
return loc.toChars();
}
char *Dsymbol::kind()
{
return "symbol";
}
/*********************************
* If this symbol is really an alias for another,
* return that other.
*/
Dsymbol *Dsymbol::toAlias()
{
return this;
}
Dsymbol *Dsymbol::toParent()
{
return parent ? parent->pastMixin() : NULL;
}
Dsymbol *Dsymbol::pastMixin()
{
Dsymbol *s = this;
//printf("Dsymbol::pastMixin() %s\n", toChars());
while (s && s->isTemplateMixin())
s = s->parent;
return s;
}
/**********************************
* Use this instead of toParent() when looking for the
* 'this' pointer of the enclosing function/class.
*/
Dsymbol *Dsymbol::toParent2()
{
Dsymbol *s = parent;
while (s && s->isTemplateInstance())
s = s->parent;
return s;
}
int Dsymbol::isAnonymous()
{
return ident ? 0 : 1;
}
void Dsymbol::semantic(Scope *sc)
{
error("%p has no semantic routine", this);
}
void Dsymbol::semantic2(Scope *sc)
{
// Most Dsymbols have no further semantic analysis needed
}
void Dsymbol::semantic3(Scope *sc)
{
// Most Dsymbols have no further semantic analysis needed
}
void Dsymbol::inlineScan()
{
// Most Dsymbols have no further semantic analysis needed
}
Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
{
//printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
return NULL;
}
/***************************************
* Search for identifier id as a member of 'this'.
* id may be a template instance.
* Returns:
* symbol found, NULL if not
*/
Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
{
//printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
Dsymbol *s = toAlias();
Dsymbol *sm;
switch (id->dyncast())
{
case DYNCAST_IDENTIFIER:
sm = s->search(loc, id, 0);
break;
case DYNCAST_DSYMBOL:
{ // It's a template instance
//printf("\ttemplate instance id\n");
Dsymbol *st = (Dsymbol *)id;
TemplateInstance *ti = st->isTemplateInstance();
id = ti->name;
sm = s->search(loc, id, 0);
if (!sm)
{ error("template identifier %s is not a member of %s %s",
id->toChars(), s->kind(), s->toChars());
return NULL;
}
sm = sm->toAlias();
TemplateDeclaration *td = sm->isTemplateDeclaration();
if (!td)
{
error("%s is not a template, it is a %s", id->toChars(), sm->kind());
return NULL;
}
ti->tempdecl = td;
if (!ti->semanticdone)
ti->semantic(sc);
sm = ti->toAlias();
break;
}
default:
assert(0);
}
return sm;
}
int Dsymbol::overloadInsert(Dsymbol *s)
{
//printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
return FALSE;
}
void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring(toChars());
}
unsigned Dsymbol::size(Loc loc)
{
error("Dsymbol '%s' has no size\n", toChars());
return 0;
}
int Dsymbol::isforwardRef()
{
return FALSE;
}
AggregateDeclaration *Dsymbol::isThis()
{
return NULL;
}
ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class?
{
Dsymbol *parent = toParent();
if (parent && parent->isClassDeclaration())
return (ClassDeclaration *)parent;
return NULL;
}
void Dsymbol::defineRef(Dsymbol *s)
{
assert(0);
}
int Dsymbol::isExport()
{
return FALSE;
}
int Dsymbol::isImportedSymbol()
{
return FALSE;
}
int Dsymbol::isDeprecated()
{
return FALSE;
}
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
{
return NULL;
}
AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration?
{
Dsymbol *parent = toParent();
return parent ? parent->isAggregateDeclaration() : NULL;
}
Type *Dsymbol::getType()
{
return NULL;
}
int Dsymbol::needThis()
{
return FALSE;
}
int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
//printf("Dsymbol::addMember('%s')\n", toChars());
//printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars());
//printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab);
parent = sd;
if (!isAnonymous()) // no name, so can't add it to symbol table
{
if (!sd->symtab->insert(this)) // if name is already defined
{
Dsymbol *s2;
s2 = sd->symtab->lookup(ident);
if (!s2->overloadInsert(this))
{
sd->multiplyDefined(0, this, s2);
}
}
if (sd->isAggregateDeclaration() || sd->isEnumDeclaration())
{
if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof)
error(".%s property cannot be redefined", ident->toChars());
}
return 1;
}
return 0;
}
void Dsymbol::error(const char *format, ...)
{
//printf("Dsymbol::error()\n");
if (!global.gag)
{
char *p = locToChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
if (isAnonymous())
fprintf(stdmsg, "%s ", kind());
else
fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
va_list ap;
va_start(ap, format);
vfprintf(stdmsg, format, ap);
va_end(ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
}
global.errors++;
//fatal();
}
void Dsymbol::error(Loc loc, const char *format, ...)
{
if (!global.gag)
{
char *p = loc.toChars();
if (!*p)
p = locToChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
va_list ap;
va_start(ap, format);
vfprintf(stdmsg, format, ap);
va_end(ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
}
global.errors++;
//fatal();
}
void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
{
if (!global.params.useDeprecated && isDeprecated())
{
// Don't complain if we're inside a deprecated symbol's scope
for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
{ if (sp->isDeprecated())
return;
}
for (; sc; sc = sc->enclosing)
{
if (sc->scopesym && sc->scopesym->isDeprecated())
return;
}
error(loc, "is deprecated");
}
}
/**********************************
* Determine which Module a Dsymbol is in.
*/
Module *Dsymbol::getModule()
{
Module *m;
Dsymbol *s;
//printf("Dsymbol::getModule()\n");
s = this;
while (s)
{
//printf("\ts = '%s'\n", s->toChars());
m = s->isModule();
if (m)
return m;
s = s->parent;
}
return NULL;
}
/*************************************
*/
enum PROT Dsymbol::prot()
{
return PROTpublic;
}
/*************************************
* Do syntax copy of an array of Dsymbol's.
*/
Array *Dsymbol::arraySyntaxCopy(Array *a)
{
Array *b = NULL;
if (a)
{
b = a->copy();
for (int i = 0; i < b->dim; i++)
{
Dsymbol *s = (Dsymbol *)b->data[i];
s = s->syntaxCopy(NULL);
b->data[i] = (void *)s;
}
}
return b;
}
/****************************************
* Add documentation comment to Dsymbol.
* Ignore NULL comments.
*/
void Dsymbol::addComment(unsigned char *comment)
{
// if (comment)
// printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
if (!this->comment)
this->comment = comment;
#if 1
else if (comment && strcmp((char *)comment, (char *)this->comment))
{ // Concatenate the two
this->comment = Lexer::combineComments(this->comment, comment);
}
#endif
}
/********************************* ScopeDsymbol ****************************/
ScopeDsymbol::ScopeDsymbol()
: Dsymbol()
{
members = NULL;
symtab = NULL;
imports = NULL;
prots = NULL;
}
ScopeDsymbol::ScopeDsymbol(Identifier *id)
: Dsymbol(id)
{
members = NULL;
symtab = NULL;
imports = NULL;
prots = NULL;
}
Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
{
//printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
ScopeDsymbol *sd;
if (s)
sd = (ScopeDsymbol *)s;
else
sd = new ScopeDsymbol(ident);
sd->members = arraySyntaxCopy(members);
return sd;
}
Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
{ Dsymbol *s;
int i;
//printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
// Look in symbols declared in this module
s = symtab ? symtab->lookup(ident) : NULL;
if (s)
{
//printf("\ts = '%s.%s'\n",toChars(),s->toChars());
}
else if (imports)
{
// Look in imported modules
for (i = 0; i < imports->dim; i++)
{ ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
Dsymbol *s2;
// If private import, don't search it
if (flags & 1 && prots[i] == PROTprivate)
continue;
//printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
if (!s)
s = s2;
else if (s2 && s != s2)
{
if (s->toAlias() == s2->toAlias())
{
if (s->isDeprecated())
s = s2;
}
else
{
/* Two imports of the same module should be regarded as
* the same.
*/
Import *i1 = s->isImport();
Import *i2 = s2->isImport();
if (!(i1 && i2 &&
(i1->mod == i2->mod ||
(!i1->parent->isImport() && !i2->parent->isImport() &&
i1->ident->equals(i2->ident))
)
)
)
{
ss->multiplyDefined(loc, s, s2);
break;
}
}
}
}
if (s)
{
Declaration *d = s->isDeclaration();
if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin())
error("%s is private", d->toPrettyChars());
}
}
return s;
}
void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
{
//printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
// No circular or redundant import's
if (s != this)
{
if (!imports)
imports = new Array();
else
{
for (int i = 0; i < imports->dim; i++)
{ ScopeDsymbol *ss;
ss = (ScopeDsymbol *) imports->data[i];
if (ss == s)
{
if (protection > prots[i])
prots[i] = protection; // upgrade access
return;
}
}
}
imports->push(s);
prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
prots[imports->dim - 1] = protection;
}
}
int ScopeDsymbol::isforwardRef()
{
return (members == NULL);
}
void ScopeDsymbol::defineRef(Dsymbol *s)
{
ScopeDsymbol *ss;
ss = s->isScopeDsymbol();
members = ss->members;
ss->members = NULL;
}
void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
{
#if 0
printf("ScopeDsymbol::multiplyDefined()\n");
printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : "");
printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : "");
#endif
if (loc.filename)
{ ::error(loc, "%s at %s conflicts with %s at %s",
s1->toPrettyChars(),
s1->locToChars(),
s2->toPrettyChars(),
s2->locToChars());
}
else
{
s1->error(loc, "conflicts with %s %s at %s",
s2->kind(),
s2->toPrettyChars(),
s2->locToChars());
}
}
Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
{
Dsymbol *sprev;
// Look to see if we are defining a forward referenced symbol
sprev = symtab->lookup(s->ident);
assert(sprev);
if (s->equals(sprev)) // if the same symbol
{
if (s->isforwardRef()) // if second declaration is a forward reference
return sprev;
if (sprev->isforwardRef())
{
sprev->defineRef(s); // copy data from s into sprev
return sprev;
}
}
multiplyDefined(0, s, sprev);
return sprev;
}
char *ScopeDsymbol::kind()
{
return "ScopeDsymbol";
}
/****************************** WithScopeSymbol ******************************/
WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
: ScopeDsymbol()
{
this->withstate = withstate;
}
Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
{
// Acts as proxy to the with class declaration
return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0);
}
/****************************** ArrayScopeSymbol ******************************/
ArrayScopeSymbol::ArrayScopeSymbol(Expression *e)
: ScopeDsymbol()
{
assert(e->op == TOKindex || e->op == TOKslice);
exp = e;
type = NULL;
td = NULL;
}
ArrayScopeSymbol::ArrayScopeSymbol(TypeTuple *t)
: ScopeDsymbol()
{
exp = NULL;
type = t;
td = NULL;
}
ArrayScopeSymbol::ArrayScopeSymbol(TupleDeclaration *s)
: ScopeDsymbol()
{
exp = NULL;
type = NULL;
td = s;
}
Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
{
//printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
if (ident == Id::length || ident == Id::dollar)
{ VarDeclaration **pvar;
Expression *ce;
L1:
if (td)
{
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
v->storage_class |= STCconst;
return v;
}
if (type)
{
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
v->storage_class |= STCconst;
return v;
}
if (exp->op == TOKindex)
{
IndexExp *ie = (IndexExp *)exp;
pvar = &ie->lengthVar;
ce = ie->e1;
}
else if (exp->op == TOKslice)
{
SliceExp *se = (SliceExp *)exp;
pvar = &se->lengthVar;
ce = se->e1;
}
else
return NULL;
if (ce->op == TOKtype)
{
Type *t = ((TypeExp *)ce)->type;
if (t->ty == Ttuple)
{ type = (TypeTuple *)t;
goto L1;
}
}
if (!*pvar)
{
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
if (ce->op == TOKstring)
{ /* It is for a string literal, so the
* length will be a const.
*/
Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t);
v->init = new ExpInitializer(0, e);
v->storage_class |= STCconst;
}
else if (ce->op == TOKarrayliteral)
{ /* It is for an array literal, so the
* length will be a const.
*/
Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
v->storage_class |= STCconst;
}
else if (ce->op == TOKtuple)
{ /* It is for an expression tuple, so the
* length will be a const.
*/
Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
v->storage_class |= STCconst;
}
*pvar = v;
}
return (*pvar);
}
return NULL;
}
/****************************** DsymbolTable ******************************/
DsymbolTable::DsymbolTable()
{
tab = new StringTable;
}
DsymbolTable::~DsymbolTable()
{
delete tab;
}
Dsymbol *DsymbolTable::lookup(Identifier *ident)
{ StringValue *sv;
#ifdef DEBUG
assert(ident);
assert(tab);
#endif
sv = tab->lookup((char*)ident->string, ident->len);
return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
}
Dsymbol *DsymbolTable::insert(Dsymbol *s)
{ StringValue *sv;
Identifier *ident;
//printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
ident = s->ident;
#ifdef DEBUG
assert(ident);
assert(tab);
#endif
sv = tab->insert(ident->toChars(), ident->len);
if (!sv)
return NULL; // already in table
sv->ptrvalue = s;
return s;
}
Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s)
{ StringValue *sv;
//printf("DsymbolTable::insert()\n");
sv = tab->insert(ident->toChars(), ident->len);
if (!sv)
return NULL; // already in table
sv->ptrvalue = s;
return s;
}
Dsymbol *DsymbolTable::update(Dsymbol *s)
{ StringValue *sv;
Identifier *ident;
ident = s->ident;
sv = tab->update(ident->toChars(), ident->len);
sv->ptrvalue = s;
return s;
}

299
dmd/dsymbol.h Normal file
View File

@@ -0,0 +1,299 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_DSYMBOL_H
#define DMD_DSYMBOL_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "stringtable.h"
#include "mars.h"
#include "arraytypes.h"
struct Identifier;
struct Scope;
struct DsymbolTable;
struct Declaration;
struct TupleDeclaration;
struct TypedefDeclaration;
struct AliasDeclaration;
struct AggregateDeclaration;
struct EnumDeclaration;
struct ClassDeclaration;
struct InterfaceDeclaration;
struct StructDeclaration;
struct UnionDeclaration;
struct FuncDeclaration;
struct FuncAliasDeclaration;
struct FuncLiteralDeclaration;
struct CtorDeclaration;
struct DtorDeclaration;
struct StaticCtorDeclaration;
struct StaticDtorDeclaration;
struct InvariantDeclaration;
struct UnitTestDeclaration;
struct NewDeclaration;
struct VarDeclaration;
struct AttribDeclaration;
struct Symbol;
struct Package;
struct Module;
struct Import;
struct Type;
struct TypeTuple;
struct WithStatement;
struct LabelDsymbol;
struct ScopeDsymbol;
struct TemplateDeclaration;
struct TemplateInstance;
struct TemplateMixin;
struct EnumMember;
struct ScopeDsymbol;
struct WithScopeSymbol;
struct ArrayScopeSymbol;
struct SymbolDeclaration;
struct Expression;
struct DeleteDeclaration;
struct HdrGenState;
struct TypeInfoDeclaration;
#if IN_GCC
union tree_node;
typedef union tree_node TYPE;
#else
struct TYPE;
#endif
#if IN_LLVM
namespace llvm
{
class Value;
}
#endif
enum PROT
{
PROTundefined,
PROTnone, // no access
PROTprivate,
PROTpackage,
PROTprotected,
PROTpublic,
PROTexport,
};
struct Dsymbol : Object
{
Identifier *ident;
Identifier *c_ident;
Dsymbol *parent;
Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Dsymbol();
Dsymbol(Identifier *);
char *toChars();
char *toPrettyChars();
char *locToChars();
int equals(Object *o);
int isAnonymous();
void error(Loc loc, const char *format, ...);
void error(const char *format, ...);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule();
Dsymbol *pastMixin();
Dsymbol *toParent();
Dsymbol *toParent2();
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
static Array *arraySyntaxCopy(Array *a);
virtual char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void semantic(Scope *sc);
virtual void semantic2(Scope *sc);
virtual void semantic3(Scope *sc);
virtual void inlineScan();
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
virtual int overloadInsert(Dsymbol *s);
#ifdef _DH
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
#endif
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
virtual ClassDeclaration *isClassMember(); // are we a member of a class?
virtual int isExport(); // is Dsymbol exported?
virtual int isImportedSymbol(); // is Dsymbol imported?
virtual int isDeprecated(); // is Dsymbol deprecated?
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type?
virtual char *mangle();
virtual int needThis(); // need a 'this' pointer?
virtual enum PROT prot();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual int oneMember(Dsymbol **ps);
static int oneMembers(Array *members, Dsymbol **ps);
virtual int hasPointers();
virtual void addLocalClass(ClassDeclarations *) { }
virtual void checkCtorConstInit() { }
virtual void addComment(unsigned char *comment);
virtual void emitComment(Scope *sc);
void emitDitto(Scope *sc);
// Backend
virtual Symbol *toSymbol(); // to backend symbol
virtual void toObjFile(); // compile to .obj file
virtual int cvMember(unsigned char *p); // emit cv debug info for member
Symbol *toImport(); // to backend import symbol
static Symbol *toImport(Symbol *s); // to backend import symbol
Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper
// Eliminate need for dynamic_cast
virtual Package *isPackage() { return NULL; }
virtual Module *isModule() { return NULL; }
virtual EnumMember *isEnumMember() { return NULL; }
virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
virtual TemplateInstance *isTemplateInstance() { return NULL; }
virtual TemplateMixin *isTemplateMixin() { return NULL; }
virtual Declaration *isDeclaration() { return NULL; }
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
virtual NewDeclaration *isNewDeclaration() { return NULL; }
virtual VarDeclaration *isVarDeclaration() { return NULL; }
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
virtual StructDeclaration *isStructDeclaration() { return NULL; }
virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
virtual Import *isImport() { return NULL; }
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
#ifdef _DH
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
#endif
virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; }
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
// llvm stuff
int llvmInternal;
char* llvmInternal1;
char* llvmInternal2;
llvm::Value* llvmValue;
Module* llvmDModule;
};
// Dsymbol that generates a scope
struct ScopeDsymbol : Dsymbol
{
Array *members; // all Dsymbol's in this scope
DsymbolTable *symtab; // members[] sorted into table
Array *imports; // imported ScopeDsymbol's
unsigned char *prots; // PROT for each import
ScopeDsymbol();
ScopeDsymbol(Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void importScope(ScopeDsymbol *s, enum PROT protection);
int isforwardRef();
void defineRef(Dsymbol *s);
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
Dsymbol *nameCollision(Dsymbol *s);
char *kind();
void emitMemberComments(Scope *sc);
ScopeDsymbol *isScopeDsymbol() { return this; }
};
// With statement scope
struct WithScopeSymbol : ScopeDsymbol
{
WithStatement *withstate;
WithScopeSymbol(WithStatement *withstate);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
WithScopeSymbol *isWithScopeSymbol() { return this; }
};
// Array Index/Slice scope
struct ArrayScopeSymbol : ScopeDsymbol
{
Expression *exp; // IndexExp or SliceExp
TypeTuple *type; // for tuple[length]
TupleDeclaration *td; // for tuples of objects
ArrayScopeSymbol(Expression *e);
ArrayScopeSymbol(TypeTuple *t);
ArrayScopeSymbol(TupleDeclaration *td);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
};
// Table of Dsymbol's
struct DsymbolTable : Object
{
StringTable *tab;
DsymbolTable();
~DsymbolTable();
// Look up Identifier. Return Dsymbol if found, NULL if not.
Dsymbol *lookup(Identifier *ident);
// Insert Dsymbol in table. Return NULL if already there.
Dsymbol *insert(Dsymbol *s);
// Look for Dsymbol in table. If there, return it. If not, insert s and return that.
Dsymbol *update(Dsymbol *s);
Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same
};
#endif /* DMD_DSYMBOL_H */

144
dmd/dump.c Normal file
View File

@@ -0,0 +1,144 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include "mars.h"
#include "mtype.h"
#include "declaration.h"
#include "expression.h"
#include "template.h"
static void indent(int indent)
{
int i;
for (i = 0; i < indent; i++)
printf(" ");
}
static char *type_print(Type *type)
{
return type ? type->toChars() : (char *) "null";
}
void dumpExpressions(int i, Expressions *exps)
{
for (size_t j = 0; j < exps->dim; j++)
{ Expression *e = (Expression *)exps->data[j];
indent(i);
printf("(\n");
e->dump(i + 2);
indent(i);
printf(")\n");
}
}
void Expression::dump(int i)
{
indent(i);
printf("%p %s type=%s\n", this, Token::toChars(op), type_print(type));
}
void IntegerExp::dump(int i)
{
indent(i);
printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type));
}
void IdentifierExp::dump(int i)
{
indent(i);
printf("%p ident '%s' type=%s\n", this, ident->toChars(), type_print(type));
}
void DsymbolExp::dump(int i)
{
indent(i);
printf("%p %s type=%s\n", this, s->toChars(), type_print(type));
}
void VarExp::dump(int i)
{
indent(i);
printf("%p %s var=%s type=%s\n", this, Token::toChars(op), var->toChars(), type_print(type));
}
void UnaExp::dump(int i)
{
indent(i);
printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1);
if (e1)
e1->dump(i + 2);
}
void CallExp::dump(int i)
{
UnaExp::dump(i);
dumpExpressions(i, arguments);
}
void SliceExp::dump(int i)
{
indent(i);
printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1);
if (e1)
e1->dump(i + 2);
if (lwr)
lwr->dump(i + 2);
if (upr)
upr->dump(i + 2);
}
void DotIdExp::dump(int i)
{
indent(i);
printf("%p %s type=%s ident=%s e1=%p\n", this, Token::toChars(op), type_print(type), ident->toChars(), e1);
if (e1)
e1->dump(i + 2);
}
void DotVarExp::dump(int i)
{
indent(i);
printf("%p %s type=%s var='%s' e1=%p\n", this, Token::toChars(op), type_print(type), var->toChars(), e1);
if (e1)
e1->dump(i + 2);
}
void DotTemplateInstanceExp::dump(int i)
{
indent(i);
printf("%p %s type=%s ti='%s' e1=%p\n", this, Token::toChars(op), type_print(type), ti->toChars(), e1);
if (e1)
e1->dump(i + 2);
}
void DelegateExp::dump(int i)
{
indent(i);
printf("%p %s func=%s type=%s e1=%p\n", this, Token::toChars(op), func->toChars(), type_print(type), e1);
if (e1)
e1->dump(i + 2);
}
void BinExp::dump(int i)
{
indent(i);
printf("%p %s type=%s e1=%p e2=%p\n", this, Token::toChars(op), type_print(type), e1, e2);
if (e1)
e1->dump(i + 2);
if (e2)
e2->dump(i + 2);
}

1366
dmd/entity.c Normal file

File diff suppressed because it is too large Load Diff

314
dmd/enum.c Normal file
View File

@@ -0,0 +1,314 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "enum.h"
#include "mtype.h"
#include "scope.h"
/********************************* EnumDeclaration ****************************/
EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
: ScopeDsymbol(id)
{
this->loc = loc;
type = new TypeEnum(this);
this->memtype = memtype;
maxval = 0;
minval = 0;
defaultval = 0;
sinit = NULL;
}
Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
{
Type *t = NULL;
if (memtype)
t = memtype->syntaxCopy();
EnumDeclaration *ed;
if (s)
{ ed = (EnumDeclaration *)s;
ed->memtype = t;
}
else
ed = new EnumDeclaration(loc, ident, t);
ScopeDsymbol::syntaxCopy(ed);
return ed;
}
void EnumDeclaration::semantic(Scope *sc)
{ int i;
uinteger_t number;
Type *t;
Scope *sce;
//printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars());
if (symtab) // if already done
return;
if (!memtype)
memtype = Type::tint32;
parent = sc->scopesym;
memtype = memtype->semantic(loc, sc);
/* Check to see if memtype is forward referenced
*/
if (memtype->ty == Tenum)
{ EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
if (!sym->memtype)
{
error("base enum %s is forward referenced", sym->toChars());
memtype = Type::tint32;
}
}
if (!memtype->isintegral())
{ error("base type must be of integral type, not %s", memtype->toChars());
memtype = Type::tint32;
}
t = isAnonymous() ? memtype : type;
symtab = new DsymbolTable();
sce = sc->push(this);
sce->parent = this;
number = 0;
if (!members) // enum ident;
return;
if (members->dim == 0)
error("enum %s must have at least one member", toChars());
int first = 1;
for (i = 0; i < members->dim; i++)
{
EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
Expression *e;
if (!em)
/* The e->semantic(sce) can insert other symbols, such as
* template instances and function literals.
*/
continue;
//printf("Enum member '%s'\n",em->toChars());
e = em->value;
if (e)
{
assert(e->dyncast() == DYNCAST_EXPRESSION);
e = e->semantic(sce);
e = e->optimize(WANTvalue);
// Need to copy it because we're going to change the type
e = e->copy();
e = e->implicitCastTo(sc, memtype);
e = e->optimize(WANTvalue);
number = e->toInteger();
e->type = t;
}
else
{ // Default is the previous number plus 1
// Check for overflow
if (!first)
{
switch (t->toBasetype()->ty)
{
case Tbool:
if (number == 2) goto Loverflow;
break;
case Tint8:
if (number == 128) goto Loverflow;
break;
case Tchar:
case Tuns8:
if (number == 256) goto Loverflow;
break;
case Tint16:
if (number == 0x8000) goto Loverflow;
break;
case Twchar:
case Tuns16:
if (number == 0x10000) goto Loverflow;
break;
case Tint32:
if (number == 0x80000000) goto Loverflow;
break;
case Tdchar:
case Tuns32:
if (number == 0x100000000LL) goto Loverflow;
break;
case Tint64:
if (number == 0x8000000000000000LL) goto Loverflow;
break;
case Tuns64:
if (number == 0) goto Loverflow;
break;
Loverflow:
error("overflow of enum value");
break;
default:
assert(0);
}
}
e = new IntegerExp(em->loc, number, t);
}
em->value = e;
// Add to symbol table only after evaluating 'value'
if (isAnonymous())
{
//sce->enclosing->insert(em);
for (Scope *scx = sce->enclosing; scx; scx = scx->enclosing)
{
if (scx->scopesym)
{
if (!scx->scopesym->symtab)
scx->scopesym->symtab = new DsymbolTable();
em->addMember(sce, scx->scopesym, 1);
break;
}
}
}
else
em->addMember(sc, this, 1);
if (first)
{ first = 0;
defaultval = number;
minval = number;
maxval = number;
}
else if (memtype->isunsigned())
{
if (number < minval)
minval = number;
if (number > maxval)
maxval = number;
}
else
{
if ((sinteger_t)number < (sinteger_t)minval)
minval = number;
if ((sinteger_t)number > (sinteger_t)maxval)
maxval = number;
}
number++;
}
//printf("defaultval = %lld\n", defaultval);
sce->pop();
//members->print();
}
int EnumDeclaration::oneMember(Dsymbol **ps)
{
if (isAnonymous())
return Dsymbol::oneMembers(members, ps);
return Dsymbol::oneMember(ps);
}
void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ int i;
buf->writestring("enum ");
if (ident)
{ buf->writestring(ident->toChars());
buf->writeByte(' ');
}
if (memtype)
{
buf->writestring(": ");
memtype->toCBuffer(buf, NULL, hgs);
}
if (!members)
{
buf->writeByte(';');
buf->writenl();
return;
}
buf->writenl();
buf->writeByte('{');
buf->writenl();
for (i = 0; i < members->dim; i++)
{
EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
if (!em)
continue;
//buf->writestring(" ");
em->toCBuffer(buf, hgs);
buf->writeByte(',');
buf->writenl();
}
buf->writeByte('}');
buf->writenl();
}
Type *EnumDeclaration::getType()
{
return type;
}
char *EnumDeclaration::kind()
{
return "enum";
}
/********************************* EnumMember ****************************/
EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value)
: Dsymbol(id)
{
this->value = value;
this->loc = loc;
}
Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
{
Expression *e = NULL;
if (value)
e = value->syntaxCopy();
EnumMember *em;
if (s)
{ em = (EnumMember *)s;
em->loc = loc;
em->value = e;
}
else
em = new EnumMember(loc, ident, e);
return em;
}
void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring(ident->toChars());
if (value)
{
buf->writestring(" = ");
value->toCBuffer(buf, hgs);
}
}
char *EnumMember::kind()
{
return "enum member";
}

74
dmd/enum.h Normal file
View File

@@ -0,0 +1,74 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_ENUM_H
#define DMD_ENUM_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct Identifier;
struct Type;
struct Expression;
#ifdef _DH
struct HdrGenState;
#endif
struct EnumDeclaration : ScopeDsymbol
{
Type *type; // the TypeEnum
Type *memtype; // type of the members
integer_t maxval;
integer_t minval;
integer_t defaultval; // default initializer
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *getType();
char *kind();
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
EnumDeclaration *isEnumDeclaration() { return this; }
void toObjFile(); // compile to .obj file
void toDebug();
int cvMember(unsigned char *p);
Symbol *sinit;
Symbol *toInitializer();
};
struct EnumMember : Dsymbol
{
Expression *value;
EnumMember(Loc loc, Identifier *id, Expression *value);
Dsymbol *syntaxCopy(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
EnumMember *isEnumMember() { return this; }
};
#endif /* DMD_ENUM_H */

8584
dmd/expression.c Normal file

File diff suppressed because it is too large Load Diff

1410
dmd/expression.h Normal file

File diff suppressed because it is too large Load Diff

2659
dmd/func.c Normal file

File diff suppressed because it is too large Load Diff

55
dmd/gnuc.c Normal file
View File

@@ -0,0 +1,55 @@
// Put functions in here missing from gnu C
#include "gnuc.h"
int memicmp(const char *s1, const char *s2, int n)
{
int result = 0;
for (int i = 0; i < n; i++)
{ char c1 = s1[i];
char c2 = s2[i];
result = c1 - c2;
if (result)
{
if ('A' <= c1 && c1 <= 'Z')
c1 += 'a' - 'A';
if ('A' <= c2 && c2 <= 'Z')
c2 += 'a' - 'A';
result = c1 - c2;
if (result)
break;
}
}
return result;
}
int stricmp(const char *s1, const char *s2)
{
int result = 0;
for (;;)
{ char c1 = *s1;
char c2 = *s2;
result = c1 - c2;
if (result)
{
if ('A' <= c1 && c1 <= 'Z')
c1 += 'a' - 'A';
if ('A' <= c2 && c2 <= 'Z')
c2 += 'a' - 'A';
result = c1 - c2;
if (result)
break;
}
if (!c1)
break;
s1++;
s2++;
}
return result;
}

8
dmd/gnuc.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef _GNUC_H
#define _GNUC_H 1
int memicmp(const char *s1, const char *s2, int n);
int stricmp(const char *s1, const char *s2);
#endif

248
dmd/gpl.txt Normal file
View File

@@ -0,0 +1,248 @@
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

114
dmd/hdrgen.c Normal file
View File

@@ -0,0 +1,114 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// Initial header generation implementation by Dave Fladebo
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
// Routines to emit header files
#ifdef _DH
#define PRETTY_PRINT
#define TEST_EMIT_ALL 0 // For Testing
#define LOG 0
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if __DMC__
#include <complex.h>
#endif
#if IN_GCC || IN_LLVM
#include "mem.h"
#else
#if _WIN32
#include "..\root\mem.h"
#elif linux
#include "../root/mem.h"
#else
#error "fix this"
#endif
#endif
#include "id.h"
#include "init.h"
#include "attrib.h"
#include "cond.h"
#include "enum.h"
#include "import.h"
#include "module.h"
#include "mtype.h"
#include "scope.h"
#include "staticassert.h"
#include "template.h"
#include "utf.h"
#include "version.h"
#include "declaration.h"
#include "aggregate.h"
#include "expression.h"
#include "statement.h"
#include "mtype.h"
#include "hdrgen.h"
void argsToCBuffer(OutBuffer *buf, Array *arguments, HdrGenState *hgs);
void Module::genhdrfile()
{
OutBuffer hdrbufr;
hdrbufr.printf("// D import file generated from '%s'", srcfile->toChars());
hdrbufr.writenl();
HdrGenState hgs;
memset(&hgs, 0, sizeof(hgs));
hgs.hdrgen = 1;
toCBuffer(&hdrbufr, &hgs);
// Transfer image to file
hdrfile->setbuffer(hdrbufr.data, hdrbufr.offset);
hdrbufr.data = NULL;
char *pt = FileName::path(hdrfile->toChars());
if (*pt)
FileName::ensurePathExists(pt);
mem.free(pt);
hdrfile->writev();
}
void Module::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (md)
{
buf->writestring("module ");
buf->writestring(md->toChars());
buf->writebyte(';');
buf->writenl();
}
for (int i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
s->toHBuffer(buf, hgs);
}
}
void Dsymbol::toHBuffer(OutBuffer *buf, HdrGenState *hgs)
{
toCBuffer(buf, hgs);
}
/*************************************/
#endif // #ifdef _DH

34
dmd/hdrgen.h Normal file
View File

@@ -0,0 +1,34 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// initial header generation implementation by Dave Fladebo
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
struct HdrGenState
{
int hdrgen; // 1 if generating header file
int ddoc; // 1 if generating Ddoc file
int console; // 1 if writing to console
int tpltMember;
int inCallExp;
int inPtrExp;
int inSlcExp;
int inDotExp;
int inBinExp;
int inArrExp;
int emitInst;
struct
{
int init;
int decl;
} FLinit;
HdrGenState() { memset(this, 0, sizeof(HdrGenState)); }
};

718
dmd/html.c Normal file
View File

@@ -0,0 +1,718 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
/* HTML parser
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <errno.h>
#include <wchar.h>
#include "mars.h"
#include "html.h"
#include <assert.h>
#include "root.h"
extern int HtmlNamedEntity(unsigned char *p, int length);
static int isLineSeparator(const unsigned char* p);
/**********************************
* Determine if beginning of tag identifier
* or a continuation of a tag identifier.
*/
inline int istagstart(int c)
{
return (isalpha(c) || c == '_');
}
inline int istag(int c)
{
return (isalnum(c) || c == '_');
}
/**********************************************
*/
Html::Html(const char *sourcename, unsigned char *base, unsigned length)
{
//printf("Html::Html()\n");
this->sourcename = sourcename;
this->base = base;
p = base;
end = base + length;
linnum = 1;
dbuf = NULL;
inCode = 0;
}
/**********************************************
* Print error & quit.
*/
void Html::error(const char *format, ...)
{
if (!global.gag)
{
printf("%s(%d) : HTML Error: ", sourcename, linnum);
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
printf("\n");
fflush(stdout);
}
global.errors++;
}
/**********************************************
* Extract all the code from an HTML file,
* concatenate it all together, and store in buf.
*/
void Html::extractCode(OutBuffer *buf)
{
//printf("Html::extractCode()\n");
dbuf = buf; // save for other routines
buf->reserve(end - p);
inCode = 0;
while (1)
{
//printf("p = %p, *p = x%x\n", p, *p);
switch (*p)
{
#if 0 // strings are not recognized outside of tags
case '"':
case '\'':
skipString();
continue;
#endif
case '<':
if (p[1] == '!' && isCommentStart())
{ // Comments start with <!--
scanComment();
}
else if(p[1] == '!' && isCDATAStart())
{
scanCDATA();
}
else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
skipTag();
else if (istagstart(*skipWhite(p + 1)))
skipTag();
else
goto Ldefault;
continue;
case 0:
case 0x1a:
break; // end of file
case '&':
if (inCode)
{ // Translate character entity into ascii for D parser
int c;
c = charEntity();
buf->writeUTF8(c);
}
else
p++;
continue;
case '\r':
if (p[1] == '\n')
goto Ldefault;
case '\n':
linnum++;
// Always extract new lines, so that D lexer counts the
// lines right.
buf->writeByte(*p);
p++;
continue;
default:
Ldefault:
if (inCode)
buf->writeByte(*p);
p++;
continue;
}
break;
}
buf->writeByte(0); // ending sentinel
//printf("D code is: '%s'\n", (char *)buf->data);
}
/***********************************************
* Scan to end of <> tag.
* Look for <code> and </code> tags to start/stop D processing.
* Input:
* p is on opening '<' of tag; it's already verified that
* it's a tag by lookahead
* Output:
* p is past closing '>' of tag
*/
void Html::skipTag()
{
enum TagState // what parsing state we're in
{
TStagstart, // start of tag name
TStag, // in a tag name
TSrest, // following tag name
};
enum TagState state = TStagstart;
int inot;
unsigned char *tagstart = NULL;
int taglen = 0;
p++;
inot = 0;
if (*p == '/')
{ inot = 1;
p++;
}
while (1)
{
switch (*p)
{
case '>': // found end of tag
p++;
break;
case '"':
case '\'':
state = TSrest;
skipString();
continue;
case '<':
if (p[1] == '!' && isCommentStart())
{ // Comments start with <!--
scanComment();
}
else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
{ error("nested tag");
skipTag();
}
else if (istagstart(*skipWhite(p + 1)))
{ error("nested tag");
skipTag();
}
// Treat comments as if they were whitespace
state = TSrest;
continue;
case 0:
case 0x1a:
error("end of file before end of tag");
break; // end of file
case '\r':
if (p[1] == '\n')
goto Ldefault;
case '\n':
linnum++;
// Always extract new lines, so that code lexer counts the
// lines right.
dbuf->writeByte(*p);
state = TSrest; // end of tag
p++;
continue;
case ' ':
case '\t':
case '\f':
case '\v':
if (state == TStagstart)
{ p++;
continue;
}
default:
Ldefault:
switch (state)
{
case TStagstart: // start of tag name
assert(istagstart(*p));
state = TStag;
tagstart = p;
taglen = 0;
break;
case TStag:
if (istag(*p))
{ // Continuing tag name
taglen++;
}
else
{ // End of tag name
state = TSrest;
}
break;
case TSrest:
break;
}
p++;
continue;
}
break;
}
// See if we parsed a <code> or </code> tag
if (taglen && memicmp((char *) tagstart, (char *) "CODE", taglen) == 0
&& *(p - 2) != '/') // ignore "<code />" (XHTML)
{
if (inot)
{ inCode--;
if (inCode < 0)
inCode = 0; // ignore extra </code>'s
}
else
inCode++;
}
}
/***********************************************
* Scan to end of attribute string.
*/
void Html::skipString()
{
int tc = *p;
while (1)
{
p++;
switch (*p)
{
case '"':
case '\'':
if (*p == tc)
{ p++;
break;
}
continue;
case '\r':
if (p[1] == '\n')
goto Ldefault;
case '\n':
linnum++;
// Always extract new lines, so that D lexer counts the
// lines right.
dbuf->writeByte(*p);
continue;
case 0:
case 0x1a:
Leof:
error("end of file before closing %c of string", tc);
break;
default:
Ldefault:
continue;
}
break;
}
}
/*********************************
* If p points to any white space, skip it
* and return pointer just past it.
*/
unsigned char *Html::skipWhite(unsigned char *q)
{
for (; 1; q++)
{
switch (*q)
{
case ' ':
case '\t':
case '\f':
case '\v':
case '\r':
case '\n':
continue;
default:
break;
}
break;
}
return q;
}
/***************************************************
* Scan to end of comment.
* Comments are defined any of a number of ways.
* IE 5.0: <!-- followed by >
* "HTML The Definitive Guide": <!-- text with at least one space in it -->
* Netscape: <!-- --> comments nest
* w3c: whitespace can appear between -- and > of comment close
*/
void Html::scanComment()
{
// Most of the complexity is dealing with the case that
// an arbitrary amount of whitespace can appear between
// the -- and the > of a comment close.
int scangt = 0;
//printf("scanComment()\n");
if (*p == '\n')
{ linnum++;
// Always extract new lines, so that D lexer counts the
// lines right.
dbuf->writeByte(*p);
}
while (1)
{
//scangt = 1; // IE 5.0 compatibility
p++;
switch (*p)
{
case '-':
if (p[1] == '-')
{
if (p[2] == '>') // optimize for most common case
{
p += 3;
break;
}
p++;
scangt = 1;
}
else
scangt = 0;
continue;
case '>':
if (scangt)
{ // found -->
p++;
break;
}
continue;
case ' ':
case '\t':
case '\f':
case '\v':
// skip white space
continue;
case '\r':
if (p[1] == '\n')
goto Ldefault;
case '\n':
linnum++; // remember to count lines
// Always extract new lines, so that D lexer counts the
// lines right.
dbuf->writeByte(*p);
continue;
case 0:
case 0x1a:
error("end of file before closing --> of comment");
break;
default:
Ldefault:
scangt = 0; // it's not -->
continue;
}
break;
}
//printf("*p = '%c'\n", *p);
}
/********************************************
* Determine if we are at the start of a comment.
* Input:
* p is on the opening '<'
* Returns:
* 0 if not start of a comment
* 1 if start of a comment, p is adjusted to point past --
*/
int Html::isCommentStart()
#ifdef __DMC__
__out(result)
{
if (result == 0)
;
else if (result == 1)
{
assert(p[-2] == '-' && p[-1] == '-');
}
else
assert(0);
}
__body
#endif /* __DMC__ */
{ unsigned char *s;
if (p[0] == '<' && p[1] == '!')
{
for (s = p + 2; 1; s++)
{
switch (*s)
{
case ' ':
case '\t':
case '\r':
case '\f':
case '\v':
// skip white space, even though spec says no
// white space is allowed
continue;
case '-':
if (s[1] == '-')
{
p = s + 2;
return 1;
}
goto No;
default:
goto No;
}
}
}
No:
return 0;
}
int Html::isCDATAStart()
{
const char * CDATA_START_MARKER = "<![CDATA[";
size_t len = strlen(CDATA_START_MARKER);
if (strncmp((char*)p, CDATA_START_MARKER, len) == 0)
{
p += len;
return 1;
}
else
{
return 0;
}
}
void Html::scanCDATA()
{
while(*p && *p != 0x1A)
{
int lineSepLength = isLineSeparator(p);
if (lineSepLength>0)
{
/* Always extract new lines, so that D lexer counts the lines
* right.
*/
linnum++;
dbuf->writeUTF8('\n');
p += lineSepLength;
continue;
}
else if (p[0] == ']' && p[1] == ']' && p[2] == '>')
{
/* end of CDATA section */
p += 3;
return;
}
else if (inCode)
{
/* this CDATA section contains D code */
dbuf->writeByte(*p);
}
p++;
}
}
/********************************************
* Convert an HTML character entity into a character.
* Forms are:
* &name; named entity
* &#ddd; decimal
* &#xhhhh; hex
* Input:
* p is on the &
*/
int Html::charEntity()
{ int c = 0;
int v;
int hex;
unsigned char *pstart = p;
//printf("Html::charEntity('%c')\n", *p);
if (p[1] == '#')
{
p++;
if (p[1] == 'x' || p[1] == 'X')
{ p++;
hex = 1;
}
else
hex = 0;
if (p[1] == ';')
goto Linvalid;
while (1)
{
p++;
switch (*p)
{
case 0:
case 0x1a:
error("end of file before end of character entity");
goto Lignore;
case '\n':
case '\r':
case '<': // tag start
// Termination is assumed
break;
case ';':
// Termination is explicit
p++;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
v = *p - '0';
goto Lvalue;
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
if (!hex)
goto Linvalid;
v = (*p - 'a') + 10;
goto Lvalue;
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
if (!hex)
goto Linvalid;
v = (*p - 'A') + 10;
goto Lvalue;
Lvalue:
if (hex)
c = (c << 4) + v;
else
c = (c * 10) + v;
if (c > 0x10FFFF)
{
error("character entity out of range");
goto Lignore;
}
continue;
default:
Linvalid:
error("invalid numeric character reference");
goto Lignore;
}
break;
}
}
else
{
// It's a named entity; gather all characters until ;
unsigned char *idstart = p + 1;
while (1)
{
p++;
switch (*p)
{
case 0:
case 0x1a:
error("end of file before end of character entity");
break;
case '\n':
case '\r':
case '<': // tag start
// Termination is assumed
c = HtmlNamedEntity(idstart, p - idstart);
if (c == -1)
goto Lignore;
break;
case ';':
// Termination is explicit
c = HtmlNamedEntity(idstart, p - idstart);
if (c == -1)
goto Lignore;
p++;
break;
default:
continue;
}
break;
}
}
// Kludge to convert non-breaking space to ascii space
if (c == 160)
c = ' ';
return c;
Lignore:
//printf("Lignore\n");
p = pstart + 1;
return '&';
}
/**
* identify DOS, Linux, Mac, Next and Unicode line endings
* 0 if this is no line separator
* >0 the length of the separator
* Note: input has to be UTF-8
*/
static int isLineSeparator(const unsigned char* p)
{
// Linux
if( p[0]=='\n')
return 1;
// Mac & Dos
if( p[0]=='\r')
return (p[1]=='\n') ? 2 : 1;
// Unicode (line || paragraph sep.)
if( p[0]==0xE2 && p[1]==0x80 && (p[2]==0xA8 || p[2]==0xA9))
return 3;
// Next
if( p[0]==0xC2 && p[1]==0x85)
return 2;
return 0;
}

43
dmd/html.h Normal file
View File

@@ -0,0 +1,43 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_HTML_H
#define DMD_HTML_H 1
struct OutBuffer;
struct Html
{
const char *sourcename;
unsigned char *base; // pointer to start of buffer
unsigned char *end; // past end of buffer
unsigned char *p; // current character
unsigned linnum; // current line number
OutBuffer *dbuf; // code source buffer
int inCode; // !=0 if in code
Html(const char *sourcename, unsigned char *base, unsigned length);
void error(const char *format, ...);
void extractCode(OutBuffer *buf);
void skipTag();
void skipString();
unsigned char *skipWhite(unsigned char *q);
void scanComment();
int isCommentStart();
void scanCDATA();
int isCDATAStart();
int charEntity();
static int namedEntity(unsigned char *p, int length);
};
#endif

353
dmd/id.c Normal file
View File

@@ -0,0 +1,353 @@
// File generated by idgen.c
#include "id.h"
#include "identifier.h"
#include "lexer.h"
Identifier *Id::IUnknown;
Identifier *Id::Object;
Identifier *Id::object;
Identifier *Id::max;
Identifier *Id::min;
Identifier *Id::This;
Identifier *Id::ctor;
Identifier *Id::dtor;
Identifier *Id::classInvariant;
Identifier *Id::unitTest;
Identifier *Id::staticCtor;
Identifier *Id::staticDtor;
Identifier *Id::init;
Identifier *Id::size;
Identifier *Id::__sizeof;
Identifier *Id::alignof;
Identifier *Id::mangleof;
Identifier *Id::stringof;
Identifier *Id::tupleof;
Identifier *Id::length;
Identifier *Id::remove;
Identifier *Id::ptr;
Identifier *Id::funcptr;
Identifier *Id::dollar;
Identifier *Id::offset;
Identifier *Id::offsetof;
Identifier *Id::ModuleInfo;
Identifier *Id::ClassInfo;
Identifier *Id::classinfo;
Identifier *Id::typeinfo;
Identifier *Id::outer;
Identifier *Id::Exception;
Identifier *Id::withSym;
Identifier *Id::result;
Identifier *Id::returnLabel;
Identifier *Id::delegate;
Identifier *Id::line;
Identifier *Id::empty;
Identifier *Id::p;
Identifier *Id::coverage;
Identifier *Id::TypeInfo;
Identifier *Id::TypeInfo_Class;
Identifier *Id::TypeInfo_Interface;
Identifier *Id::TypeInfo_Struct;
Identifier *Id::TypeInfo_Enum;
Identifier *Id::TypeInfo_Typedef;
Identifier *Id::TypeInfo_Pointer;
Identifier *Id::TypeInfo_Array;
Identifier *Id::TypeInfo_StaticArray;
Identifier *Id::TypeInfo_AssociativeArray;
Identifier *Id::TypeInfo_Function;
Identifier *Id::TypeInfo_Delegate;
Identifier *Id::TypeInfo_Tuple;
Identifier *Id::TypeInfo_Const;
Identifier *Id::TypeInfo_Invariant;
Identifier *Id::elements;
Identifier *Id::_arguments_typeinfo;
Identifier *Id::_arguments;
Identifier *Id::_argptr;
Identifier *Id::_match;
Identifier *Id::LINE;
Identifier *Id::FILE;
Identifier *Id::DATE;
Identifier *Id::TIME;
Identifier *Id::TIMESTAMP;
Identifier *Id::VENDOR;
Identifier *Id::VERSIONX;
Identifier *Id::nan;
Identifier *Id::infinity;
Identifier *Id::dig;
Identifier *Id::epsilon;
Identifier *Id::mant_dig;
Identifier *Id::max_10_exp;
Identifier *Id::max_exp;
Identifier *Id::min_10_exp;
Identifier *Id::min_exp;
Identifier *Id::re;
Identifier *Id::im;
Identifier *Id::C;
Identifier *Id::D;
Identifier *Id::Windows;
Identifier *Id::Pascal;
Identifier *Id::System;
Identifier *Id::exit;
Identifier *Id::success;
Identifier *Id::failure;
Identifier *Id::keys;
Identifier *Id::values;
Identifier *Id::rehash;
Identifier *Id::sort;
Identifier *Id::reverse;
Identifier *Id::dup;
Identifier *Id::idup;
Identifier *Id::___out;
Identifier *Id::___in;
Identifier *Id::__int;
Identifier *Id::__dollar;
Identifier *Id::__LOCAL_SIZE;
Identifier *Id::uadd;
Identifier *Id::neg;
Identifier *Id::com;
Identifier *Id::add;
Identifier *Id::add_r;
Identifier *Id::sub;
Identifier *Id::sub_r;
Identifier *Id::mul;
Identifier *Id::mul_r;
Identifier *Id::div;
Identifier *Id::div_r;
Identifier *Id::mod;
Identifier *Id::mod_r;
Identifier *Id::eq;
Identifier *Id::cmp;
Identifier *Id::iand;
Identifier *Id::iand_r;
Identifier *Id::ior;
Identifier *Id::ior_r;
Identifier *Id::ixor;
Identifier *Id::ixor_r;
Identifier *Id::shl;
Identifier *Id::shl_r;
Identifier *Id::shr;
Identifier *Id::shr_r;
Identifier *Id::ushr;
Identifier *Id::ushr_r;
Identifier *Id::cat;
Identifier *Id::cat_r;
Identifier *Id::assign;
Identifier *Id::addass;
Identifier *Id::subass;
Identifier *Id::mulass;
Identifier *Id::divass;
Identifier *Id::modass;
Identifier *Id::andass;
Identifier *Id::orass;
Identifier *Id::xorass;
Identifier *Id::shlass;
Identifier *Id::shrass;
Identifier *Id::ushrass;
Identifier *Id::catass;
Identifier *Id::postinc;
Identifier *Id::postdec;
Identifier *Id::index;
Identifier *Id::indexass;
Identifier *Id::slice;
Identifier *Id::sliceass;
Identifier *Id::call;
Identifier *Id::cast;
Identifier *Id::match;
Identifier *Id::next;
Identifier *Id::opIn;
Identifier *Id::opIn_r;
Identifier *Id::classNew;
Identifier *Id::classDelete;
Identifier *Id::apply;
Identifier *Id::applyReverse;
Identifier *Id::adDup;
Identifier *Id::adReverse;
Identifier *Id::aaLen;
Identifier *Id::aaKeys;
Identifier *Id::aaValues;
Identifier *Id::aaRehash;
Identifier *Id::lib;
Identifier *Id::msg;
Identifier *Id::GNU_asm;
Identifier *Id::LLVM_intrinsic;
Identifier *Id::LLVM_internal;
Identifier *Id::tohash;
Identifier *Id::tostring;
Identifier *Id::alloca;
Identifier *Id::main;
Identifier *Id::WinMain;
Identifier *Id::DllMain;
void Id::initialize()
{
IUnknown = Lexer::idPool("IUnknown");
Object = Lexer::idPool("Object");
object = Lexer::idPool("object");
max = Lexer::idPool("max");
min = Lexer::idPool("min");
This = Lexer::idPool("this");
ctor = Lexer::idPool("_ctor");
dtor = Lexer::idPool("_dtor");
classInvariant = Lexer::idPool("__invariant");
unitTest = Lexer::idPool("_unitTest");
staticCtor = Lexer::idPool("_staticCtor");
staticDtor = Lexer::idPool("_staticDtor");
init = Lexer::idPool("init");
size = Lexer::idPool("size");
__sizeof = Lexer::idPool("sizeof");
alignof = Lexer::idPool("alignof");
mangleof = Lexer::idPool("mangleof");
stringof = Lexer::idPool("stringof");
tupleof = Lexer::idPool("tupleof");
length = Lexer::idPool("length");
remove = Lexer::idPool("remove");
ptr = Lexer::idPool("ptr");
funcptr = Lexer::idPool("funcptr");
dollar = Lexer::idPool("__dollar");
offset = Lexer::idPool("offset");
offsetof = Lexer::idPool("offsetof");
ModuleInfo = Lexer::idPool("ModuleInfo");
ClassInfo = Lexer::idPool("ClassInfo");
classinfo = Lexer::idPool("classinfo");
typeinfo = Lexer::idPool("typeinfo");
outer = Lexer::idPool("outer");
Exception = Lexer::idPool("Exception");
withSym = Lexer::idPool("__withSym");
result = Lexer::idPool("__result");
returnLabel = Lexer::idPool("__returnLabel");
delegate = Lexer::idPool("delegate");
line = Lexer::idPool("line");
empty = Lexer::idPool("");
p = Lexer::idPool("p");
coverage = Lexer::idPool("__coverage");
TypeInfo = Lexer::idPool("TypeInfo");
TypeInfo_Class = Lexer::idPool("TypeInfo_Class");
TypeInfo_Interface = Lexer::idPool("TypeInfo_Interface");
TypeInfo_Struct = Lexer::idPool("TypeInfo_Struct");
TypeInfo_Enum = Lexer::idPool("TypeInfo_Enum");
TypeInfo_Typedef = Lexer::idPool("TypeInfo_Typedef");
TypeInfo_Pointer = Lexer::idPool("TypeInfo_Pointer");
TypeInfo_Array = Lexer::idPool("TypeInfo_Array");
TypeInfo_StaticArray = Lexer::idPool("TypeInfo_StaticArray");
TypeInfo_AssociativeArray = Lexer::idPool("TypeInfo_AssociativeArray");
TypeInfo_Function = Lexer::idPool("TypeInfo_Function");
TypeInfo_Delegate = Lexer::idPool("TypeInfo_Delegate");
TypeInfo_Tuple = Lexer::idPool("TypeInfo_Tuple");
TypeInfo_Const = Lexer::idPool("TypeInfo_Const");
TypeInfo_Invariant = Lexer::idPool("TypeInfo_Invariant");
elements = Lexer::idPool("elements");
_arguments_typeinfo = Lexer::idPool("_arguments_typeinfo");
_arguments = Lexer::idPool("_arguments");
_argptr = Lexer::idPool("_argptr");
_match = Lexer::idPool("_match");
LINE = Lexer::idPool("__LINE__");
FILE = Lexer::idPool("__FILE__");
DATE = Lexer::idPool("__DATE__");
TIME = Lexer::idPool("__TIME__");
TIMESTAMP = Lexer::idPool("__TIMESTAMP__");
VENDOR = Lexer::idPool("__VENDOR__");
VERSIONX = Lexer::idPool("__VERSION__");
nan = Lexer::idPool("nan");
infinity = Lexer::idPool("infinity");
dig = Lexer::idPool("dig");
epsilon = Lexer::idPool("epsilon");
mant_dig = Lexer::idPool("mant_dig");
max_10_exp = Lexer::idPool("max_10_exp");
max_exp = Lexer::idPool("max_exp");
min_10_exp = Lexer::idPool("min_10_exp");
min_exp = Lexer::idPool("min_exp");
re = Lexer::idPool("re");
im = Lexer::idPool("im");
C = Lexer::idPool("C");
D = Lexer::idPool("D");
Windows = Lexer::idPool("Windows");
Pascal = Lexer::idPool("Pascal");
System = Lexer::idPool("System");
exit = Lexer::idPool("exit");
success = Lexer::idPool("success");
failure = Lexer::idPool("failure");
keys = Lexer::idPool("keys");
values = Lexer::idPool("values");
rehash = Lexer::idPool("rehash");
sort = Lexer::idPool("sort");
reverse = Lexer::idPool("reverse");
dup = Lexer::idPool("dup");
idup = Lexer::idPool("idup");
___out = Lexer::idPool("out");
___in = Lexer::idPool("in");
__int = Lexer::idPool("int");
__dollar = Lexer::idPool("$");
__LOCAL_SIZE = Lexer::idPool("__LOCAL_SIZE");
uadd = Lexer::idPool("opPos");
neg = Lexer::idPool("opNeg");
com = Lexer::idPool("opCom");
add = Lexer::idPool("opAdd");
add_r = Lexer::idPool("opAdd_r");
sub = Lexer::idPool("opSub");
sub_r = Lexer::idPool("opSub_r");
mul = Lexer::idPool("opMul");
mul_r = Lexer::idPool("opMul_r");
div = Lexer::idPool("opDiv");
div_r = Lexer::idPool("opDiv_r");
mod = Lexer::idPool("opMod");
mod_r = Lexer::idPool("opMod_r");
eq = Lexer::idPool("opEquals");
cmp = Lexer::idPool("opCmp");
iand = Lexer::idPool("opAnd");
iand_r = Lexer::idPool("opAnd_r");
ior = Lexer::idPool("opOr");
ior_r = Lexer::idPool("opOr_r");
ixor = Lexer::idPool("opXor");
ixor_r = Lexer::idPool("opXor_r");
shl = Lexer::idPool("opShl");
shl_r = Lexer::idPool("opShl_r");
shr = Lexer::idPool("opShr");
shr_r = Lexer::idPool("opShr_r");
ushr = Lexer::idPool("opUShr");
ushr_r = Lexer::idPool("opUShr_r");
cat = Lexer::idPool("opCat");
cat_r = Lexer::idPool("opCat_r");
assign = Lexer::idPool("opAssign");
addass = Lexer::idPool("opAddAssign");
subass = Lexer::idPool("opSubAssign");
mulass = Lexer::idPool("opMulAssign");
divass = Lexer::idPool("opDivAssign");
modass = Lexer::idPool("opModAssign");
andass = Lexer::idPool("opAndAssign");
orass = Lexer::idPool("opOrAssign");
xorass = Lexer::idPool("opXorAssign");
shlass = Lexer::idPool("opShlAssign");
shrass = Lexer::idPool("opShrAssign");
ushrass = Lexer::idPool("opUShrAssign");
catass = Lexer::idPool("opCatAssign");
postinc = Lexer::idPool("opPostInc");
postdec = Lexer::idPool("opPostDec");
index = Lexer::idPool("opIndex");
indexass = Lexer::idPool("opIndexAssign");
slice = Lexer::idPool("opSlice");
sliceass = Lexer::idPool("opSliceAssign");
call = Lexer::idPool("opCall");
cast = Lexer::idPool("opCast");
match = Lexer::idPool("opMatch");
next = Lexer::idPool("opNext");
opIn = Lexer::idPool("opIn");
opIn_r = Lexer::idPool("opIn_r");
classNew = Lexer::idPool("new");
classDelete = Lexer::idPool("delete");
apply = Lexer::idPool("opApply");
applyReverse = Lexer::idPool("opApplyReverse");
adDup = Lexer::idPool("_adDupT");
adReverse = Lexer::idPool("_adReverse");
aaLen = Lexer::idPool("_aaLen");
aaKeys = Lexer::idPool("_aaKeys");
aaValues = Lexer::idPool("_aaValues");
aaRehash = Lexer::idPool("_aaRehash");
lib = Lexer::idPool("lib");
msg = Lexer::idPool("msg");
GNU_asm = Lexer::idPool("GNU_asm");
LLVM_intrinsic = Lexer::idPool("LLVM_intrinsic");
LLVM_internal = Lexer::idPool("LLVM_internal");
tohash = Lexer::idPool("toHash");
tostring = Lexer::idPool("toString");
alloca = Lexer::idPool("alloca");
main = Lexer::idPool("main");
WinMain = Lexer::idPool("WinMain");
DllMain = Lexer::idPool("DllMain");
}

182
dmd/id.h Normal file
View File

@@ -0,0 +1,182 @@
// File generated by idgen.c
#ifndef DMD_ID_H
#define DMD_ID_H 1
struct Identifier;
struct Id
{
static Identifier *IUnknown;
static Identifier *Object;
static Identifier *object;
static Identifier *max;
static Identifier *min;
static Identifier *This;
static Identifier *ctor;
static Identifier *dtor;
static Identifier *classInvariant;
static Identifier *unitTest;
static Identifier *staticCtor;
static Identifier *staticDtor;
static Identifier *init;
static Identifier *size;
static Identifier *__sizeof;
static Identifier *alignof;
static Identifier *mangleof;
static Identifier *stringof;
static Identifier *tupleof;
static Identifier *length;
static Identifier *remove;
static Identifier *ptr;
static Identifier *funcptr;
static Identifier *dollar;
static Identifier *offset;
static Identifier *offsetof;
static Identifier *ModuleInfo;
static Identifier *ClassInfo;
static Identifier *classinfo;
static Identifier *typeinfo;
static Identifier *outer;
static Identifier *Exception;
static Identifier *withSym;
static Identifier *result;
static Identifier *returnLabel;
static Identifier *delegate;
static Identifier *line;
static Identifier *empty;
static Identifier *p;
static Identifier *coverage;
static Identifier *TypeInfo;
static Identifier *TypeInfo_Class;
static Identifier *TypeInfo_Interface;
static Identifier *TypeInfo_Struct;
static Identifier *TypeInfo_Enum;
static Identifier *TypeInfo_Typedef;
static Identifier *TypeInfo_Pointer;
static Identifier *TypeInfo_Array;
static Identifier *TypeInfo_StaticArray;
static Identifier *TypeInfo_AssociativeArray;
static Identifier *TypeInfo_Function;
static Identifier *TypeInfo_Delegate;
static Identifier *TypeInfo_Tuple;
static Identifier *TypeInfo_Const;
static Identifier *TypeInfo_Invariant;
static Identifier *elements;
static Identifier *_arguments_typeinfo;
static Identifier *_arguments;
static Identifier *_argptr;
static Identifier *_match;
static Identifier *LINE;
static Identifier *FILE;
static Identifier *DATE;
static Identifier *TIME;
static Identifier *TIMESTAMP;
static Identifier *VENDOR;
static Identifier *VERSIONX;
static Identifier *nan;
static Identifier *infinity;
static Identifier *dig;
static Identifier *epsilon;
static Identifier *mant_dig;
static Identifier *max_10_exp;
static Identifier *max_exp;
static Identifier *min_10_exp;
static Identifier *min_exp;
static Identifier *re;
static Identifier *im;
static Identifier *C;
static Identifier *D;
static Identifier *Windows;
static Identifier *Pascal;
static Identifier *System;
static Identifier *exit;
static Identifier *success;
static Identifier *failure;
static Identifier *keys;
static Identifier *values;
static Identifier *rehash;
static Identifier *sort;
static Identifier *reverse;
static Identifier *dup;
static Identifier *idup;
static Identifier *___out;
static Identifier *___in;
static Identifier *__int;
static Identifier *__dollar;
static Identifier *__LOCAL_SIZE;
static Identifier *uadd;
static Identifier *neg;
static Identifier *com;
static Identifier *add;
static Identifier *add_r;
static Identifier *sub;
static Identifier *sub_r;
static Identifier *mul;
static Identifier *mul_r;
static Identifier *div;
static Identifier *div_r;
static Identifier *mod;
static Identifier *mod_r;
static Identifier *eq;
static Identifier *cmp;
static Identifier *iand;
static Identifier *iand_r;
static Identifier *ior;
static Identifier *ior_r;
static Identifier *ixor;
static Identifier *ixor_r;
static Identifier *shl;
static Identifier *shl_r;
static Identifier *shr;
static Identifier *shr_r;
static Identifier *ushr;
static Identifier *ushr_r;
static Identifier *cat;
static Identifier *cat_r;
static Identifier *assign;
static Identifier *addass;
static Identifier *subass;
static Identifier *mulass;
static Identifier *divass;
static Identifier *modass;
static Identifier *andass;
static Identifier *orass;
static Identifier *xorass;
static Identifier *shlass;
static Identifier *shrass;
static Identifier *ushrass;
static Identifier *catass;
static Identifier *postinc;
static Identifier *postdec;
static Identifier *index;
static Identifier *indexass;
static Identifier *slice;
static Identifier *sliceass;
static Identifier *call;
static Identifier *cast;
static Identifier *match;
static Identifier *next;
static Identifier *opIn;
static Identifier *opIn_r;
static Identifier *classNew;
static Identifier *classDelete;
static Identifier *apply;
static Identifier *applyReverse;
static Identifier *adDup;
static Identifier *adReverse;
static Identifier *aaLen;
static Identifier *aaKeys;
static Identifier *aaValues;
static Identifier *aaRehash;
static Identifier *lib;
static Identifier *msg;
static Identifier *GNU_asm;
static Identifier *LLVM_intrinsic;
static Identifier *LLVM_internal;
static Identifier *tohash;
static Identifier *tostring;
static Identifier *alloca;
static Identifier *main;
static Identifier *WinMain;
static Identifier *DllMain;
static void initialize();
};
#endif

89
dmd/identifier.c Normal file
View File

@@ -0,0 +1,89 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include "root.h"
#include "identifier.h"
#include "mars.h"
#include "lexer.h"
#include "id.h"
Identifier::Identifier(const char *string, int value)
{
//printf("Identifier('%s', %d)\n", string, value);
this->string = string;
this->value = value;
this->len = strlen(string);
}
hash_t Identifier::hashCode()
{
return String::calcHash(string);
}
int Identifier::equals(Object *o)
{
return this == o || memcmp(string,o->toChars(),len+1) == 0;
}
int Identifier::compare(Object *o)
{
return memcmp(string, o->toChars(), len + 1);
}
char *Identifier::toChars()
{
return (char *)string;
}
char *Identifier::toHChars2()
{
char *p = NULL;
if (this == Id::ctor) p = "this";
else if (this == Id::dtor) p = "~this";
else if (this == Id::classInvariant) p = "invariant";
else if (this == Id::unitTest) p = "unittest";
else if (this == Id::staticCtor) p = "static this";
else if (this == Id::staticDtor) p = "static ~this";
else if (this == Id::dollar) p = "$";
else if (this == Id::withSym) p = "with";
else if (this == Id::result) p = "result";
else if (this == Id::returnLabel) p = "return";
else
p = toChars();
return p;
}
void Identifier::print()
{
fprintf(stdmsg, "%s",string);
}
int Identifier::dyncast()
{
return DYNCAST_IDENTIFIER;
}
Identifier *Identifier::generateId(char *prefix)
{ OutBuffer buf;
char *id;
static unsigned i;
buf.writestring(prefix);
buf.printf("%u", ++i);
id = buf.toChars();
buf.data = NULL;
return new Identifier(id, TOKidentifier);
}

46
dmd/identifier.h Normal file
View File

@@ -0,0 +1,46 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_IDENTIFIER_H
#define DMD_IDENTIFIER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
namespace llvm
{
class Value;
}
struct Identifier : Object
{
int value;
const char *string;
unsigned len;
Identifier(const char *string, int value);
int equals(Object *o);
hash_t hashCode();
int compare(Object *o);
void print();
char *toChars();
#ifdef _DH
char *toHChars();
#endif
char *toHChars2();
int dyncast();
static Identifier *generateId(char *prefix);
};
#endif /* DMD_IDENTIFIER_H */

304
dmd/idgen.c Normal file
View File

@@ -0,0 +1,304 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
// Program to generate string files in d data structures.
// Saves much tedious typing, and eliminates typo problems.
// Generates:
// id.h
// id.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
struct Msgtable
{
char *ident; // name to use in DMD source
char *name; // name in D executable
};
Msgtable msgtable[] =
{
{ "IUnknown" },
{ "Object" },
{ "object" },
{ "max" },
{ "min" },
{ "This", "this" },
{ "ctor", "_ctor" },
{ "dtor", "_dtor" },
{ "classInvariant", "__invariant" },
{ "unitTest", "_unitTest" },
{ "staticCtor", "_staticCtor" },
{ "staticDtor", "_staticDtor" },
{ "init" },
{ "size" },
{ "__sizeof", "sizeof" },
{ "alignof" },
{ "mangleof" },
{ "stringof" },
{ "tupleof" },
{ "length" },
{ "remove" },
{ "ptr" },
{ "funcptr" },
{ "dollar", "__dollar" },
{ "offset" },
{ "offsetof" },
{ "ModuleInfo" },
{ "ClassInfo" },
{ "classinfo" },
{ "typeinfo" },
{ "outer" },
{ "Exception" },
{ "withSym", "__withSym" },
{ "result", "__result" },
{ "returnLabel", "__returnLabel" },
{ "delegate" },
{ "line" },
{ "empty", "" },
{ "p" },
{ "coverage", "__coverage" },
{ "TypeInfo" },
{ "TypeInfo_Class" },
{ "TypeInfo_Interface" },
{ "TypeInfo_Struct" },
{ "TypeInfo_Enum" },
{ "TypeInfo_Typedef" },
{ "TypeInfo_Pointer" },
{ "TypeInfo_Array" },
{ "TypeInfo_StaticArray" },
{ "TypeInfo_AssociativeArray" },
{ "TypeInfo_Function" },
{ "TypeInfo_Delegate" },
{ "TypeInfo_Tuple" },
{ "TypeInfo_Const" },
{ "TypeInfo_Invariant" },
{ "elements" },
{ "_arguments_typeinfo" },
{ "_arguments" },
{ "_argptr" },
{ "_match" },
{ "LINE", "__LINE__" },
{ "FILE", "__FILE__" },
{ "DATE", "__DATE__" },
{ "TIME", "__TIME__" },
{ "TIMESTAMP", "__TIMESTAMP__" },
{ "VENDOR", "__VENDOR__" },
{ "VERSIONX", "__VERSION__" },
{ "nan" },
{ "infinity" },
{ "dig" },
{ "epsilon" },
{ "mant_dig" },
{ "max_10_exp" },
{ "max_exp" },
{ "min_10_exp" },
{ "min_exp" },
{ "re" },
{ "im" },
{ "C" },
{ "D" },
{ "Windows" },
{ "Pascal" },
{ "System" },
{ "exit" },
{ "success" },
{ "failure" },
{ "keys" },
{ "values" },
{ "rehash" },
{ "sort" },
{ "reverse" },
{ "dup" },
{ "idup" },
// For inline assembler
{ "___out", "out" },
{ "___in", "in" },
{ "__int", "int" },
{ "__dollar", "$" },
{ "__LOCAL_SIZE" },
// For operator overloads
{ "uadd", "opPos" },
{ "neg", "opNeg" },
{ "com", "opCom" },
{ "add", "opAdd" },
{ "add_r", "opAdd_r" },
{ "sub", "opSub" },
{ "sub_r", "opSub_r" },
{ "mul", "opMul" },
{ "mul_r", "opMul_r" },
{ "div", "opDiv" },
{ "div_r", "opDiv_r" },
{ "mod", "opMod" },
{ "mod_r", "opMod_r" },
{ "eq", "opEquals" },
{ "cmp", "opCmp" },
{ "iand", "opAnd" },
{ "iand_r", "opAnd_r" },
{ "ior", "opOr" },
{ "ior_r", "opOr_r" },
{ "ixor", "opXor" },
{ "ixor_r", "opXor_r" },
{ "shl", "opShl" },
{ "shl_r", "opShl_r" },
{ "shr", "opShr" },
{ "shr_r", "opShr_r" },
{ "ushr", "opUShr" },
{ "ushr_r", "opUShr_r" },
{ "cat", "opCat" },
{ "cat_r", "opCat_r" },
{ "assign", "opAssign" },
{ "addass", "opAddAssign" },
{ "subass", "opSubAssign" },
{ "mulass", "opMulAssign" },
{ "divass", "opDivAssign" },
{ "modass", "opModAssign" },
{ "andass", "opAndAssign" },
{ "orass", "opOrAssign" },
{ "xorass", "opXorAssign" },
{ "shlass", "opShlAssign" },
{ "shrass", "opShrAssign" },
{ "ushrass", "opUShrAssign" },
{ "catass", "opCatAssign" },
{ "postinc", "opPostInc" },
{ "postdec", "opPostDec" },
{ "index", "opIndex" },
{ "indexass", "opIndexAssign" },
{ "slice", "opSlice" },
{ "sliceass", "opSliceAssign" },
{ "call", "opCall" },
{ "cast", "opCast" },
{ "match", "opMatch" },
{ "next", "opNext" },
{ "opIn" },
{ "opIn_r" },
{ "classNew", "new" },
{ "classDelete", "delete" },
// For foreach
{ "apply", "opApply" },
{ "applyReverse", "opApplyReverse" },
{ "adDup", "_adDupT" },
{ "adReverse", "_adReverse" },
// For internal functions
{ "aaLen", "_aaLen" },
{ "aaKeys", "_aaKeys" },
{ "aaValues", "_aaValues" },
{ "aaRehash", "_aaRehash" },
// For pragma's
{ "lib" },
{ "msg" },
{ "GNU_asm" },
{ "LLVM_intrinsic" },
{ "LLVM_internal" },
// For toHash/toString
{ "tohash", "toHash" },
{ "tostring", "toString" },
// Special functions
{ "alloca" },
{ "main" },
{ "WinMain" },
{ "DllMain" },
};
int main()
{
FILE *fp;
unsigned i;
{
fp = fopen("id.h","w");
if (!fp)
{ printf("can't open id.h\n");
exit(EXIT_FAILURE);
}
fprintf(fp, "// File generated by idgen.c\n");
#if __DMC__
fprintf(fp, "#pragma once\n");
#endif
fprintf(fp, "#ifndef DMD_ID_H\n");
fprintf(fp, "#define DMD_ID_H 1\n");
fprintf(fp, "struct Identifier;\n");
fprintf(fp, "struct Id\n");
fprintf(fp, "{\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ char *id = msgtable[i].ident;
fprintf(fp," static Identifier *%s;\n", id);
}
fprintf(fp, " static void initialize();\n");
fprintf(fp, "};\n");
fprintf(fp, "#endif\n");
fclose(fp);
}
{
fp = fopen("id.c","w");
if (!fp)
{ printf("can't open id.c\n");
exit(EXIT_FAILURE);
}
fprintf(fp, "// File generated by idgen.c\n");
fprintf(fp, "#include \"id.h\"\n");
fprintf(fp, "#include \"identifier.h\"\n");
fprintf(fp, "#include \"lexer.h\"\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ char *id = msgtable[i].ident;
char *p = msgtable[i].name;
if (!p)
p = id;
fprintf(fp,"Identifier *Id::%s;\n", id);
}
fprintf(fp, "void Id::initialize()\n");
fprintf(fp, "{\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ char *id = msgtable[i].ident;
char *p = msgtable[i].name;
if (!p)
p = id;
fprintf(fp," %s = Lexer::idPool(\"%s\");\n", id, p);
}
fprintf(fp, "}\n");
fclose(fp);
}
return EXIT_SUCCESS;
}

440
dmd/impcnvgen.c Normal file
View File

@@ -0,0 +1,440 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include "mtype.h"
enum TY impcnvResult[TMAX][TMAX];
enum TY impcnvType1[TMAX][TMAX];
enum TY impcnvType2[TMAX][TMAX];
int impcnvWarn[TMAX][TMAX];
int integral_promotion(int t)
{
switch (t)
{
case Tchar:
case Twchar:
case Tbit:
case Tbool:
case Tint8:
case Tuns8:
case Tint16:
case Tuns16: return Tint32;
case Tdchar: return Tuns32;
default: return t;
}
}
void init()
{ int i, j;
// Set conversion tables
for (i = 0; i < TMAX; i++)
for (j = 0; j < TMAX; j++)
{ impcnvResult[i][j] = Terror;
impcnvType1[i][j] = Terror;
impcnvType2[i][j] = Terror;
impcnvWarn[i][j] = 0;
}
#define X(t1,t2, nt1,nt2, rt) \
impcnvResult[t1][t2] = rt; \
impcnvType1[t1][t2] = nt1; \
impcnvType2[t1][t2] = nt2;
/* ======================= */
X(Tbit,Tbit, Tint32,Tint32, Tint32)
X(Tbit,Tint8, Tint32,Tint32, Tint32)
X(Tbit,Tuns8, Tint32,Tint32, Tint32)
X(Tbit,Tint16, Tint32,Tint32, Tint32)
X(Tbit,Tuns16, Tint32,Tint32, Tint32)
X(Tbit,Tint32, Tint32,Tint32, Tint32)
X(Tbit,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tbit,Tint64, Tint64,Tint64, Tint64)
X(Tbit,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tbit,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tbit,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tbit,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tbit,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tbit,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tbit,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tbit,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tbit,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tbit,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tbool,Tbool, Tbool,Tbool, Tbool)
X(Tbool,Tint8, Tint32,Tint32, Tint32)
X(Tbool,Tuns8, Tint32,Tint32, Tint32)
X(Tbool,Tint16, Tint32,Tint32, Tint32)
X(Tbool,Tuns16, Tint32,Tint32, Tint32)
X(Tbool,Tint32, Tint32,Tint32, Tint32)
X(Tbool,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tbool,Tint64, Tint64,Tint64, Tint64)
X(Tbool,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tbool,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tbool,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tbool,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tbool,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tbool,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tbool,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tbool,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tbool,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tbool,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tint8,Tint8, Tint32,Tint32, Tint32)
X(Tint8,Tuns8, Tint32,Tint32, Tint32)
X(Tint8,Tint16, Tint32,Tint32, Tint32)
X(Tint8,Tuns16, Tint32,Tint32, Tint32)
X(Tint8,Tint32, Tint32,Tint32, Tint32)
X(Tint8,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tint8,Tint64, Tint64,Tint64, Tint64)
X(Tint8,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tint8,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tint8,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tint8,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tint8,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tint8,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tint8,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tint8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tint8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tint8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tuns8,Tuns8, Tint32,Tint32, Tint32)
X(Tuns8,Tint16, Tint32,Tint32, Tint32)
X(Tuns8,Tuns16, Tint32,Tint32, Tint32)
X(Tuns8,Tint32, Tint32,Tint32, Tint32)
X(Tuns8,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tuns8,Tint64, Tint64,Tint64, Tint64)
X(Tuns8,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tuns8,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tuns8,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tuns8,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tuns8,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tuns8,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tuns8,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tuns8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tuns8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tuns8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tint16,Tint16, Tint32,Tint32, Tint32)
X(Tint16,Tuns16, Tint32,Tint32, Tint32)
X(Tint16,Tint32, Tint32,Tint32, Tint32)
X(Tint16,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tint16,Tint64, Tint64,Tint64, Tint64)
X(Tint16,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tint16,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tint16,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tint16,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tint16,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tint16,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tint16,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tint16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tint16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tint16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tuns16,Tuns16, Tint32,Tint32, Tint32)
X(Tuns16,Tint32, Tint32,Tint32, Tint32)
X(Tuns16,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tuns16,Tint64, Tint64,Tint64, Tint64)
X(Tuns16,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tuns16,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tuns16,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tuns16,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tuns16,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tuns16,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tuns16,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tuns16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tuns16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tuns16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tint32,Tint32, Tint32,Tint32, Tint32)
X(Tint32,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tint32,Tint64, Tint64,Tint64, Tint64)
X(Tint32,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tint32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tint32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tint32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tint32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tint32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tint32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tint32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tint32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tint32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tuns32,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tuns32,Tint64, Tint64,Tint64, Tint64)
X(Tuns32,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tuns32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tuns32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tuns32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tuns32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tuns32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tuns32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tuns32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tuns32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tuns32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tint64,Tint64, Tint64,Tint64, Tint64)
X(Tint64,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tint64,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tint64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tint64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tint64,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tint64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tint64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tint64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tint64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tint64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tuns64,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tuns64,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tuns64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tuns64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tuns64,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tuns64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tuns64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tuns64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tuns64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tuns64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tfloat32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tfloat32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tfloat32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tfloat32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tfloat32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tfloat32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tfloat32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tfloat32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tfloat64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tfloat64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tfloat64,Timaginary32, Tfloat64,Timaginary64, Tfloat64)
X(Tfloat64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tfloat64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat64,Tcomplex32, Tfloat64,Tcomplex64, Tcomplex64)
X(Tfloat64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tfloat64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tfloat80,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tfloat80,Timaginary32, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat80,Timaginary64, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat80,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat80,Tcomplex32, Tfloat80,Tcomplex80, Tcomplex80)
X(Tfloat80,Tcomplex64, Tfloat80,Tcomplex80, Tcomplex80)
X(Tfloat80,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Timaginary32,Timaginary32, Timaginary32,Timaginary32, Timaginary32)
X(Timaginary32,Timaginary64, Timaginary64,Timaginary64, Timaginary64)
X(Timaginary32,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
X(Timaginary32,Tcomplex32, Timaginary32,Tcomplex32, Tcomplex32)
X(Timaginary32,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64)
X(Timaginary32,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Timaginary64,Timaginary64, Timaginary64,Timaginary64, Timaginary64)
X(Timaginary64,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
X(Timaginary64,Tcomplex32, Timaginary64,Tcomplex64, Tcomplex64)
X(Timaginary64,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64)
X(Timaginary64,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Timaginary80,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
X(Timaginary80,Tcomplex32, Timaginary80,Tcomplex80, Tcomplex80)
X(Timaginary80,Tcomplex64, Timaginary80,Tcomplex80, Tcomplex80)
X(Timaginary80,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tcomplex32,Tcomplex32, Tcomplex32,Tcomplex32, Tcomplex32)
X(Tcomplex32,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64)
X(Tcomplex32,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tcomplex64,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64)
X(Tcomplex64,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
#undef X
#define Y(t1,t2) impcnvWarn[t1][t2] = 1;
Y(Tint8, Tbit)
Y(Tuns8, Tbit)
Y(Tint16, Tbit)
Y(Tuns16, Tbit)
Y(Tint32, Tbit)
Y(Tuns32, Tbit)
Y(Tint64, Tbit)
Y(Tuns64, Tbit)
Y(Tuns8, Tint8)
Y(Tint16, Tint8)
Y(Tuns16, Tint8)
Y(Tint32, Tint8)
Y(Tuns32, Tint8)
Y(Tint64, Tint8)
Y(Tuns64, Tint8)
Y(Tint8, Tuns8)
Y(Tint16, Tuns8)
Y(Tuns16, Tuns8)
Y(Tint32, Tuns8)
Y(Tuns32, Tuns8)
Y(Tint64, Tuns8)
Y(Tuns64, Tuns8)
Y(Tuns16, Tint16)
Y(Tint32, Tint16)
Y(Tuns32, Tint16)
Y(Tint64, Tint16)
Y(Tuns64, Tint16)
Y(Tint16, Tuns16)
Y(Tint32, Tuns16)
Y(Tuns32, Tuns16)
Y(Tint64, Tuns16)
Y(Tuns64, Tuns16)
// Y(Tuns32, Tint32)
Y(Tint64, Tint32)
Y(Tuns64, Tint32)
// Y(Tint32, Tuns32)
Y(Tint64, Tuns32)
Y(Tuns64, Tuns32)
Y(Tint64, Tuns64)
Y(Tuns64, Tint64)
for (i = 0; i < TMAX; i++)
for (j = 0; j < TMAX; j++)
{
if (impcnvResult[i][j] == Terror)
{
impcnvResult[i][j] = impcnvResult[j][i];
impcnvType1[i][j] = impcnvType2[j][i];
impcnvType2[i][j] = impcnvType1[j][i];
}
}
}
int main()
{ FILE *fp;
int i;
int j;
init();
fp = fopen("impcnvtab.c","w");
fprintf(fp,"// This file is generated by impcnvgen.c\n");
fprintf(fp,"#include \"mtype.h\"\n");
fprintf(fp,"unsigned char Type::impcnvResult[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvResult[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvType1[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvType1[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvType2[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvType2[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvWarn[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvWarn[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp,"};\n");
fclose(fp);
return EXIT_SUCCESS;
}

178
dmd/impcnvtab.c Normal file
View File

@@ -0,0 +1,178 @@
// This file is generated by impcnvgen.c
#include "mtype.h"
unsigned char Type::impcnvResult[TMAX][TMAX] =
{
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,28,29,30,19,19,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,28,29,30,20,20,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,28,29,30,21,21,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,28,29,30,22,22,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,29,29,30,23,23,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,30,30,30,24,24,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,22,22,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,23,23,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,24,24,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,28,28,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,29,29,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,32,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
};
unsigned char Type::impcnvType1[TMAX][TMAX] =
{
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,22,23,24,19,19,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,22,23,24,20,20,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,22,23,24,21,21,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,22,23,24,22,22,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,23,23,24,23,23,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,25,25,25,25,25,25,25,25,25,26,27,25,26,27,25,26,27,25,25,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,26,26,26,26,26,26,26,26,26,26,27,26,26,27,26,26,27,26,26,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,28,28,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,29,29,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,32,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
};
unsigned char Type::impcnvType2[TMAX][TMAX] =
{
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,18,18,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,19,19,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,20,20,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,21,21,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,22,22,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,23,23,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,24,24,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,22,22,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,23,23,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,24,24,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,22,22,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,23,23,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,24,24,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,32,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
};
unsigned char Type::impcnvWarn[TMAX][TMAX] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};

268
dmd/import.c Normal file
View File

@@ -0,0 +1,268 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "dsymbol.h"
#include "import.h"
#include "identifier.h"
#include "module.h"
#include "scope.h"
#include "hdrgen.h"
#include "mtype.h"
#include "declaration.h"
#include "id.h"
/********************************* Import ****************************/
Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(id)
{
this->loc = loc;
this->packages = packages;
this->id = id;
this->aliasId = aliasId;
this->isstatic = isstatic;
pkg = NULL;
mod = NULL;
if (aliasId)
this->ident = aliasId;
// Kludge to change Import identifier to first package
else if (packages && packages->dim)
this->ident = (Identifier *)packages->data[0];
}
void Import::addAlias(Identifier *name, Identifier *alias)
{
if (isstatic)
error("cannot have an import bind list");
if (!aliasId)
this->ident = NULL; // make it an anonymous import
names.push(name);
aliases.push(alias);
}
char *Import::kind()
{
return isstatic ? (char *)"static import" : (char *)"import";
}
Dsymbol *Import::syntaxCopy(Dsymbol *s)
{
assert(!s);
Import *si;
si = new Import(loc, packages, id, aliasId, isstatic);
for (size_t i = 0; i < names.dim; i++)
{
si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
}
return si;
}
void Import::load(Scope *sc)
{
DsymbolTable *dst;
Dsymbol *s;
//printf("Import::load('%s')\n", toChars());
// See if existing module
dst = Package::resolve(packages, NULL, &pkg);
s = dst->lookup(id);
if (s)
{
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
}
if (!mod)
{
// Load module
mod = Module::load(loc, packages, id);
dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias
if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
}
if (!pkg)
pkg = mod;
mod->semantic();
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s')\n", toChars());
load(sc);
if (mod)
{
#if 0
if (mod->loc.linnum != 0)
{ /* If the line number is not 0, then this is not
* a 'root' module, i.e. it was not specified on the command line.
*/
mod->importedFrom = sc->module->importedFrom;
assert(mod->importedFrom);
}
#endif
if (!isstatic && !aliasId && !names.dim)
{
/* Default to private importing
*/
enum PROT prot = sc->protection;
if (!sc->explicitProtection)
prot = PROTprivate;
sc->scopesym->importScope(mod, prot);
}
// Modules need a list of each imported module
sc->module->aimports.push(mod);
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
sc = sc->push(mod);
for (size_t i = 0; i < aliasdecls.dim; i++)
{ Dsymbol *s = (Dsymbol *)aliasdecls.data[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, (Identifier *)names.data[i], 0))
error("%s not found", ((Identifier *)names.data[i])->toChars());
s->semantic(sc);
}
sc = sc->pop();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic2(Scope *sc)
{
//printf("Import::semantic2('%s')\n", toChars());
mod->semantic2();
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
}
Dsymbol *Import::toAlias()
{
if (aliasId)
return mod;
return this;
}
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
int result = 0;
if (names.dim == 0)
return Dsymbol::addMember(sc, sd, memnum);
if (aliasId)
result = Dsymbol::addMember(sc, sd, memnum);
for (size_t i = 0; i < names.dim; i++)
{
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias)
alias = name;
#if 1
TypeIdentifier *tname = new TypeIdentifier(loc, name);
#else
TypeIdentifier *tname = new TypeIdentifier(loc, NULL);
if (packages)
{
for (size_t j = 0; j < packages->dim; j++)
{ Identifier *pid = (Identifier *)packages->data[j];
if (!tname->ident)
tname->ident = pid;
else
tname->addIdent(pid);
}
}
if (!tname->ident)
tname->ident = id;
else
tname->addIdent(id);
tname->addIdent(name);
#endif
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
result |= ad->addMember(sc, sd, memnum);
aliasdecls.push(ad);
}
return result;
}
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
{
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
if (!pkg)
load(NULL);
// Forward it to the package/module
return pkg->search(loc, ident, flags);
}
int Import::overloadInsert(Dsymbol *s)
{
// Allow multiple imports of the same name
return s->isImport() != NULL;
}
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (hgs->hdrgen && id == Id::object)
return; // object is imported by default
if (isstatic)
buf->writestring("static ");
buf->writestring("import ");
if (aliasId)
{
buf->printf("%s = ", aliasId->toChars());
}
if (packages && packages->dim)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
buf->printf("%s.", pid->toChars());
}
}
buf->printf("%s;", id->toChars());
buf->writenl();
}

65
dmd/import.h Normal file
View File

@@ -0,0 +1,65 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_IMPORT_H
#define DMD_IMPORT_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Identifier;
struct Scope;
struct OutBuffer;
struct Module;
struct Package;
struct AliasDeclaration;
#ifdef _DH
struct HdrGenState;
#endif
struct Import : Dsymbol
{
Array *packages; // array of Identifier's representing packages
Identifier *id; // module Identifier
Identifier *aliasId;
int isstatic; // !=0 if static import
// Pairs of alias=name to bind into current namespace
Array names;
Array aliases;
Array aliasdecls; // AliasDeclarations for names/aliases
Module *mod;
Package *pkg; // leftmost package/module
Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic);
void addAlias(Identifier *name, Identifier *alias);
char *kind();
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
void load(Scope *sc);
void semantic(Scope *sc);
void semantic2(Scope *sc);
Dsymbol *toAlias();
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Import *isImport() { return this; }
};
#endif /* DMD_IMPORT_H */

272
dmd/inifile.c Normal file
View File

@@ -0,0 +1,272 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "root.h"
#include "mem.h"
#define LOG 0
char *skipspace(const char *p);
#if __GNUC__
char *strupr(char *s)
{
char *t = s;
while (*s)
{
*s = toupper(*s);
s++;
}
return t;
}
#endif /* unix */
/*****************************
* Read and analyze .ini file.
* Input:
* argv0 program name (argv[0])
* inifile .ini file name
*/
void inifile(char *argv0, char *inifile)
{
char *path; // need path for @P macro
char *filename;
OutBuffer buf;
int i;
int k;
int envsection = 0;
#if LOG
printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
#endif
if (FileName::absolute(inifile))
{
filename = inifile;
}
else
{
/* Look for inifile in the following sequence of places:
* o current directory
* o home directory
* o directory off of argv0
* o /etc/
*/
if (FileName::exists(inifile))
{
filename = inifile;
}
else
{
filename = FileName::combine(getenv("HOME"), inifile);
if (!FileName::exists(filename))
{
filename = FileName::replaceName(argv0, inifile);
if (!FileName::exists(filename))
{
#if linux
// Search PATH for argv0
const char *p = getenv("PATH");
Array *paths = FileName::splitPath(p);
filename = FileName::searchPath(paths, argv0, 0);
if (!filename)
goto Letc; // argv0 not found on path
filename = FileName::replaceName(filename, inifile);
if (FileName::exists(filename))
goto Ldone;
#endif
// Search /etc/ for inifile
Letc:
filename = FileName::combine("/etc/", inifile);
Ldone:
;
}
}
}
}
path = FileName::path(filename);
#if LOG
printf("\tpath = '%s', filename = '%s'\n", path, filename);
#endif
File file(filename);
if (file.read())
return; // error reading file
// Parse into lines
int eof = 0;
for (i = 0; i < file.len && !eof; i++)
{
int linestart = i;
for (; i < file.len; i++)
{
switch (file.buffer[i])
{
case '\r':
break;
case '\n':
// Skip if it was preceded by '\r'
if (i && file.buffer[i - 1] == '\r')
goto Lskip;
break;
case 0:
case 0x1A:
eof = 1;
break;
default:
continue;
}
break;
}
// The line is file.buffer[linestart..i]
char *line;
int len;
char *p;
char *pn;
line = (char *)&file.buffer[linestart];
len = i - linestart;
buf.reset();
// First, expand the macros.
// Macros are bracketed by % characters.
for (k = 0; k < len; k++)
{
if (line[k] == '%')
{
int j;
for (j = k + 1; j < len; j++)
{
if (line[j] == '%')
{
if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
{
// %@P% is special meaning the path to the .ini file
p = path;
if (!*p)
p = ".";
}
else
{ int len = j - k;
char tmp[10]; // big enough most of the time
if (len <= sizeof(tmp))
p = tmp;
else
p = (char *)alloca(len);
len--;
memcpy(p, &line[k + 1], len);
p[len] = 0;
strupr(p);
p = getenv(p);
if (!p)
p = "";
}
buf.writestring(p);
k = j;
goto L1;
}
}
}
buf.writeByte(line[k]);
L1:
;
}
// Remove trailing spaces
while (buf.offset && isspace(buf.data[buf.offset - 1]))
buf.offset--;
p = buf.toChars();
// The expanded line is in p.
// Now parse it for meaning.
p = skipspace(p);
switch (*p)
{
case ';': // comment
case 0: // blank
break;
case '[': // look for [Environment]
p = skipspace(p + 1);
for (pn = p; isalnum(*pn); pn++)
;
if (pn - p == 11 &&
memicmp(p, "Environment", 11) == 0 &&
*skipspace(pn) == ']'
)
envsection = 1;
else
envsection = 0;
break;
default:
if (envsection)
{
pn = p;
// Convert name to upper case;
// remove spaces bracketing =
for (p = pn; *p; p++)
{ if (islower(*p))
*p &= ~0x20;
else if (isspace(*p))
memmove(p, p + 1, strlen(p));
else if (*p == '=')
{
p++;
while (isspace(*p))
memmove(p, p + 1, strlen(p));
break;
}
}
putenv(strdup(pn));
#if LOG
printf("\tputenv('%s')\n", pn);
//printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
#endif
}
break;
}
Lskip:
;
}
}
/********************
* Skip spaces.
*/
char *skipspace(const char *p)
{
while (isspace(*p))
p++;
return (char *)p;
}

550
dmd/init.c Normal file
View File

@@ -0,0 +1,550 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "mars.h"
#include "init.h"
#include "expression.h"
#include "statement.h"
#include "identifier.h"
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
#include "mtype.h"
#include "hdrgen.h"
/********************************** Initializer *******************************/
Initializer::Initializer(Loc loc)
{
this->loc = loc;
}
Initializer *Initializer::syntaxCopy()
{
return this;
}
Initializer *Initializer::semantic(Scope *sc, Type *t)
{
return this;
}
Type *Initializer::inferType(Scope *sc)
{
error(loc, "cannot infer type from initializer");
return Type::terror;
}
Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
{ Initializers *a = NULL;
if (ai)
{
a = new Initializers();
a->setDim(ai->dim);
for (int i = 0; i < a->dim; i++)
{ Initializer *e = (Initializer *)ai->data[i];
e = e->syntaxCopy();
a->data[i] = e;
}
}
return a;
}
char *Initializer::toChars()
{ OutBuffer *buf;
HdrGenState hgs;
memset(&hgs, 0, sizeof(hgs));
buf = new OutBuffer();
toCBuffer(buf, &hgs);
return buf->toChars();
}
/********************************** VoidInitializer ***************************/
VoidInitializer::VoidInitializer(Loc loc)
: Initializer(loc)
{
type = NULL;
}
Initializer *VoidInitializer::syntaxCopy()
{
return new VoidInitializer(loc);
}
Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
{
//printf("VoidInitializer::semantic(t = %p)\n", t);
type = t;
return this;
}
Expression *VoidInitializer::toExpression()
{
error(loc, "void initializer has no value");
return new IntegerExp(0);
}
void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("void");
}
/********************************** StructInitializer *************************/
StructInitializer::StructInitializer(Loc loc)
: Initializer(loc)
{
ad = NULL;
}
Initializer *StructInitializer::syntaxCopy()
{
StructInitializer *ai = new StructInitializer(loc);
assert(field.dim == value.dim);
ai->field.setDim(field.dim);
ai->value.setDim(value.dim);
for (int i = 0; i < field.dim; i++)
{
ai->field.data[i] = field.data[i];
Initializer *init = (Initializer *)value.data[i];
init = init->syntaxCopy();
ai->value.data[i] = init;
}
return ai;
}
void StructInitializer::addInit(Identifier *field, Initializer *value)
{
//printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
this->field.push(field);
this->value.push(value);
}
Initializer *StructInitializer::semantic(Scope *sc, Type *t)
{
TypeStruct *ts;
int errors = 0;
//printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
vars.setDim(field.dim);
t = t->toBasetype();
if (t->ty == Tstruct)
{ unsigned i;
unsigned fieldi = 0;
ts = (TypeStruct *)t;
ad = ts->sym;
for (i = 0; i < field.dim; i++)
{
Identifier *id = (Identifier *)field.data[i];
Initializer *val = (Initializer *)value.data[i];
Dsymbol *s;
VarDeclaration *v;
if (id == NULL)
{
if (fieldi >= ad->fields.dim)
{ error(loc, "too many initializers for %s", ad->toChars());
continue;
}
else
{
s = (Dsymbol *)ad->fields.data[fieldi];
}
}
else
{
//s = ad->symtab->lookup(id);
s = ad->search(loc, id, 0);
if (!s)
{
error("'%s' is not a member of '%s'", id->toChars(), t->toChars());
continue;
}
// Find out which field index it is
for (fieldi = 0; 1; fieldi++)
{
if (fieldi >= ad->fields.dim)
{
s->error("is not a per-instance initializable field");
break;
}
if (s == (Dsymbol *)ad->fields.data[fieldi])
break;
}
}
if (s && (v = s->isVarDeclaration()) != NULL)
{
val = val->semantic(sc, v->type);
value.data[i] = (void *)val;
vars.data[i] = (void *)v;
}
else
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
errors = 1;
}
fieldi++;
}
}
else if (t->ty == Tdelegate && value.dim == 0)
{ /* Rewrite as empty delegate literal { }
*/
Arguments *arguments = new Arguments;
Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
fd->fbody = new CompoundStatement(loc, new Statements());
fd->endloc = loc;
Expression *e = new FuncExp(loc, fd);
ExpInitializer *ie = new ExpInitializer(loc, e);
return ie->semantic(sc, t);
}
else
{
error(loc, "a struct is not a valid initializer for a %s", t->toChars());
errors = 1;
}
if (errors)
{
field.setDim(0);
value.setDim(0);
vars.setDim(0);
}
return this;
}
Expression *StructInitializer::toExpression()
{
return NULL; // cannot do it
}
void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
//printf("StructInitializer::toCBuffer()\n");
buf->writebyte('{');
for (int i = 0; i < field.dim; i++)
{
if (i > 0)
buf->writebyte(',');
Identifier *id = (Identifier *)field.data[i];
if (id)
{
buf->writestring(id->toChars());
buf->writebyte(':');
}
Initializer *iz = (Initializer *)value.data[i];
if (iz)
iz->toCBuffer(buf, hgs);
}
buf->writebyte('}');
}
/********************************** ArrayInitializer ************************************/
ArrayInitializer::ArrayInitializer(Loc loc)
: Initializer(loc)
{
dim = 0;
type = NULL;
sem = 0;
}
Initializer *ArrayInitializer::syntaxCopy()
{
//printf("ArrayInitializer::syntaxCopy()\n");
ArrayInitializer *ai = new ArrayInitializer(loc);
assert(index.dim == value.dim);
ai->index.setDim(index.dim);
ai->value.setDim(value.dim);
for (int i = 0; i < ai->value.dim; i++)
{ Expression *e = (Expression *)index.data[i];
if (e)
e = e->syntaxCopy();
ai->index.data[i] = e;
Initializer *init = (Initializer *)value.data[i];
init = init->syntaxCopy();
ai->value.data[i] = init;
}
return ai;
}
void ArrayInitializer::addInit(Expression *index, Initializer *value)
{
this->index.push(index);
this->value.push(value);
dim = 0;
type = NULL;
}
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
{ unsigned i;
unsigned length;
//printf("ArrayInitializer::semantic(%s)\n", t->toChars());
if (sem) // if semantic() already run
return this;
sem = 1;
type = t;
t = t->toBasetype();
switch (t->ty)
{
case Tpointer:
case Tsarray:
case Tarray:
break;
default:
error(loc, "cannot use array to initialize %s", type->toChars());
return this;
}
length = 0;
for (i = 0; i < index.dim; i++)
{ Expression *idx;
Initializer *val;
idx = (Expression *)index.data[i];
if (idx)
{ idx = idx->semantic(sc);
idx = idx->optimize(WANTvalue | WANTinterpret);
index.data[i] = (void *)idx;
length = idx->toInteger();
}
val = (Initializer *)value.data[i];
val = val->semantic(sc, t->next);
value.data[i] = (void *)val;
length++;
if (length == 0)
error("array dimension overflow");
if (length > dim)
dim = length;
}
unsigned long amax = 0x80000000;
if ((unsigned long) dim * t->next->size() >= amax)
error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->next->size());
return this;
}
/********************************
* If possible, convert array initializer to array literal.
*/
Expression *ArrayInitializer::toExpression()
{ Expressions *elements;
Expression *e;
//printf("ArrayInitializer::toExpression()\n");
//static int i; if (++i == 2) halt();
elements = new Expressions();
for (size_t i = 0; i < value.dim; i++)
{
if (index.data[i])
goto Lno;
Initializer *iz = (Initializer *)value.data[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
if (!ex)
goto Lno;
elements->push(ex);
}
e = new ArrayLiteralExp(loc, elements);
e->type = type;
return e;
Lno:
delete elements;
error(loc, "array initializers as expressions are not allowed");
return NULL;
}
/********************************
* If possible, convert array initializer to associative array initializer.
*/
Initializer *ArrayInitializer::toAssocArrayInitializer()
{ Expressions *keys;
Expressions *values;
Expression *e;
//printf("ArrayInitializer::toAssocArrayInitializer()\n");
//static int i; if (++i == 2) halt();
keys = new Expressions();
keys->setDim(value.dim);
values = new Expressions();
values->setDim(value.dim);
for (size_t i = 0; i < value.dim; i++)
{
e = (Expression *)index.data[i];
if (!e)
goto Lno;
keys->data[i] = (void *)e;
Initializer *iz = (Initializer *)value.data[i];
if (!iz)
goto Lno;
e = iz->toExpression();
if (!e)
goto Lno;
values->data[i] = (void *)e;
}
e = new AssocArrayLiteralExp(loc, keys, values);
return new ExpInitializer(loc, e);
Lno:
delete keys;
delete values;
error(loc, "not an associative array initializer");
return this;
}
Type *ArrayInitializer::inferType(Scope *sc)
{
for (size_t i = 0; i < value.dim; i++)
{
if (index.data[i])
goto Lno;
}
if (value.dim)
{
Initializer *iz = (Initializer *)value.data[0];
if (iz)
{ Type *t = iz->inferType(sc);
t = new TypeSArray(t, new IntegerExp(value.dim));
t = t->semantic(loc, sc);
return t;
}
}
Lno:
error(loc, "cannot infer type from this array initializer");
return Type::terror;
}
void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writebyte('[');
for (int i = 0; i < index.dim; i++)
{
if (i > 0)
buf->writebyte(',');
Expression *ex = (Expression *)index.data[i];
if (ex)
{
ex->toCBuffer(buf, hgs);
buf->writebyte(':');
}
Initializer *iz = (Initializer *)value.data[i];
if (iz)
iz->toCBuffer(buf, hgs);
}
buf->writebyte(']');
}
/********************************** ExpInitializer ************************************/
ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
: Initializer(loc)
{
this->exp = exp;
}
Initializer *ExpInitializer::syntaxCopy()
{
return new ExpInitializer(loc, exp->syntaxCopy());
}
Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
{
//printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
exp = exp->semantic(sc);
Type *tb = t->toBasetype();
/* Look for case of initializing a static array with a too-short
* string literal, such as:
* char[5] foo = "abc";
* Allow this by doing an explicit cast, which will lengthen the string
* literal.
*/
if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
{ StringExp *se = (StringExp *)exp;
if (!se->committed && se->type->ty == Tsarray &&
((TypeSArray *)se->type)->dim->toInteger() <
((TypeSArray *)t)->dim->toInteger())
{
exp = se->castTo(sc, t);
goto L1;
}
}
// Look for the case of statically initializing an array
// with a single member.
if (tb->ty == Tsarray &&
!tb->next->equals(exp->type->toBasetype()->next) &&
exp->implicitConvTo(tb->next)
)
{
t = tb->next;
}
exp = exp->implicitCastTo(sc, t);
L1:
exp = exp->optimize(WANTvalue | WANTinterpret);
//printf("-ExpInitializer::semantic(): "); exp->print();
return this;
}
Type *ExpInitializer::inferType(Scope *sc)
{
//printf("ExpInitializer::inferType() %s\n", toChars());
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
return exp->type;
}
Expression *ExpInitializer::toExpression()
{
return exp;
}
void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
exp->toCBuffer(buf, hgs);
}

129
dmd/init.h Normal file
View File

@@ -0,0 +1,129 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef INIT_H
#define INIT_H
#include "root.h"
#include "mars.h"
#include "arraytypes.h"
struct Identifier;
struct Expression;
struct Scope;
struct Type;
struct dt_t;
struct AggregateDeclaration;
struct VoidInitializer;
struct ArrayInitializer;
struct ExpInitializer;
struct StructInitializer;
#ifdef _DH
struct HdrGenState;
#endif
struct Initializer : Object
{
Loc loc;
Initializer(Loc loc);
virtual Initializer *syntaxCopy();
virtual Initializer *semantic(Scope *sc, Type *t);
virtual Type *inferType(Scope *sc);
virtual Expression *toExpression() = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
char *toChars();
static Initializers *arraySyntaxCopy(Initializers *ai);
virtual dt_t *toDt();
virtual VoidInitializer *isVoidInitializer() { return NULL; }
virtual ArrayInitializer *isArrayInitializer() { return NULL; }
virtual ExpInitializer *isExpInitializer() { return NULL; }
virtual StructInitializer *isStructInitializer() { return NULL; }
};
struct VoidInitializer : Initializer
{
Type *type; // type that this will initialize to
VoidInitializer(Loc loc);
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
dt_t *toDt();
virtual VoidInitializer *isVoidInitializer() { return this; }
};
struct StructInitializer : Initializer
{
Identifiers field; // of Identifier *'s
Initializers value; // parallel array of Initializer *'s
Array vars; // parallel array of VarDeclaration *'s
AggregateDeclaration *ad; // which aggregate this is for
StructInitializer(Loc loc);
Initializer *syntaxCopy();
void addInit(Identifier *field, Initializer *value);
Initializer *semantic(Scope *sc, Type *t);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
dt_t *toDt();
virtual StructInitializer *isStructInitializer() { return this; }
};
struct ArrayInitializer : Initializer
{
Expressions index; // indices
Initializers value; // of Initializer *'s
unsigned dim; // length of array being initialized
Type *type; // type that array will be used to initialize
int sem; // !=0 if semantic() is run
ArrayInitializer(Loc loc);
Initializer *syntaxCopy();
void addInit(Expression *index, Initializer *value);
Initializer *semantic(Scope *sc, Type *t);
Type *inferType(Scope *sc);
Expression *toExpression();
Initializer *toAssocArrayInitializer();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
dt_t *toDt();
dt_t *toDtBit(); // for bit arrays
ArrayInitializer *isArrayInitializer() { return this; }
};
struct ExpInitializer : Initializer
{
Expression *exp;
ExpInitializer(Loc loc, Expression *exp);
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t);
Type *inferType(Scope *sc);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
dt_t *toDt();
virtual ExpInitializer *isExpInitializer() { return this; }
};
#endif

1441
dmd/inline.c Normal file

File diff suppressed because it is too large Load Diff

2106
dmd/interpret.c Normal file

File diff suppressed because it is too large Load Diff

2778
dmd/lexer.c Normal file

File diff suppressed because it is too large Load Diff

285
dmd/lexer.h Normal file
View File

@@ -0,0 +1,285 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_LEXER_H
#define DMD_LEXER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "mars.h"
struct StringTable;
struct Identifier;
struct Module;
/* Tokens:
( )
[ ]
{ }
< > <= >= == != === !==
<< >> <<= >>= >>> >>>=
+ - += -=
* / % *= /= %=
& | ^ &= |= ^=
= ! ~
++ --
. -> : ,
? && ||
*/
enum TOK
{
TOKreserved,
// Other
TOKlparen, TOKrparen,
TOKlbracket, TOKrbracket,
TOKlcurly, TOKrcurly,
TOKcolon, TOKneg,
TOKsemicolon, TOKdotdotdot,
TOKeof, TOKcast,
TOKnull, TOKassert,
TOKtrue, TOKfalse,
TOKarray, TOKcall,
TOKaddress, TOKtypedot,
TOKtype, TOKthrow,
TOKnew, TOKdelete,
TOKstar, TOKsymoff,
TOKvar, TOKdotvar,
TOKdotti, TOKdotexp,
TOKdottype, TOKslice,
TOKarraylength, TOKversion,
TOKmodule, TOKdollar,
TOKtemplate, TOKdottd,
TOKdeclaration, TOKtypeof,
TOKpragma, TOKdsymbol,
TOKtypeid, TOKuadd,
TOKremove,
TOKnewanonclass, TOKcomment,
TOKarrayliteral, TOKassocarrayliteral,
TOKstructliteral,
// Operators
TOKlt, TOKgt,
TOKle, TOKge,
TOKequal, TOKnotequal,
TOKidentity, TOKnotidentity,
TOKindex, TOKis,
TOKtobool,
// 60
// NCEG floating point compares
// !<>= <> <>= !> !>= !< !<= !<>
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
TOKshl, TOKshr,
TOKshlass, TOKshrass,
TOKushr, TOKushrass,
TOKcat, TOKcatass, // ~ ~=
TOKadd, TOKmin, TOKaddass, TOKminass,
TOKmul, TOKdiv, TOKmod,
TOKmulass, TOKdivass, TOKmodass,
TOKand, TOKor, TOKxor,
TOKandass, TOKorass, TOKxorass,
TOKassign, TOKnot, TOKtilde,
TOKplusplus, TOKminusminus, TOKconstruct,
TOKdot, TOKarrow, TOKcomma,
TOKquestion, TOKandand, TOKoror,
// 103
// Numeric literals
TOKint32v, TOKuns32v,
TOKint64v, TOKuns64v,
TOKfloat32v, TOKfloat64v, TOKfloat80v,
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
// Char constants
TOKcharv, TOKwcharv, TOKdcharv,
// Leaf operators
TOKidentifier, TOKstring,
TOKthis, TOKsuper,
TOKhalt, TOKtuple,
// Basic types
TOKvoid,
TOKint8, TOKuns8,
TOKint16, TOKuns16,
TOKint32, TOKuns32,
TOKint64, TOKuns64,
TOKfloat32, TOKfloat64, TOKfloat80,
TOKimaginary32, TOKimaginary64, TOKimaginary80,
TOKcomplex32, TOKcomplex64, TOKcomplex80,
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
TOKcent, TOKucent,
// Aggregates
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
TOKmixin,
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
TOKauto, TOKpackage,
// Statements
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
TOKasm, TOKforeach, TOKforeach_reverse,
TOKscope,
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
// Contracts
TOKbody, TOKinvariant,
// Testing
TOKunittest,
// Added after 1.0
TOKref,
TOKmacro,
TOKMAX
};
#define CASE_BASIC_TYPES \
case TOKwchar: case TOKdchar: \
case TOKbit: case TOKbool: case TOKchar: \
case TOKint8: case TOKuns8: \
case TOKint16: case TOKuns16: \
case TOKint32: case TOKuns32: \
case TOKint64: case TOKuns64: \
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
case TOKvoid
#define CASE_BASIC_TYPES_X(t) \
case TOKvoid: t = Type::tvoid; goto LabelX; \
case TOKint8: t = Type::tint8; goto LabelX; \
case TOKuns8: t = Type::tuns8; goto LabelX; \
case TOKint16: t = Type::tint16; goto LabelX; \
case TOKuns16: t = Type::tuns16; goto LabelX; \
case TOKint32: t = Type::tint32; goto LabelX; \
case TOKuns32: t = Type::tuns32; goto LabelX; \
case TOKint64: t = Type::tint64; goto LabelX; \
case TOKuns64: t = Type::tuns64; goto LabelX; \
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
case TOKbit: t = Type::tbit; goto LabelX; \
case TOKbool: t = Type::tbool; goto LabelX; \
case TOKchar: t = Type::tchar; goto LabelX; \
case TOKwchar: t = Type::twchar; goto LabelX; \
case TOKdchar: t = Type::tdchar; goto LabelX; \
LabelX
struct Token
{
Token *next;
unsigned char *ptr; // pointer to first character of this token within buffer
enum TOK value;
unsigned char *blockComment; // doc comment string prior to this token
unsigned char *lineComment; // doc comment for previous token
union
{
// Integers
d_int32 int32value;
d_uns32 uns32value;
d_int64 int64value;
d_uns64 uns64value;
// Floats
#ifdef IN_GCC
// real_t float80value; // can't use this in a union!
#else
d_float80 float80value;
#endif
struct
{ unsigned char *ustring; // UTF8 string
unsigned len;
unsigned char postfix; // 'c', 'w', 'd'
};
Identifier *ident;
};
#ifdef IN_GCC
real_t float80value; // can't use this in a union!
#endif
static char *tochars[TOKMAX];
static void *operator new(size_t sz);
int isKeyword();
void print();
char *toChars();
static char *toChars(enum TOK);
};
struct Lexer
{
static StringTable stringtable;
static OutBuffer stringbuffer;
static Token *freelist;
Loc loc; // for error messages
unsigned char *base; // pointer to start of buffer
unsigned char *end; // past end of buffer
unsigned char *p; // current character
Token token;
Module *mod;
int doDocComment; // collect doc comment information
int anyToken; // !=0 means seen at least one token
int commentToken; // !=0 means comments are TOKcomment's
Lexer(Module *mod,
unsigned char *base, unsigned begoffset, unsigned endoffset,
int doDocComment, int commentToken);
static void initKeywords();
static Identifier *idPool(const char *s);
TOK nextToken();
void scan(Token *t);
Token *peek(Token *t);
Token *peekPastParen(Token *t);
unsigned escapeSequence();
TOK wysiwygStringConstant(Token *t, int tc);
TOK hexStringConstant(Token *t);
TOK escapeStringConstant(Token *t, int wide);
TOK charConstant(Token *t, int wide);
void stringPostfix(Token *t);
unsigned wchar(unsigned u);
TOK number(Token *t);
TOK inreal(Token *t);
void error(const char *format, ...);
void error(Loc loc, const char *format, ...);
void pragma();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);
static int isValidIdentifier(char *p);
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
};
#endif /* DMD_LEXER_H */

504
dmd/link.c Normal file
View File

@@ -0,0 +1,504 @@
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#if _WIN32
#include <process.h>
#endif
#if linux
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#endif
#include "root.h"
#include "mars.h"
#include "mem.h"
int executecmd(char *cmd, char *args, int useenv);
int executearg0(char *cmd, char *args);
/*****************************
* Run the linker. Return status of execution.
*/
int runLINK()
{
#if _WIN32
assert(0 && "linking not done for win32");
char *p;
int i;
int status;
OutBuffer cmdbuf;
global.params.libfiles->push((void *) "user32");
global.params.libfiles->push((void *) "kernel32");
for (i = 0; i < global.params.objfiles->dim; i++)
{
if (i)
cmdbuf.writeByte('+');
p = (char *)global.params.objfiles->data[i];
char *ext = FileName::ext(p);
if (ext)
cmdbuf.write(p, ext - p - 1);
else
cmdbuf.writestring(p);
}
cmdbuf.writeByte(',');
if (global.params.exefile)
cmdbuf.writestring(global.params.exefile);
else
{ // Generate exe file name from first obj name
char *n = (char *)global.params.objfiles->data[0];
char *ex;
n = FileName::name(n);
FileName *fn = FileName::forceExt(n, "exe");
global.params.exefile = fn->toChars();
}
// Make sure path to exe file exists
{ char *p = FileName::path(global.params.exefile);
FileName::ensurePathExists(p);
mem.free(p);
}
cmdbuf.writeByte(',');
if (global.params.run)
cmdbuf.writestring("nul");
// if (mapfile)
// cmdbuf.writestring(output);
cmdbuf.writeByte(',');
for (i = 0; i < global.params.libfiles->dim; i++)
{
if (i)
cmdbuf.writeByte('+');
cmdbuf.writestring((char *) global.params.libfiles->data[i]);
}
if (global.params.deffile)
{
cmdbuf.writeByte(',');
cmdbuf.writestring(global.params.deffile);
}
/* Eliminate unnecessary trailing commas */
while (1)
{ i = cmdbuf.offset;
if (!i || cmdbuf.data[i - 1] != ',')
break;
cmdbuf.offset--;
}
if (global.params.resfile)
{
cmdbuf.writestring("/RC:");
cmdbuf.writestring(global.params.resfile);
}
#if 0
if (mapfile)
cmdbuf.writestring("/m");
if (debuginfo)
cmdbuf.writestring("/li");
if (codeview)
{
cmdbuf.writestring("/co");
if (codeview3)
cmdbuf.writestring(":3");
}
#else
if (global.params.symdebug)
cmdbuf.writestring("/co");
#endif
cmdbuf.writestring("/noi");
for (i = 0; i < global.params.linkswitches->dim; i++)
{
cmdbuf.writestring((char *) global.params.linkswitches->data[i]);
}
cmdbuf.writeByte(';');
p = cmdbuf.toChars();
FileName *lnkfilename = NULL;
size_t plen = strlen(p);
if (plen > 7000)
{
lnkfilename = FileName::forceExt(global.params.exefile, "lnk");
File flnk(lnkfilename);
flnk.setbuffer(p, plen);
flnk.ref = 1;
if (flnk.write())
error("error writing file %s", lnkfilename);
if (lnkfilename->len() < plen)
sprintf(p, "@%s", lnkfilename->toChars());
}
char *linkcmd = getenv("LINKCMD");
if (!linkcmd)
linkcmd = "link";
status = executecmd(linkcmd, p, 1);
if (lnkfilename)
{
remove(lnkfilename->toChars());
delete lnkfilename;
}
return status;
#elif linux
pid_t childpid;
int i;
int status;
// Build argv[]
Array argv;
//char *cc = getenv("CC");
//if (!cc)
//cc = "gcc";
char *cc = "llvm-ld";
argv.push((void *)cc);
// None of that a.out stuff. Use explicit exe file name, or
// generate one from name of first source file.
OutBuffer* exestr = new OutBuffer;
if (global.params.exefile)
{
exestr->printf("-o=%s", global.params.exefile);
argv.push(exestr->toChars());
}
else
{ // Generate exe file name from first obj name
char *n = (char *)global.params.objfiles->data[0];
char *e;
char *ex;
n = FileName::name(n);
e = FileName::ext(n);
if (e)
{
e--; // back up over '.'
ex = (char *)mem.malloc(e - n + 1);
memcpy(ex, n, e - n);
ex[e - n] = 0;
}
else
ex = (char *)"a.out"; // no extension, so give up
exestr->printf("-o=%s", ex);
ex = exestr->toChars();
argv.push(ex);
global.params.exefile = ex;
}
// Make sure path to exe file exists
{ char *p = FileName::path(global.params.exefile);
FileName::ensurePathExists(p);
mem.free(p);
}
argv.insert(argv.dim, global.params.libfiles);
//if (global.params.symdebug)
//argv.push((void *)"-g");
//argv.push((void *)"-m32");
if (!global.params.optimize)
argv.push((void *)"-disable-opt");
else {
const char* s = 0;
switch(global.params.optimizeLevel) {
case 0:
s = "-O0"; break;
case 1:
s = "-O1"; break;
case 2:
s = "-O2"; break;
case 3:
s = "-O3"; break;
case 4:
s = "-O4"; break;
case 5:
s = "-O5"; break;
default:
assert(0);
}
argv.push((void*)s);
}
#if 0
if (0 && global.params.exefile)
{
/* This switch enables what is known as 'smart linking'
* in the Windows world, where unreferenced sections
* are removed from the executable. It eliminates unreferenced
* functions, essentially making a 'library' out of a module.
* Although it is documented to work with ld version 2.13,
* in practice it does not, but just seems to be ignored.
* Thomas Kuehne has verified that it works with ld 2.16.1.
* BUG: disabled because it causes exception handling to fail
*/
argv.push((void *)"-Xlinker");
argv.push((void *)"--gc-sections");
}
#endif
for (i = 0; i < global.params.linkswitches->dim; i++)
{ char *p = (char *)global.params.linkswitches->data[i];
//if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l'))
//{ // Don't need -Xlinker if switch starts with -l
// argv.push((void *)"-Xlinker");
//}
argv.push((void *) p);
}
argv.push((void*)"-native");
/* Standard libraries must go after user specified libraries
* passed with -l.
*/
//argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a
//argv.push((void *)"-lpthread");
//argv.push((void *)"-lm");
std::string corelibpath = global.params.runtimeImppath;
corelibpath.append("/llvmdcore.bc");
argv.append(global.params.objfiles);
argv.push((void *)corelibpath.c_str());
if (!global.params.quiet)
{
// Print it
for (i = 0; i < argv.dim; i++)
printf("%s ", (char *)argv.data[i]);
printf("\n");
fflush(stdout);
}
argv.push(NULL);
childpid = fork();
if (childpid == 0)
{
execvp((char *)argv.data[0], (char **)argv.data);
perror((char *)argv.data[0]); // failed to execute
return -1;
}
waitpid(childpid, &status, 0);
status=WEXITSTATUS(status);
if (status)
printf("--- errorlevel %d\n", status);
return status;
#else
printf ("Linking is not yet supported for this version of LLVMDMD.\n");
return -1;
#endif
}
/**********************************
* Delete generated EXE file.
*/
void deleteExeFile()
{
if (global.params.exefile)
{
//printf("deleteExeFile() %s\n", global.params.exefile);
remove(global.params.exefile);
}
}
/******************************
* Execute a rule. Return the status.
* cmd program to run
* args arguments to cmd, as a string
* useenv if cmd knows about _CMDLINE environment variable
*/
#if _WIN32
int executecmd(char *cmd, char *args, int useenv)
{
int status;
char *buff;
size_t len;
if (!global.params.quiet || global.params.verbose)
{
printf("%s %s\n", cmd, args);
fflush(stdout);
}
if ((len = strlen(args)) > 255)
{ char *q;
static char envname[] = "@_CMDLINE";
envname[0] = '@';
switch (useenv)
{ case 0: goto L1;
case 2: envname[0] = '%'; break;
}
q = (char *) alloca(sizeof(envname) + len + 1);
sprintf(q,"%s=%s", envname + 1, args);
status = putenv(q);
if (status == 0)
args = envname;
else
{
L1:
error("command line length of %d is too long",len);
}
}
status = executearg0(cmd,args);
#if _WIN32
if (status == -1)
status = spawnlp(0,cmd,cmd,args,NULL);
#endif
// if (global.params.verbose)
// printf("\n");
if (status)
{
if (status == -1)
printf("Can't run '%s', check PATH\n", cmd);
else
printf("--- errorlevel %d\n", status);
}
return status;
}
#endif
/**************************************
* Attempt to find command to execute by first looking in the directory
* where DMD was run from.
* Returns:
* -1 did not find command there
* !=-1 exit status from command
*/
#if _WIN32
int executearg0(char *cmd, char *args)
{
char *file;
char *argv0 = global.params.argv0;
//printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args);
// If cmd is fully qualified, we don't do this
if (FileName::absolute(cmd))
return -1;
file = FileName::replaceName(argv0, cmd);
//printf("spawning '%s'\n",file);
#if _WIN32
return spawnl(0,file,file,args,NULL);
#elif linux
char *full;
int cmdl = strlen(cmd);
full = (char*) mem.malloc(cmdl + strlen(args) + 2);
if (full == NULL)
return 1;
strcpy(full, cmd);
full [cmdl] = ' ';
strcpy(full + cmdl + 1, args);
int result = system(full);
mem.free(full);
return result;
#else
assert(0);
#endif
}
#endif
/***************************************
* Run the compiled program.
* Return exit status.
*/
int runProgram()
{
//printf("runProgram()\n");
if (global.params.verbose)
{
printf("%s", global.params.exefile);
for (size_t i = 0; i < global.params.runargs_length; i++)
printf(" %s", (char *)global.params.runargs[i]);
printf("\n");
}
// Build argv[]
Array argv;
argv.push((void *)global.params.exefile);
for (size_t i = 0; i < global.params.runargs_length; i++)
{ char *a = global.params.runargs[i];
#if _WIN32
// BUG: what about " appearing in the string?
if (strchr(a, ' '))
{ char *b = (char *)mem.malloc(3 + strlen(a));
sprintf(b, "\"%s\"", a);
a = b;
}
#endif
argv.push((void *)a);
}
argv.push(NULL);
#if _WIN32
char *ex = FileName::name(global.params.exefile);
if (ex == global.params.exefile)
ex = FileName::combine(".", ex);
else
ex = global.params.exefile;
return spawnv(0,ex,(char **)argv.data);
#elif linux
pid_t childpid;
int status;
childpid = fork();
if (childpid == 0)
{
char *fn = (char *)argv.data[0];
if (!FileName::absolute(fn))
{ // Make it "./fn"
fn = FileName::combine(".", fn);
}
execv(fn, (char **)argv.data);
perror(fn); // failed to execute
return -1;
}
waitpid(childpid, &status, 0);
status = WEXITSTATUS(status);
return status;
#else
assert(0);
#endif
}

59
dmd/lstring.c Normal file
View File

@@ -0,0 +1,59 @@
// lstring.c
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdlib.h>
#include "dchar.h"
#include "mem.h"
#include "lstring.h"
Lstring Lstring::zero = LSTRING_EMPTY();
Lstring *Lstring::ctor(const dchar *p, unsigned length)
{
Lstring *s;
s = alloc(length);
memcpy(s->string, p, length * sizeof(dchar));
return s;
}
Lstring *Lstring::alloc(unsigned length)
{
Lstring *s;
s = (Lstring *)mem.malloc(size(length));
s->length = length;
s->string[length] = 0;
return s;
}
Lstring *Lstring::append(const Lstring *s)
{
Lstring *t;
if (!s->length)
return this;
t = alloc(length + s->length);
memcpy(t->string, string, length * sizeof(dchar));
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
return t;
}
Lstring *Lstring::substring(int start, int end)
{
Lstring *t;
if (start == end)
return &zero;
t = alloc(end - start);
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
return t;
}

72
dmd/lstring.h Normal file
View File

@@ -0,0 +1,72 @@
// lstring.h
// length-prefixed strings
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef LSTRING_H
#define LSTRING_H 1
#include "dchar.h"
struct Lstring
{
unsigned length;
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
dchar string[];
static Lstring zero; // 0 length string
// No constructors because we want to be able to statically
// initialize Lstring's, and Lstrings are of variable size.
#if M_UNICODE
#define LSTRING(p,length) { length, L##p }
#else
#define LSTRING(p,length) { length, p }
#endif
#if __GNUC__
#define LSTRING_EMPTY() { 0 }
#else
#define LSTRING_EMPTY() LSTRING("", 0)
#endif
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
static Lstring *ctor(const dchar *p, unsigned length);
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
static Lstring *alloc(unsigned length);
Lstring *clone();
unsigned len() { return length; }
dchar *toDchars() { return string; }
hash_t hash() { return Dchar::calcHash(string, length); }
hash_t ihash() { return Dchar::icalcHash(string, length); }
static int cmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
}
static int icmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
}
Lstring *append(const Lstring *s);
Lstring *substring(int start, int end);
};
#endif

459
dmd/macro.c Normal file
View File

@@ -0,0 +1,459 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
/* Simple macro text processor.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <assert.h>
#if IN_GCC || IN_LLVM
#include "mem.h"
#else
#if _WIN32
#include "..\root\mem.h"
#elif linux
#include "../root/mem.h"
#else
#error "fix this"
#endif
#endif
#include "root.h"
#include "macro.h"
#define isidstart(c) (isalpha(c) || (c) == '_')
#define isidchar(c) (isalnum(c) || (c) == '_')
unsigned char *memdup(unsigned char *p, size_t len)
{
return (unsigned char *)memcpy(mem.malloc(len), p, len);
}
Macro::Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen)
{
next = NULL;
#if 1
this->name = name;
this->namelen = namelen;
this->text = text;
this->textlen = textlen;
#else
this->name = name;
this->namelen = namelen;
this->text = text;
this->textlen = textlen;
#endif
inuse = 0;
}
Macro *Macro::search(unsigned char *name, size_t namelen)
{ Macro *table;
//printf("Macro::search(%.*s)\n", namelen, name);
for (table = this; table; table = table->next)
{
if (table->namelen == namelen &&
memcmp(table->name, name, namelen) == 0)
{
//printf("\tfound %d\n", table->textlen);
break;
}
}
return table;
}
Macro *Macro::define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen)
{
//printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text);
Macro *table;
//assert(ptable);
for (table = *ptable; table; table = table->next)
{
if (table->namelen == namelen &&
memcmp(table->name, name, namelen) == 0)
{
table->text = text;
table->textlen = textlen;
return table;
}
}
table = new Macro(name, namelen, text, textlen);
table->next = *ptable;
*ptable = table;
return table;
}
/**********************************************************
* Given buffer p[0..end], extract argument marg[0..marglen].
* Params:
* n 0: get entire argument
* 1..9: get nth argument
* -1: get 2nd through end
*/
unsigned extractArgN(unsigned char *p, unsigned end, unsigned char **pmarg, unsigned *pmarglen, int n)
{
/* Scan forward for matching right parenthesis.
* Nest parentheses.
* Skip over $( and $)
* Skip over "..." and '...' strings inside HTML tags.
* Skip over <!-- ... --> comments.
* Skip over previous macro insertions
* Set marglen.
*/
unsigned parens = 1;
unsigned char instring = 0;
unsigned incomment = 0;
unsigned intag = 0;
unsigned inexp = 0;
unsigned argn = 0;
unsigned v = 0;
Largstart:
#if 1
// Skip first space, if any, to find the start of the macro argument
if (v < end && isspace(p[v]))
v++;
#else
// Skip past spaces to find the start of the macro argument
for (; v < end && isspace(p[v]); v++)
;
#endif
*pmarg = p + v;
for (; v < end; v++)
{ unsigned char c = p[v];
switch (c)
{
case ',':
if (!inexp && !instring && !incomment && parens == 1)
{
argn++;
if (argn == 1 && n == -1)
{ v++;
goto Largstart;
}
if (argn == n)
break;
if (argn + 1 == n)
{ v++;
goto Largstart;
}
}
continue;
case '(':
if (!inexp && !instring && !incomment)
parens++;
continue;
case ')':
if (!inexp && !instring && !incomment && --parens == 0)
{
break;
}
continue;
case '"':
case '\'':
if (!inexp && !incomment && intag)
{
if (c == instring)
instring = 0;
else if (!instring)
instring = c;
}
continue;
case '<':
if (!inexp && !instring && !incomment)
{
if (v + 6 < end &&
p[v + 1] == '!' &&
p[v + 2] == '-' &&
p[v + 3] == '-')
{
incomment = 1;
v += 3;
}
else if (v + 2 < end &&
isalpha(p[v + 1]))
intag = 1;
}
continue;
case '>':
if (!inexp)
intag = 0;
continue;
case '-':
if (!inexp &&
!instring &&
incomment &&
v + 2 < end &&
p[v + 1] == '-' &&
p[v + 2] == '>')
{
incomment = 0;
v += 2;
}
continue;
case 0xFF:
if (v + 1 < end)
{
if (p[v + 1] == '{')
inexp++;
else if (p[v + 1] == '}')
inexp--;
}
continue;
default:
continue;
}
break;
}
if (argn == 0 && n == -1)
*pmarg = p + v;
*pmarglen = p + v - *pmarg;
//printf("extractArg%d('%.*s') = '%.*s'\n", n, end, p, *pmarglen, *pmarg);
return v;
}
/*****************************************************
* Expand macro in place in buf.
* Only look at the text in buf from start to end.
*/
void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
unsigned char *arg, unsigned arglen)
{
#if 0
printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg);
printf("Buf is: '%.*s'\n", *pend - start, buf->data + start);
#endif
static int nest;
if (nest > 100) // limit recursive expansion
return;
nest++;
unsigned end = *pend;
assert(start <= end);
assert(end <= buf->offset);
/* First pass - replace $0
*/
arg = memdup(arg, arglen);
for (unsigned u = start; u + 1 < end; )
{
unsigned char *p = buf->data; // buf->data is not loop invariant
/* Look for $0, but not $$0, and replace it with arg.
*/
if (p[u] == '$' && (isdigit(p[u + 1]) || p[u + 1] == '+'))
{
if (u > start && p[u - 1] == '$')
{ // Don't expand $$0, but replace it with $0
buf->remove(u - 1, 1);
end--;
u += 1; // now u is one past the closing '1'
continue;
}
unsigned char c = p[u + 1];
int n = (c == '+') ? -1 : c - '0';
unsigned char *marg;
unsigned marglen;
extractArgN(arg, arglen, &marg, &marglen, n);
if (marglen == 0)
{ // Just remove macro invocation
//printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg);
buf->remove(u, 2);
end -= 2;
}
else if (c == '+')
{
// Replace '$+' with 'arg'
//printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg);
buf->remove(u, 2);
buf->insert(u, marg, marglen);
end += marglen - 2;
// Scan replaced text for further expansion
unsigned mend = u + marglen;
expand(buf, u, &mend, NULL, 0);
end += mend - (u + marglen);
u = mend;
}
else
{
// Replace '$1' with '\xFF{arg\xFF}'
//printf("Replacing '$%c' with '\xFF{%.*s\xFF}'\n", p[u + 1], marglen, marg);
buf->data[u] = 0xFF;
buf->data[u + 1] = '{';
buf->insert(u + 2, marg, marglen);
buf->insert(u + 2 + marglen, "\xFF}", 2);
end += -2 + 2 + marglen + 2;
// Scan replaced text for further expansion
unsigned mend = u + 2 + marglen;
expand(buf, u + 2, &mend, NULL, 0);
end += mend - (u + 2 + marglen);
u = mend;
}
//printf("u = %d, end = %d\n", u, end);
//printf("#%.*s#\n", end, &buf->data[0]);
continue;
}
u++;
}
/* Second pass - replace other macros
*/
for (unsigned u = start; u + 4 < end; )
{
unsigned char *p = buf->data; // buf->data is not loop invariant
/* A valid start of macro expansion is $(c, where c is
* an id start character, and not $$(c.
*/
if (p[u] == '$' && p[u + 1] == '(' && isidstart(p[u + 2]))
{
//printf("\tfound macro start '%c'\n", p[u + 2]);
unsigned char *name = p + u + 2;
unsigned namelen = 0;
unsigned char *marg;
unsigned marglen;
unsigned v;
/* Scan forward to find end of macro name and
* beginning of macro argument (marg).
*/
for (v = u + 2; v < end; v++)
{ unsigned char c = p[v];
if (!isidchar(c))
{ // We've gone past the end of the macro name.
namelen = v - (u + 2);
break;
}
}
v += extractArgN(p + v, end - v, &marg, &marglen, 0);
assert(v <= end);
if (v < end)
{ // v is on the closing ')'
if (u > start && p[u - 1] == '$')
{ // Don't expand $$(NAME), but replace it with $(NAME)
buf->remove(u - 1, 1);
end--;
u = v; // now u is one past the closing ')'
continue;
}
Macro *m = search(name, namelen);
if (m)
{
#if 0
if (m->textlen && m->text[0] == ' ')
{ m->text++;
m->textlen--;
}
#endif
if (m->inuse && marglen == 0)
{ // Remove macro invocation
buf->remove(u, v + 1 - u);
end -= v + 1 - u;
}
else if (m->inuse && arglen == marglen && memcmp(arg, marg, arglen) == 0)
{ // Recursive expansion; just leave in place
}
else
{
//printf("\tmacro '%.*s'(%.*s) = '%.*s'\n", m->namelen, m->name, marglen, marg, m->textlen, m->text);
#if 1
marg = memdup(marg, marglen);
// Insert replacement text
buf->spread(v + 1, 2 + m->textlen + 2);
buf->data[v + 1] = 0xFF;
buf->data[v + 2] = '{';
memcpy(buf->data + v + 3, m->text, m->textlen);
buf->data[v + 3 + m->textlen] = 0xFF;
buf->data[v + 3 + m->textlen + 1] = '}';
end += 2 + m->textlen + 2;
// Scan replaced text for further expansion
m->inuse++;
unsigned mend = v + 1 + 2+m->textlen+2;
expand(buf, v + 1, &mend, marg, marglen);
end += mend - (v + 1 + 2+m->textlen+2);
m->inuse--;
buf->remove(u, v + 1 - u);
end -= v + 1 - u;
u += mend - (v + 1);
#else
// Insert replacement text
buf->insert(v + 1, m->text, m->textlen);
end += m->textlen;
// Scan replaced text for further expansion
m->inuse++;
unsigned mend = v + 1 + m->textlen;
expand(buf, v + 1, &mend, marg, marglen);
end += mend - (v + 1 + m->textlen);
m->inuse--;
buf->remove(u, v + 1 - u);
end -= v + 1 - u;
u += mend - (v + 1);
#endif
mem.free(marg);
//printf("u = %d, end = %d\n", u, end);
//printf("#%.*s#\n", end - u, &buf->data[u]);
continue;
}
}
else
{
// Replace $(NAME) with nothing
buf->remove(u, v + 1 - u);
end -= (v + 1 - u);
continue;
}
}
}
u++;
}
mem.free(arg);
*pend = end;
nest--;
}

44
dmd/macro.h Normal file
View File

@@ -0,0 +1,44 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_MACRO_H
#define DMD_MACRO_H 1
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "root.h"
class Macro
{
Macro *next; // next in list
unsigned char *name; // macro name
size_t namelen; // length of macro name
unsigned char *text; // macro replacement text
size_t textlen; // length of replacement text
int inuse; // macro is in use (don't expand)
Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
Macro *search(unsigned char *name, size_t namelen);
public:
static Macro *define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
void expand(OutBuffer *buf, unsigned start, unsigned *pend,
unsigned char *arg, unsigned arglen);
};
#endif

249
dmd/mangle.c Normal file
View File

@@ -0,0 +1,249 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "root.h"
#include "init.h"
#include "declaration.h"
#include "aggregate.h"
#include "mtype.h"
#include "attrib.h"
#include "template.h"
#include "id.h"
#include "module.h"
char *mangle(Declaration *sthis)
{
OutBuffer buf;
char *id;
Dsymbol *s;
//printf("::mangle(%s)\n", sthis->toChars());
s = sthis;
do
{
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
if (s->ident)
{
FuncDeclaration *fd = s->isFuncDeclaration();
if (s != sthis && fd)
{
id = mangle(fd);
buf.prependstring(id);
goto L1;
}
else
{
id = s->ident->toChars();
int len = strlen(id);
char tmp[sizeof(len) * 3 + 1];
buf.prependstring(id);
sprintf(tmp, "%d", len);
buf.prependstring(tmp);
}
}
else
buf.prependstring("0");
s = s->parent;
} while (s);
// buf.prependstring("_D");
L1:
//printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
//printf("sthis->type = %s\n", sthis->type->toChars());
FuncDeclaration *fd = sthis->isFuncDeclaration();
if (fd && (fd->needThis() || fd->isNested()))
buf.writeByte(Type::needThisPrefix());
if (sthis->type->deco)
buf.writestring(sthis->type->deco);
else
{ assert(fd->inferRetType);
}
id = buf.toChars();
buf.data = NULL;
return id;
}
char *Declaration::mangle()
#if __DMC__
__out(result)
{
int len = strlen(result);
assert(len > 0);
//printf("mangle: '%s' => '%s'\n", toChars(), result);
for (int i = 0; i < len; i++)
{
assert(result[i] == '_' ||
result[i] == '@' ||
isalnum(result[i]) || result[i] & 0x80);
}
}
__body
#endif
{
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
if (!parent || parent->isModule()) // if at global scope
{
// If it's not a D declaration, no mangling
switch (linkage)
{
case LINKd:
break;
case LINKc:
case LINKwindows:
case LINKpascal:
case LINKcpp:
return ident->toChars();
case LINKdefault:
error("forward declaration");
return ident->toChars();
default:
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
assert(0);
}
}
char *p = ::mangle(this);
OutBuffer buf;
buf.writestring("_D");
buf.writestring(p);
p = buf.toChars();
buf.data = NULL;
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
return p;
}
char *FuncDeclaration::mangle()
#if __DMC__
__out(result)
{
assert(strlen(result) > 0);
}
__body
#endif
{
if (isMain())
return "_Dmain";
assert(this);
return Declaration::mangle();
}
char *StructDeclaration::mangle()
{
//printf("StructDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *TypedefDeclaration::mangle()
{
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *ClassDeclaration::mangle()
{
Dsymbol *parentsave = parent;
//printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
/* These are reserved to the compiler, so keep simple
* names for them.
*/
if (ident == Id::Exception)
{ if (parent->ident == Id::object)
parent = NULL;
}
else if (ident == Id::TypeInfo ||
// ident == Id::Exception ||
ident == Id::TypeInfo_Struct ||
ident == Id::TypeInfo_Class ||
ident == Id::TypeInfo_Typedef ||
ident == Id::TypeInfo_Tuple ||
this == object ||
this == classinfo ||
this == Module::moduleinfo ||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
)
parent = NULL;
char *id = Dsymbol::mangle();
parent = parentsave;
return id;
}
char *TemplateInstance::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateInstance::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (tempdecl->parent)
{
char *p = tempdecl->parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
return id;
}
char *Dsymbol::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("Dsymbol::mangle() '%s'", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
return id;
}

1164
dmd/mars.c Normal file

File diff suppressed because it is too large Load Diff

297
dmd/mars.h Normal file
View File

@@ -0,0 +1,297 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_MARS_H
#define DMD_MARS_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include <stdint.h>
#include <string>
#include <cstdarg>
#ifdef __DMC__
#ifdef DEBUG
#undef assert
#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
#endif
#endif
#ifdef IN_GCC
/* Changes for the GDC compiler by David Friedman */
#endif
#define V2 0 // Version 2.0 features
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
struct Array;
// Put command line switches in here
struct Param
{
char obj; // write object file
char link; // perform link
char trace; // insert profiling hooks
char quiet; // suppress non-error messages
char verbose; // verbose compile
char symdebug; // insert debug symbolic information
char optimize; // run optimizer
char optimizeLevel; // optimization level
char cpu; // target CPU
char is64bit; // generate 64 bit code
char isLE; // generate little endian code
char isLinux; // generate code for linux
char isWindows; // generate code for Windows
char scheduler; // which scheduler to use
char useDeprecated; // allow use of deprecated features
char useAssert; // generate runtime code for assert()'s
char useInvariants; // generate class invariant checks
char useIn; // generate precondition checks
char useOut; // generate postcondition checks
char useArrayBounds; // generate array bounds checks
char useSwitchError; // check for switches without a default
char useUnitTests; // generate unittest code
char useInline; // inline expand functions
char release; // build release version
char preservePaths; // !=0 means don't strip path from source file
char warnings; // enable warnings
char pic; // generate position-independent-code for shared libs
char cov; // generate code coverage data
char nofloat; // code should not pull in floating point support
char noruntime; // code is not allowed to make implicit calls to the runtime
char Dversion; // D version number
char *argv0; // program name
Array *imppath; // array of char*'s of where to look for import modules
Array *fileImppath; // array of char*'s of where to look for file import modules
char *runtimeImppath; // char* of where to look for the core runtime
char *objdir; // .obj file output directory
char *objname; // .obj file output name
char doDocComments; // process embedded documentation comments
char *docdir; // write documentation file to docdir directory
char *docname; // write documentation file to docname
Array *ddocfiles; // macro include files for Ddoc
char doHdrGeneration; // process embedded documentation comments
char *hdrdir; // write 'header' file to docdir directory
char *hdrname; // write 'header' file to docname
unsigned debuglevel; // debug level
Array *debugids; // debug identifiers
unsigned versionlevel; // version level
Array *versionids; // version identifiers
bool dump_source;
// Hidden debug switches
char debuga;
char debugb;
char debugc;
char debugf;
char debugr;
char debugw;
char debugx;
char debugy;
char run; // run resulting executable
size_t runargs_length;
char** runargs; // arguments for executable
// Linker stuff
Array *objfiles;
Array *linkswitches;
Array *libfiles;
char *deffile;
char *resfile;
char *exefile;
// LLVM stuff
char *llvmArch;
char forceBE;
char *tt_arch;
char *tt_os;
char *data_layout;
};
struct Global
{
char *mars_ext;
char *sym_ext;
char *obj_ext;
char *ll_ext;
char *bc_ext;
char *nativeobj_ext;
char *doc_ext; // for Ddoc generated files
char *ddoc_ext; // for Ddoc macro include files
char *hdr_ext; // for D 'header' import files
char *copyright;
char *written;
Array *path; // Array of char*'s which form the import lookup path
Array *filePath; // Array of char*'s which form the file import lookup path
int structalign;
char *version;
char *llvmdc_version;
Param params;
unsigned errors; // number of errors reported so far
unsigned gag; // !=0 means gag reporting of errors
Global();
};
extern Global global;
#if __GNUC__
//#define memicmp strncasecmp
//#define stricmp strcasecmp
#endif
#ifdef __DMC__
typedef _Complex long double complex_t;
#else
#ifndef IN_GCC
#include "complex_t.h"
#endif
#ifdef __APPLE__
//#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
#define integer_t dmd_integer_t
#endif
#endif
// Be careful not to care about sign when using integer_t
typedef uint64_t integer_t;
// Signed and unsigned variants
typedef int64_t sinteger_t;
typedef uint64_t uinteger_t;
typedef int8_t d_int8;
typedef uint8_t d_uns8;
typedef int16_t d_int16;
typedef uint16_t d_uns16;
typedef int32_t d_int32;
typedef uint32_t d_uns32;
typedef int64_t d_int64;
typedef uint64_t d_uns64;
typedef float d_float32;
typedef double d_float64;
typedef long double d_float80;
typedef d_uns8 d_char;
typedef d_uns16 d_wchar;
typedef d_uns32 d_dchar;
#ifdef IN_GCC
#include "d-gcc-real.h"
#else
typedef long double real_t;
#endif
// Modify OutBuffer::writewchar to write the correct size of wchar
#if _WIN32
#define writewchar writeword
#else
// This needs a configuration test...
#define writewchar write4
#endif
#ifdef IN_GCC
#include "d-gcc-complex_t.h"
#endif
struct Module;
//typedef unsigned Loc; // file location
struct Loc
{
char *filename;
unsigned linnum;
Loc()
{
linnum = 0;
filename = NULL;
}
Loc(int x)
{
linnum = x;
filename = NULL;
}
Loc(Module *mod, unsigned linnum);
char *toChars();
};
#ifndef GCC_SAFE_DMD
#define TRUE 1
#define FALSE 0
#endif
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
// in interface vtbl[]'s
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
// in the inheritance graph multiple
// times, only one is used
enum LINK
{
LINKdefault,
LINKd,
LINKc,
LINKcpp,
LINKwindows,
LINKpascal,
};
enum DYNCAST
{
DYNCAST_OBJECT,
DYNCAST_EXPRESSION,
DYNCAST_DSYMBOL,
DYNCAST_TYPE,
DYNCAST_IDENTIFIER,
DYNCAST_TUPLE,
};
enum MATCH
{
MATCHnomatch, // no match
MATCHconvert, // match with conversions
#if V2
MATCHconst, // match with conversion to const
#endif
MATCHexact // exact match
};
void error(Loc loc, const char *format, ...);
void verror(Loc loc, const char *format, va_list);
void fatal();
void err_nomem();
int runLINK();
void deleteExeFile();
int runProgram();
void inifile(char *argv0, char *inifile);
void halt();
/*** Where to send error messages ***/
#if IN_GCC
#define stdmsg stderr
#else
#define stdmsg stdout
#endif
#endif /* DMD_MARS_H */

144
dmd/mem.c Normal file
View File

@@ -0,0 +1,144 @@
/* Copyright (c) 2000 Digital Mars */
/* All Rights Reserved */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gc.h"
#include "mem.h"
/* This implementation of the storage allocator uses the standard C allocation package.
*/
Mem mem;
void Mem::init()
{
GC_init();
}
char *Mem::strdup(const char *s)
{
char *p;
if (s)
{
p = GC_strdup(s);
if (p)
return p;
error();
}
return NULL;
}
void *Mem::malloc(size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = GC_malloc(size);
if (!p)
error();
}
return p;
}
void *Mem::calloc(size_t size, size_t n)
{ void *p;
if (!size || !n)
p = NULL;
else
{
p = GC_malloc(size * n);
if (!p)
error();
memset(p, 0, size * n);
}
return p;
}
void *Mem::realloc(void *p, size_t size)
{
if (!size)
{ if (p)
{ GC_free(p);
p = NULL;
}
}
else if (!p)
{
p = GC_malloc(size);
if (!p)
error();
}
else
{
p = GC_realloc(p, size);
if (!p)
error();
}
return p;
}
void Mem::free(void *p)
{
if (p)
GC_free(p);
}
void *Mem::mallocdup(void *o, size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = GC_malloc(size);
if (!p)
error();
else
memcpy(p,o,size);
}
return p;
}
void Mem::error()
{
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
GC_gcollect();
}
void Mem::mark(void *pointer)
{
(void) pointer; // necessary for VC /W4
}
/* =================================================== */
void * operator new(size_t m_size)
{
void *p = GC_malloc(m_size);
if (p)
return p;
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
return p;
}
void operator delete(void *p)
{
GC_free(p);
}

51
dmd/mem.h Normal file
View File

@@ -0,0 +1,51 @@
// Copyright (C) 2000-2001 by Chromium Communications
// All Rights Reserved
#ifndef ROOT_MEM_H
#define ROOT_MEM_H
#include <stddef.h> // for size_t
typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
struct GC; // thread specific allocator
struct Mem
{
GC *gc; // pointer to our thread specific allocator
Mem() { gc = NULL; }
void init();
// Derive from Mem to get these storage allocators instead of global new/delete
void * operator new(size_t m_size);
void * operator new(size_t m_size, Mem *mem);
void * operator new(size_t m_size, GC *gc);
void operator delete(void *p);
void * operator new[](size_t m_size);
void operator delete[](void *p);
char *strdup(const char *s);
void *malloc(size_t size);
void *malloc_uncollectable(size_t size);
void *calloc(size_t size, size_t n);
void *realloc(void *p, size_t size);
void free(void *p);
void free_uncollectable(void *p);
void *mallocdup(void *o, size_t size);
void error();
void check(void *p); // validate pointer
void fullcollect(); // do full garbage collection
void fullcollectNoStack(); // do full garbage collection, no scan stack
void mark(void *pointer);
void addroots(char* pStart, char* pEnd);
void removeroots(char* pStart);
void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData);
void setStackBottom(void *bottom);
GC *getThreadGC(); // get apartment allocator for this thread
};
extern Mem mem;
#endif /* ROOT_MEM_H */

981
dmd/module.c Normal file
View File

@@ -0,0 +1,981 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#if IN_GCC
#include "gdc_alloca.h"
#endif
#include "mem.h"
#include "mars.h"
#include "module.h"
#include "parse.h"
#include "scope.h"
#include "identifier.h"
#include "id.h"
#include "import.h"
#include "dsymbol.h"
#include "hdrgen.h"
#include "lexer.h"
#define MARS 1
#include "html.h"
#ifdef IN_GCC
#include "d-dmd-gcc.h"
#endif
ClassDeclaration *Module::moduleinfo;
Module *Module::rootModule;
DsymbolTable *Module::modules;
Array Module::amodules;
Array Module::deferred; // deferred Dsymbol's needing semantic() run on them
unsigned Module::dprogress;
void Module::init()
{
modules = new DsymbolTable();
}
Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen)
: Package(ident)
{
FileName *srcfilename;
FileName *cfilename;
FileName *hfilename;
FileName *objfilename;
FileName *llfilename;
FileName *bcfilename;
FileName *symfilename;
// printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
this->arg = filename;
md = NULL;
errors = 0;
numlines = 0;
members = NULL;
isHtml = 0;
isDocFile = 0;
needmoduleinfo = 0;
#ifdef IN_GCC
strictlyneedmoduleinfo = 0;
#endif
insearch = 0;
searchCacheIdent = NULL;
searchCacheSymbol = NULL;
searchCacheFlags = 0;
semanticstarted = 0;
semanticdone = 0;
decldefs = NULL;
vmoduleinfo = NULL;
massert = NULL;
marray = NULL;
sctor = NULL;
sdtor = NULL;
stest = NULL;
sfilename = NULL;
root = 0;
importedFrom = NULL;
srcfile = NULL;
docfile = NULL;
debuglevel = 0;
debugids = NULL;
debugidsNot = NULL;
versionlevel = 0;
versionids = NULL;
versionidsNot = NULL;
macrotable = NULL;
escapetable = NULL;
cov = NULL;
covb = NULL;
srcfilename = FileName::defaultExt(filename, global.mars_ext);
if (!srcfilename->equalsExt(global.mars_ext))
{
if (srcfilename->equalsExt("html") ||
srcfilename->equalsExt("htm") ||
srcfilename->equalsExt("xhtml"))
isHtml = 1;
else
{ error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
fatal();
}
}
char *argobj;
if (global.params.objname)
argobj = global.params.objname;
else if (global.params.preservePaths)
argobj = filename;
else
argobj = FileName::name(filename);
if (!FileName::absolute(argobj))
{
argobj = FileName::combine(global.params.objdir, argobj);
}
if (global.params.objname)
objfilename = new FileName(argobj, 0);
else
objfilename = FileName::forceExt(argobj, global.obj_ext);
llfilename = FileName::forceExt(argobj, global.ll_ext);
bcfilename = FileName::forceExt(argobj, global.bc_ext);
symfilename = FileName::forceExt(filename, global.sym_ext);
srcfile = new File(srcfilename);
if (doDocComment)
{
setDocfile();
}
if (doHdrGen)
{
setHdrfile();
}
objfile = new File(objfilename);
bcfile = new File(bcfilename);
symfile = new File(symfilename);
}
void Module::setDocfile()
{
FileName *docfilename;
char *argdoc;
if (global.params.docname)
argdoc = global.params.docname;
else if (global.params.preservePaths)
argdoc = (char *)arg;
else
argdoc = FileName::name((char *)arg);
if (!FileName::absolute(argdoc))
{ //FileName::ensurePathExists(global.params.docdir);
argdoc = FileName::combine(global.params.docdir, argdoc);
}
if (global.params.docname)
docfilename = new FileName(argdoc, 0);
else
docfilename = FileName::forceExt(argdoc, global.doc_ext);
if (docfilename->equals(srcfile->name))
{ error("Source file and documentation file have same name '%s'", srcfile->name->str);
fatal();
}
docfile = new File(docfilename);
}
void Module::setHdrfile()
{
FileName *hdrfilename;
char *arghdr;
if (global.params.hdrname)
arghdr = global.params.hdrname;
else if (global.params.preservePaths)
arghdr = (char *)arg;
else
arghdr = FileName::name((char *)arg);
if (!FileName::absolute(arghdr))
{ //FileName::ensurePathExists(global.params.hdrdir);
arghdr = FileName::combine(global.params.hdrdir, arghdr);
}
if (global.params.hdrname)
hdrfilename = new FileName(arghdr, 0);
else
hdrfilename = FileName::forceExt(arghdr, global.hdr_ext);
if (hdrfilename->equals(srcfile->name))
{ error("Source file and 'header' file have same name '%s'", srcfile->name->str);
fatal();
}
hdrfile = new File(hdrfilename);
}
void Module::deleteObjFile()
{
if (global.params.obj)
objfile->remove();
//if (global.params.llvmBC)
bcfile->remove();
if (docfile)
docfile->remove();
}
Module::~Module()
{
}
char *Module::kind()
{
return "module";
}
Module *Module::load(Loc loc, Array *packages, Identifier *ident)
{ Module *m;
char *filename;
//printf("Module::load(ident = '%s')\n", ident->toChars());
// Build module filename by turning:
// foo.bar.baz
// into:
// foo\bar\baz
filename = ident->toChars();
if (packages && packages->dim)
{
OutBuffer buf;
int i;
for (i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
buf.writestring(pid->toChars());
#if _WIN32
buf.writeByte('\\');
#else
buf.writeByte('/');
#endif
}
buf.writestring(filename);
buf.writeByte(0);
filename = (char *)buf.extractData();
}
m = new Module(filename, ident, 0, 0);
m->loc = loc;
/* Search along global.path for .di file, then .d file.
*/
char *result = NULL;
FileName *fdi = FileName::forceExt(filename, global.hdr_ext);
FileName *fd = FileName::forceExt(filename, global.mars_ext);
char *sdi = fdi->toChars();
char *sd = fd->toChars();
if (FileName::exists(sdi))
result = sdi;
else if (FileName::exists(sd))
result = sd;
else if (FileName::absolute(filename))
;
else if (!global.path)
;
else
{
for (size_t i = 0; i < global.path->dim; i++)
{
char *p = (char *)global.path->data[i];
char *n = FileName::combine(p, sdi);
if (FileName::exists(n))
{ result = n;
break;
}
mem.free(n);
n = FileName::combine(p, sd);
if (FileName::exists(n))
{ result = n;
break;
}
mem.free(n);
}
}
if (result)
m->srcfile = new File(result);
if (global.params.verbose)
{
printf("import ");
if (packages)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
printf("%s.", pid->toChars());
}
}
printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
}
m->read(loc);
m->parse();
#ifdef IN_GCC
d_gcc_magic_module(m);
#endif
return m;
}
void Module::read(Loc loc)
{
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
if (srcfile->read())
{ error(loc, "cannot read file '%s'", srcfile->toChars());
fatal();
}
}
inline unsigned readwordLE(unsigned short *p)
{
#if __I86__
return *p;
#else
return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0];
#endif
}
inline unsigned readwordBE(unsigned short *p)
{
return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1];
}
inline unsigned readlongLE(unsigned *p)
{
#if __I86__
return *p;
#else
return ((unsigned char *)p)[0] |
(((unsigned char *)p)[1] << 8) |
(((unsigned char *)p)[2] << 16) |
(((unsigned char *)p)[3] << 24);
#endif
}
inline unsigned readlongBE(unsigned *p)
{
return ((unsigned char *)p)[3] |
(((unsigned char *)p)[2] << 8) |
(((unsigned char *)p)[1] << 16) |
(((unsigned char *)p)[0] << 24);
}
#if IN_GCC
void Module::parse(bool dump_source)
#else
void Module::parse()
#endif
{ char *srcname;
unsigned char *buf;
unsigned buflen;
unsigned le;
unsigned bom;
//printf("Module::parse()\n");
srcname = srcfile->name->toChars();
//printf("Module::parse(srcname = '%s')\n", srcname);
buf = srcfile->buffer;
buflen = srcfile->len;
if (buflen >= 2)
{
/* Convert all non-UTF-8 formats to UTF-8.
* BOM : http://www.unicode.org/faq/utf_bom.html
* 00 00 FE FF UTF-32BE, big-endian
* FF FE 00 00 UTF-32LE, little-endian
* FE FF UTF-16BE, big-endian
* FF FE UTF-16LE, little-endian
* EF BB BF UTF-8
*/
bom = 1; // assume there's a BOM
if (buf[0] == 0xFF && buf[1] == 0xFE)
{
if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
{ // UTF-32LE
le = 1;
Lutf32:
OutBuffer dbuf;
unsigned *pu = (unsigned *)(buf);
unsigned *pumax = &pu[buflen / 4];
if (buflen & 3)
{ error("odd length of UTF-32 char source %u", buflen);
fatal();
}
dbuf.reserve(buflen / 4);
for (pu += bom; pu < pumax; pu++)
{ unsigned u;
u = le ? readlongLE(pu) : readlongBE(pu);
if (u & ~0x7F)
{
if (u > 0x10FFFF)
{ error("UTF-32 value %08x greater than 0x10FFFF", u);
fatal();
}
dbuf.writeUTF8(u);
}
else
dbuf.writeByte(u);
}
dbuf.writeByte(0); // add 0 as sentinel for scanner
buflen = dbuf.offset - 1; // don't include sentinel in count
buf = (unsigned char *) dbuf.extractData();
}
else
{ // UTF-16LE (X86)
// Convert it to UTF-8
le = 1;
Lutf16:
OutBuffer dbuf;
unsigned short *pu = (unsigned short *)(buf);
unsigned short *pumax = &pu[buflen / 2];
if (buflen & 1)
{ error("odd length of UTF-16 char source %u", buflen);
fatal();
}
dbuf.reserve(buflen / 2);
for (pu += bom; pu < pumax; pu++)
{ unsigned u;
u = le ? readwordLE(pu) : readwordBE(pu);
if (u & ~0x7F)
{ if (u >= 0xD800 && u <= 0xDBFF)
{ unsigned u2;
if (++pu > pumax)
{ error("surrogate UTF-16 high value %04x at EOF", u);
fatal();
}
u2 = le ? readwordLE(pu) : readwordBE(pu);
if (u2 < 0xDC00 || u2 > 0xDFFF)
{ error("surrogate UTF-16 low value %04x out of range", u2);
fatal();
}
u = (u - 0xD7C0) << 10;
u |= (u2 - 0xDC00);
}
else if (u >= 0xDC00 && u <= 0xDFFF)
{ error("unpaired surrogate UTF-16 value %04x", u);
fatal();
}
else if (u == 0xFFFE || u == 0xFFFF)
{ error("illegal UTF-16 value %04x", u);
fatal();
}
dbuf.writeUTF8(u);
}
else
dbuf.writeByte(u);
}
dbuf.writeByte(0); // add 0 as sentinel for scanner
buflen = dbuf.offset - 1; // don't include sentinel in count
buf = (unsigned char *) dbuf.extractData();
}
}
else if (buf[0] == 0xFE && buf[1] == 0xFF)
{ // UTF-16BE
le = 0;
goto Lutf16;
}
else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
{ // UTF-32BE
le = 0;
goto Lutf32;
}
else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
{ // UTF-8
buf += 3;
buflen -= 3;
}
else
{
/* There is no BOM. Make use of Arcane Jill's insight that
* the first char of D source must be ASCII to
* figure out the encoding.
*/
bom = 0;
if (buflen >= 4)
{ if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
{ // UTF-32LE
le = 1;
goto Lutf32;
}
else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
{ // UTF-32BE
le = 0;
goto Lutf32;
}
}
if (buflen >= 2)
{
if (buf[1] == 0)
{ // UTF-16LE
le = 1;
goto Lutf16;
}
else if (buf[0] == 0)
{ // UTF-16BE
le = 0;
goto Lutf16;
}
}
// It's UTF-8
if (buf[0] >= 0x80)
{ error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
fatal();
}
}
}
#ifdef IN_GCC
// dump utf-8 encoded source
if (dump_source)
{ // %% srcname could contain a path ...
d_gcc_dump_source(srcname, "utf-8", buf, buflen);
}
#endif
/* If it starts with the string "Ddoc", then it's a documentation
* source file.
*/
if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0)
{
comment = buf + 4;
isDocFile = 1;
if (!docfile)
setDocfile();
return;
}
if (isHtml)
{
OutBuffer *dbuf = new OutBuffer();
Html h(srcname, buf, buflen);
h.extractCode(dbuf);
buf = dbuf->data;
buflen = dbuf->offset;
#ifdef IN_GCC
// dump extracted source
if (dump_source)
d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
#endif
}
Parser p(this, buf, buflen, docfile != NULL);
p.nextToken();
members = p.parseModule();
md = p.md;
numlines = p.loc.linnum;
DsymbolTable *dst;
if (md)
{ this->ident = md->id;
dst = Package::resolve(md->packages, &this->parent, NULL);
}
else
{
dst = modules;
/* Check to see if module name is a valid identifier
*/
if (!Lexer::isValidIdentifier(this->ident->toChars()))
error("has non-identifier characters in filename, use module declaration instead");
}
// Update global list of modules
if (!dst->insert(this))
{
if (md)
error(loc, "is in multiple packages %s", md->toChars());
else
error(loc, "is in multiple defined");
}
else
{
amodules.push(this);
}
}
void Module::semantic()
{ int i;
if (semanticstarted)
return;
//printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
semanticstarted = 1;
// Note that modules get their own scope, from scratch.
// This is so regardless of where in the syntax a module
// gets imported, it is unaffected by context.
Scope *sc = Scope::createGlobal(this); // create root scope
//printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
// Add import of "object" if this module isn't "object"
if (ident != Id::object)
{
Import *im = new Import(0, NULL, Id::object, NULL, 0);
members->shift(im);
}
// Add all symbols into module's symbol table
symtab = new DsymbolTable();
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
s->addMember(NULL, sc->scopesym, 1);
}
// Pass 1 semantic routines: do public side of the definition
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
//printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
s->semantic(sc);
runDeferredSemantic();
}
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
//printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
}
void Module::semantic2()
{ int i;
if (deferred.dim)
{
for (int i = 0; i < deferred.dim; i++)
{
Dsymbol *sd = (Dsymbol *)deferred.data[i];
sd->error("unable to resolve forward reference in definition");
}
return;
}
//printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
if (semanticstarted >= 2)
return;
assert(semanticstarted == 1);
semanticstarted = 2;
// Note that modules get their own scope, from scratch.
// This is so regardless of where in the syntax a module
// gets imported, it is unaffected by context.
Scope *sc = Scope::createGlobal(this); // create root scope
//printf("Module = %p\n", sc.scopesym);
// Pass 2 semantic routines: do initializers and function bodies
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
s->semantic2(sc);
}
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
//printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
}
void Module::semantic3()
{ int i;
//printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
if (semanticstarted >= 3)
return;
assert(semanticstarted == 2);
semanticstarted = 3;
// Note that modules get their own scope, from scratch.
// This is so regardless of where in the syntax a module
// gets imported, it is unaffected by context.
Scope *sc = Scope::createGlobal(this); // create root scope
//printf("Module = %p\n", sc.scopesym);
// Pass 3 semantic routines: do initializers and function bodies
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
//printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
s->semantic3(sc);
}
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
}
void Module::inlineScan()
{ int i;
if (semanticstarted >= 4)
return;
assert(semanticstarted == 3);
semanticstarted = 4;
// Note that modules get their own scope, from scratch.
// This is so regardless of where in the syntax a module
// gets imported, it is unaffected by context.
//printf("Module = %p\n", sc.scopesym);
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
//if (global.params.verbose)
//printf("inline scan symbol %s\n", s->toChars());
s->inlineScan();
}
semanticdone = semanticstarted;
}
/****************************************************
*/
void Module::gensymfile()
{
OutBuffer buf;
HdrGenState hgs;
int i;
//printf("Module::gensymfile()\n");
buf.printf("// Sym file generated from '%s'", srcfile->toChars());
buf.writenl();
for (i = 0; i < members->dim; i++)
{
Dsymbol *s;
s = (Dsymbol *)members->data[i];
s->toCBuffer(&buf, &hgs);
}
// Transfer image to file
symfile->setbuffer(buf.data, buf.offset);
buf.data = NULL;
symfile->writev();
}
/**********************************
* Determine if we need to generate an instance of ModuleInfo
* for this Module.
*/
int Module::needModuleInfo()
{
return needmoduleinfo || global.params.cov;
}
Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
{
/* Since modules can be circularly referenced,
* need to stop infinite recursive searches.
*/
//printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
Dsymbol *s;
if (insearch)
s = NULL;
else if (searchCacheIdent == ident && searchCacheFlags == flags)
s = searchCacheSymbol;
else
{
insearch = 1;
s = ScopeDsymbol::search(loc, ident, flags);
insearch = 0;
searchCacheIdent = ident;
searchCacheSymbol = s;
searchCacheFlags = flags;
}
return s;
}
/*******************************************
* Can't run semantic on s now, try again later.
*/
void Module::addDeferredSemantic(Dsymbol *s)
{
// Don't add it if it is already there
for (int i = 0; i < deferred.dim; i++)
{
Dsymbol *sd = (Dsymbol *)deferred.data[i];
if (sd == s)
return;
}
//printf("Module::addDeferredSemantic('%s')\n", s->toChars());
deferred.push(s);
}
/******************************************
* Run semantic() on deferred symbols.
*/
void Module::runDeferredSemantic()
{
size_t len;
static int nested;
if (nested)
return;
//if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
nested++;
do
{
dprogress = 0;
len = deferred.dim;
if (!len)
break;
Dsymbol **todo;
Dsymbol *tmp;
if (len == 1)
{
todo = &tmp;
}
else
{
todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *));
assert(todo);
}
memcpy(todo, deferred.data, len * sizeof(Dsymbol *));
deferred.setDim(0);
for (int i = 0; i < len; i++)
{
Dsymbol *s = todo[i];
s->semantic(NULL);
//printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
}
//printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
} while (deferred.dim < len || dprogress); // while making progress
nested--;
//printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
}
/* =========================== ModuleDeclaration ===================== */
ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id)
{
this->packages = packages;
this->id = id;
}
char *ModuleDeclaration::toChars()
{
OutBuffer buf;
int i;
if (packages && packages->dim)
{
for (i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
buf.writestring(pid->toChars());
buf.writeByte('.');
}
}
buf.writestring(id->toChars());
buf.writeByte(0);
return (char *)buf.extractData();
}
/* =========================== Package ===================== */
Package::Package(Identifier *ident)
: ScopeDsymbol(ident)
{
}
char *Package::kind()
{
return "package";
}
DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg)
{
DsymbolTable *dst = Module::modules;
Dsymbol *parent = NULL;
//printf("Package::resolve()\n");
if (ppkg)
*ppkg = NULL;
if (packages)
{ int i;
for (i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
Dsymbol *p;
p = dst->lookup(pid);
if (!p)
{
p = new Package(pid);
dst->insert(p);
p->parent = parent;
((ScopeDsymbol *)p)->symtab = new DsymbolTable();
}
else
{
assert(p->isPackage());
if (p->isModule())
{ p->error("module and package have the same name");
fatal();
break;
}
}
parent = p;
dst = ((Package *)p)->symtab;
if (ppkg && !*ppkg)
*ppkg = (Package *)p;
}
if (pparent)
{
*pparent = parent;
}
}
return dst;
}

177
dmd/module.h Normal file
View File

@@ -0,0 +1,177 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_MODULE_H
#define DMD_MODULE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct ModuleInfoDeclaration;
struct ClassDeclaration;
struct ModuleDeclaration;
struct Macro;
struct Escape;
struct VarDeclaration;
// Back end
#if IN_GCC
union tree_node; typedef union tree_node elem;
#else
struct elem;
#endif
struct Package : ScopeDsymbol
{
Package(Identifier *ident);
char *kind();
static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg);
Package *isPackage() { return this; }
virtual void semantic(Scope *sc) { }
};
struct Module : Package
{
static Module *rootModule;
static DsymbolTable *modules; // symbol table of all modules
static Array amodules; // array of all modules
static Array deferred; // deferred Dsymbol's needing semantic() run on them
static unsigned dprogress; // progress resolving the deferred list
static void init();
static ClassDeclaration *moduleinfo;
const char *arg; // original argument name
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
File *srcfile; // input source file
File *objfile; // output .obj file
File *bcfile; // output .bc file
File *hdrfile; // 'header' file
File *symfile; // output symbol file
File *docfile; // output documentation file
unsigned errors; // if any errors in file
unsigned numlines; // number of lines in source file
int isHtml; // if it is an HTML file
int isDocFile; // if it is a documentation input file, not D source
int needmoduleinfo;
#ifdef IN_GCC
int strictlyneedmoduleinfo;
#endif
int insearch;
Identifier *searchCacheIdent;
Dsymbol *searchCacheSymbol; // cached value of search
int searchCacheFlags; // cached flags
int semanticstarted; // has semantic() been started?
int semanticdone; // has semantic() been done?
int root; // != 0 if this is a 'root' module,
// i.e. a module that will be taken all the
// way to an object file
Module *importedFrom; // module from command line we're imported from,
// i.e. a module that will be taken all the
// way to an object file
Array *decldefs; // top level declarations for this Module
Array aimports; // all imported modules
ModuleInfoDeclaration *vmoduleinfo;
unsigned debuglevel; // debug level
Array *debugids; // debug identifiers
Array *debugidsNot; // forward referenced debug identifiers
unsigned versionlevel; // version level
Array *versionids; // version identifiers
Array *versionidsNot; // forward referenced version identifiers
Macro *macrotable; // document comment macros
Escape *escapetable; // document comment escapes
Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
~Module();
static Module *load(Loc loc, Array *packages, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
void setDocfile(); // set docfile member
void read(Loc loc); // read file
#if IN_GCC
void parse(bool dump_source = false); // syntactic parse
#else
void parse(); // syntactic parse
#endif
void semantic(); // semantic analysis
void semantic2(); // pass 2 semantic analysis
void semantic3(); // pass 3 semantic analysis
void inlineScan(); // scan for functions to inline
void setHdrfile(); // set hdrfile member
#ifdef _DH
void genhdrfile(); // generate D import file
#endif
void genobjfile();
void gensymfile();
void gendocfile();
int needModuleInfo();
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void deleteObjFile();
void addDeferredSemantic(Dsymbol *s);
void runDeferredSemantic();
// Back end
Symbol *cov; // private uint[] __coverage;
unsigned *covb; // bit array of valid code line numbers
Symbol *sctor; // module constructor
Symbol *sdtor; // module destructor
Symbol *stest; // module unit test
Symbol *sfilename; // symbol for filename
Symbol *massert; // module assert function
Symbol *toModuleAssert(); // get module assert function
Symbol *marray; // module array bounds function
Symbol *toModuleArray(); // get module array bounds function
static Symbol *gencritsec();
elem *toEfilename();
elem *toEmodulename();
Symbol *toSymbol();
void genmoduleinfo();
Module *isModule() { return this; }
};
struct ModuleDeclaration
{
Identifier *id;
Array *packages; // array of Identifier's representing packages
ModuleDeclaration(Array *packages, Identifier *id);
char *toChars();
};
#endif /* DMD_MODULE_H */

5216
dmd/mtype.c Normal file

File diff suppressed because it is too large Load Diff

705
dmd/mtype.h Normal file
View File

@@ -0,0 +1,705 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_MTYPE_H
#define DMD_MTYPE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "stringtable.h"
#include "arraytypes.h"
#include "expression.h"
namespace llvm
{
class Value;
class Type;
class Instruction;
}
struct Scope;
struct Identifier;
struct Expression;
struct StructDeclaration;
struct ClassDeclaration;
struct VarDeclaration;
struct EnumDeclaration;
struct TypedefDeclaration;
struct TypeInfoDeclaration;
struct Dsymbol;
struct TemplateInstance;
enum LINK;
struct TypeBasic;
struct HdrGenState;
// Back end
#if IN_GCC
union tree_node; typedef union tree_node TYPE;
typedef TYPE type;
#else
typedef struct TYPE type;
#endif
struct Symbol;
enum TY
{
Tarray, // dynamic array
Tsarray, // static array
Taarray, // associative array
Tpointer,
Treference,
Tfunction,
Tident,
Tclass,
Tstruct,
Tenum,
Ttypedef,
Tdelegate,
Tnone,
Tvoid,
Tint8,
Tuns8,
Tint16,
Tuns16,
Tint32,
Tuns32,
Tint64,
Tuns64,
Tfloat32,
Tfloat64,
Tfloat80,
Timaginary32,
Timaginary64,
Timaginary80,
Tcomplex32,
Tcomplex64,
Tcomplex80,
Tbit,
Tbool,
Tchar,
Twchar,
Tdchar,
Terror,
Tinstance,
Ttypeof,
Ttuple,
Tslice,
TMAX
};
#define Tascii Tchar
extern int Tsize_t;
extern int Tptrdiff_t;
struct Type : Object
{
TY ty;
Type *next;
char *deco;
Type *pto; // merged pointer to this type
Type *rto; // reference to this type
Type *arrayof; // array of this type
TypeInfoDeclaration *vtinfo; // TypeInfo object for this Type
type *ctype; // for back end
#define tvoid basic[Tvoid]
#define tint8 basic[Tint8]
#define tuns8 basic[Tuns8]
#define tint16 basic[Tint16]
#define tuns16 basic[Tuns16]
#define tint32 basic[Tint32]
#define tuns32 basic[Tuns32]
#define tint64 basic[Tint64]
#define tuns64 basic[Tuns64]
#define tfloat32 basic[Tfloat32]
#define tfloat64 basic[Tfloat64]
#define tfloat80 basic[Tfloat80]
#define timaginary32 basic[Timaginary32]
#define timaginary64 basic[Timaginary64]
#define timaginary80 basic[Timaginary80]
#define tcomplex32 basic[Tcomplex32]
#define tcomplex64 basic[Tcomplex64]
#define tcomplex80 basic[Tcomplex80]
#define tbit basic[Tbit]
#define tbool basic[Tbool]
#define tchar basic[Tchar]
#define twchar basic[Twchar]
#define tdchar basic[Tdchar]
// Some special types
#define tshiftcnt tint32 // right side of shift expression
// #define tboolean tint32 // result of boolean expression
#define tboolean tbool // result of boolean expression
#define tindex tint32 // array/ptr index
static Type *tvoidptr; // void*
#define terror basic[Terror] // for error recovery
#define tsize_t basic[Tsize_t] // matches size_t alias
#define tptrdiff_t basic[Tptrdiff_t] // matches ptrdiff_t alias
#define thash_t tsize_t // matches hash_t alias
static ClassDeclaration *typeinfo;
static ClassDeclaration *typeinfoclass;
static ClassDeclaration *typeinfointerface;
static ClassDeclaration *typeinfostruct;
static ClassDeclaration *typeinfotypedef;
static ClassDeclaration *typeinfopointer;
static ClassDeclaration *typeinfoarray;
static ClassDeclaration *typeinfostaticarray;
static ClassDeclaration *typeinfoassociativearray;
static ClassDeclaration *typeinfoenum;
static ClassDeclaration *typeinfofunction;
static ClassDeclaration *typeinfodelegate;
static ClassDeclaration *typeinfotypelist;
static Type *basic[TMAX];
static unsigned char mangleChar[TMAX];
static StringTable stringtable;
// These tables are for implicit conversion of binary ops;
// the indices are the type of operand one, followed by operand two.
static unsigned char impcnvResult[TMAX][TMAX];
static unsigned char impcnvType1[TMAX][TMAX];
static unsigned char impcnvType2[TMAX][TMAX];
// If !=0, give warning on implicit conversion
static unsigned char impcnvWarn[TMAX][TMAX];
Type(TY ty, Type *next);
virtual Type *syntaxCopy();
int equals(Object *o);
int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
int covariant(Type *t);
char *toChars();
static char needThisPrefix();
static void init();
d_uns64 size();
virtual d_uns64 size(Loc loc);
virtual unsigned alignsize();
virtual Type *semantic(Loc loc, Scope *sc);
virtual void toDecoBuffer(OutBuffer *buf);
virtual void toTypeInfoBuffer(OutBuffer *buf);
Type *merge();
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
virtual void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
virtual int isbit();
virtual int isintegral();
virtual int isfloating(); // real, imaginary, or complex
virtual int isreal();
virtual int isimaginary();
virtual int iscomplex();
virtual int isscalar();
virtual int isunsigned();
virtual int isauto();
virtual int isString();
virtual int checkBoolean(); // if can be converted to boolean value
void checkDeprecated(Loc loc, Scope *sc);
Type *pointerTo();
Type *referenceTo();
Type *arrayOf();
virtual Dsymbol *toDsymbol(Scope *sc);
virtual Type *toBasetype();
virtual int isBaseOf(Type *t, int *poffset);
virtual MATCH implicitConvTo(Type *to);
virtual ClassDeclaration *isClassHandle();
virtual Expression *getProperty(Loc loc, Identifier *ident);
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
virtual unsigned memalign(unsigned salign);
virtual Expression *defaultInit();
virtual int isZeroInit(); // if initializer is 0
virtual dt_t **toDt(dt_t **pdt);
Identifier *getTypeInfoIdent(int internal);
virtual MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Expression *getInternalTypeInfo(Scope *sc);
Expression *getTypeInfo(Scope *sc);
virtual TypeInfoDeclaration *getTypeInfoDeclaration();
virtual int builtinTypeInfo();
virtual Type *reliesOnTident();
virtual Expression *toExpression();
virtual int hasPointers();
Type *nextOf() { return next; }
static void error(Loc loc, const char *format, ...);
// For backend
virtual unsigned totym();
virtual type *toCtype();
virtual type *toCParamtype();
virtual Symbol *toSymbol();
llvm::Type* llvmType;
// For eliminating dynamic_cast
virtual TypeBasic *isTypeBasic();
};
struct TypeBasic : Type
{
char *dstring;
char *cstring;
unsigned flags;
TypeBasic(TY ty);
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
char *toChars();
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
int isintegral();
int isbit();
int isfloating();
int isreal();
int isimaginary();
int iscomplex();
int isscalar();
int isunsigned();
MATCH implicitConvTo(Type *to);
Expression *defaultInit();
int isZeroInit();
int builtinTypeInfo();
// For eliminating dynamic_cast
TypeBasic *isTypeBasic();
};
struct TypeArray : Type
{
TypeArray(TY ty, Type *next);
virtual void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs) = 0;
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
};
// Static array, one with a fixed dimension
struct TypeSArray : TypeArray
{
Expression *dim;
TypeSArray(Type *t, Expression *dim);
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf);
void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit();
unsigned memalign(unsigned salign);
MATCH implicitConvTo(Type *to);
Expression *defaultInit();
dt_t **toDt(dt_t **pdt);
dt_t **toDtElem(dt_t **pdt, Expression *e);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration();
Expression *toExpression();
int hasPointers();
type *toCtype();
type *toCParamtype();
};
// Dynamic array, no dimension
struct TypeDArray : TypeArray
{
TypeDArray(Type *t);
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf);
void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit();
int checkBoolean();
MATCH implicitConvTo(Type *to);
Expression *defaultInit();
int builtinTypeInfo();
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
type *toCtype();
};
struct TypeAArray : TypeArray
{
Type *index; // key type for type checking
Type *key; // actual key type
TypeAArray(Type *t, Type *index);
Type *syntaxCopy();
d_uns64 size(Loc loc);
Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf);
void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit();
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
// Back end
Symbol *aaGetSymbol(char *func, int flags);
type *toCtype();
};
struct TypePointer : Type
{
TypePointer(Type *t);
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
MATCH implicitConvTo(Type *to);
int isscalar();
Expression *defaultInit();
int isZeroInit();
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
type *toCtype();
};
struct TypeReference : Type
{
TypeReference(Type *t);
Type *syntaxCopy();
d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit();
int isZeroInit();
};
enum RET
{
RETregs = 1, // returned in registers
RETstack = 2, // returned on stack
};
struct TypeFunction : Type
{
Arguments *parameters; // function parameters
int varargs; // 1: T t, ...) style for variable number of arguments
// 2: T t ...) style for variable number of arguments
enum LINK linkage; // calling convention
int inuse;
TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage);
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration();
Type *reliesOnTident();
int callMatch(Expressions *toargs);
type *toCtype();
enum RET retStyle();
unsigned totym();
bool llvmRetInPtr;
llvm::Value* llvmRetArg;
llvm::Instruction* llvmAllocaPoint;
};
struct TypeDelegate : Type
{
TypeDelegate(Type *t);
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *defaultInit();
int isZeroInit();
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int hasPointers();
type *toCtype();
};
struct TypeQualified : Type
{
Loc loc;
Array idents; // array of Identifier's representing ident.ident.ident etc.
TypeQualified(TY ty, Loc loc);
void syntaxCopyHelper(TypeQualified *t);
void addIdent(Identifier *ident);
void toCBuffer2Helper(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
d_uns64 size(Loc loc);
void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
Expression **pe, Type **pt, Dsymbol **ps);
};
struct TypeIdentifier : TypeQualified
{
Identifier *ident;
TypeIdentifier(Loc loc, Identifier *ident);
Type *syntaxCopy();
//char *toChars();
void toDecoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
Type *reliesOnTident();
Expression *toExpression();
};
/* Similar to TypeIdentifier, but with a TemplateInstance as the root
*/
struct TypeInstance : TypeQualified
{
TemplateInstance *tempinst;
TypeInstance(Loc loc, TemplateInstance *tempinst);
Type *syntaxCopy();
//char *toChars();
//void toDecoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Type *semantic(Loc loc, Scope *sc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
};
struct TypeTypeof : TypeQualified
{
Expression *exp;
TypeTypeof(Loc loc, Expression *exp);
Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
};
struct TypeStruct : Type
{
StructDeclaration *sym;
TypeStruct(StructDeclaration *sym);
d_uns64 size(Loc loc);
unsigned alignsize();
char *toChars();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
unsigned memalign(unsigned salign);
Expression *defaultInit();
int isZeroInit();
int checkBoolean();
dt_t **toDt(dt_t **pdt);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
type *toCtype();
llvm::Value* llvmInit;
};
struct TypeEnum : Type
{
EnumDeclaration *sym;
TypeEnum(EnumDeclaration *sym);
d_uns64 size(Loc loc);
unsigned alignsize();
char *toChars();
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident);
int isintegral();
int isfloating();
int isscalar();
int isunsigned();
MATCH implicitConvTo(Type *to);
Type *toBasetype();
Expression *defaultInit();
int isZeroInit();
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
type *toCtype();
};
struct TypeTypedef : Type
{
TypedefDeclaration *sym;
TypeTypedef(TypedefDeclaration *sym);
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
char *toChars();
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isbit();
int isintegral();
int isfloating();
int isreal();
int isimaginary();
int iscomplex();
int isscalar();
int isunsigned();
int checkBoolean();
Type *toBasetype();
MATCH implicitConvTo(Type *to);
Expression *defaultInit();
int isZeroInit();
dt_t **toDt(dt_t **pdt);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
type *toCtype();
type *toCParamtype();
};
struct TypeClass : Type
{
ClassDeclaration *sym;
TypeClass(ClassDeclaration *sym);
d_uns64 size(Loc loc);
char *toChars();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
ClassDeclaration *isClassHandle();
int isBaseOf(Type *t, int *poffset);
MATCH implicitConvTo(Type *to);
Expression *defaultInit();
int isZeroInit();
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
int isauto();
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
type *toCtype();
Symbol *toSymbol();
llvm::Value* llvmInit;
};
struct TypeTuple : Type
{
Arguments *arguments; // types making up the tuple
TypeTuple(Arguments *arguments);
TypeTuple(Expressions *exps);
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
int equals(Object *o);
Type *reliesOnTident();
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toDecoBuffer(OutBuffer *buf);
Expression *getProperty(Loc loc, Identifier *ident);
TypeInfoDeclaration *getTypeInfoDeclaration();
};
struct TypeSlice : Type
{
Expression *lwr;
Expression *upr;
TypeSlice(Type *next, Expression *lwr, Expression *upr);
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
};
/**************************************************************/
//enum InOut { None, In, Out, InOut, Lazy };
struct Argument : Object
{
//enum InOut inout;
unsigned storageClass;
Type *type;
Identifier *ident;
Expression *defaultArg;
Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg);
Argument *syntaxCopy();
Type *isLazyArray();
void toDecoBuffer(OutBuffer *buf);
static Arguments *arraySyntaxCopy(Arguments *args);
static char *argsTypesToChars(Arguments *args, int varargs);
static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs);
static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
static size_t dim(Arguments *arguments);
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
// backend
bool llvmCopy;
VarDeclaration* vardecl;
};
extern int PTRSIZE;
extern int REALSIZE;
extern int REALPAD;
extern int Tsize_t;
extern int Tptrdiff_t;
#endif /* DMD_MTYPE_H */

748
dmd/opover.c Normal file
View File

@@ -0,0 +1,748 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <complex>
#ifdef __APPLE__
#define integer_t dmd_integer_t
#endif
#if IN_GCC || IN_LLVM
#include "mem.h"
#elif linux
#include "../root/mem.h"
#elif _WIN32
#include "..\root\mem.h"
#endif
//#include "port.h"
#include "mtype.h"
#include "init.h"
#include "expression.h"
#include "id.h"
#include "declaration.h"
#include "aggregate.h"
#include "template.h"
static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id);
static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments);
static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments);
/******************************** Expression **************************/
/***********************************
* Determine if operands of binary op can be reversed
* to fit operator overload.
*/
int Expression::isCommutative()
{
return FALSE; // default is no reverse
}
/***********************************
* Get Identifier for operator overload.
*/
Identifier *Expression::opId()
{
assert(0);
return NULL;
}
/***********************************
* Get Identifier for reverse operator overload,
* NULL if not supported for this operator.
*/
Identifier *Expression::opId_r()
{
return NULL;
}
/************************* Operators *****************************/
Identifier *UAddExp::opId() { return Id::uadd; }
Identifier *NegExp::opId() { return Id::neg; }
Identifier *ComExp::opId() { return Id::com; }
Identifier *CastExp::opId() { return Id::cast; }
Identifier *InExp::opId() { return Id::opIn; }
Identifier *InExp::opId_r() { return Id::opIn_r; }
Identifier *PostExp::opId() { return (op == TOKplusplus)
? Id::postinc
: Id::postdec; }
int AddExp::isCommutative() { return TRUE; }
Identifier *AddExp::opId() { return Id::add; }
Identifier *AddExp::opId_r() { return Id::add_r; }
Identifier *MinExp::opId() { return Id::sub; }
Identifier *MinExp::opId_r() { return Id::sub_r; }
int MulExp::isCommutative() { return TRUE; }
Identifier *MulExp::opId() { return Id::mul; }
Identifier *MulExp::opId_r() { return Id::mul_r; }
Identifier *DivExp::opId() { return Id::div; }
Identifier *DivExp::opId_r() { return Id::div_r; }
Identifier *ModExp::opId() { return Id::mod; }
Identifier *ModExp::opId_r() { return Id::mod_r; }
Identifier *ShlExp::opId() { return Id::shl; }
Identifier *ShlExp::opId_r() { return Id::shl_r; }
Identifier *ShrExp::opId() { return Id::shr; }
Identifier *ShrExp::opId_r() { return Id::shr_r; }
Identifier *UshrExp::opId() { return Id::ushr; }
Identifier *UshrExp::opId_r() { return Id::ushr_r; }
int AndExp::isCommutative() { return TRUE; }
Identifier *AndExp::opId() { return Id::iand; }
Identifier *AndExp::opId_r() { return Id::iand_r; }
int OrExp::isCommutative() { return TRUE; }
Identifier *OrExp::opId() { return Id::ior; }
Identifier *OrExp::opId_r() { return Id::ior_r; }
int XorExp::isCommutative() { return TRUE; }
Identifier *XorExp::opId() { return Id::ixor; }
Identifier *XorExp::opId_r() { return Id::ixor_r; }
Identifier *CatExp::opId() { return Id::cat; }
Identifier *CatExp::opId_r() { return Id::cat_r; }
Identifier * AssignExp::opId() { return Id::assign; }
Identifier * AddAssignExp::opId() { return Id::addass; }
Identifier * MinAssignExp::opId() { return Id::subass; }
Identifier * MulAssignExp::opId() { return Id::mulass; }
Identifier * DivAssignExp::opId() { return Id::divass; }
Identifier * ModAssignExp::opId() { return Id::modass; }
Identifier * AndAssignExp::opId() { return Id::andass; }
Identifier * OrAssignExp::opId() { return Id::orass; }
Identifier * XorAssignExp::opId() { return Id::xorass; }
Identifier * ShlAssignExp::opId() { return Id::shlass; }
Identifier * ShrAssignExp::opId() { return Id::shrass; }
Identifier *UshrAssignExp::opId() { return Id::ushrass; }
Identifier * CatAssignExp::opId() { return Id::catass; }
int EqualExp::isCommutative() { return TRUE; }
Identifier *EqualExp::opId() { return Id::eq; }
int CmpExp::isCommutative() { return TRUE; }
Identifier *CmpExp::opId() { return Id::cmp; }
Identifier *ArrayExp::opId() { return Id::index; }
/************************************
* Operator overload.
* Check for operator overload, if so, replace
* with function call.
* Return NULL if not an operator overload.
*/
Expression *UnaExp::op_overload(Scope *sc)
{
AggregateDeclaration *ad;
Dsymbol *fd;
Type *t1 = e1->type->toBasetype();
if (t1->ty == Tclass)
{
ad = ((TypeClass *)t1)->sym;
goto L1;
}
else if (t1->ty == Tstruct)
{
ad = ((TypeStruct *)t1)->sym;
L1:
fd = search_function(ad, opId());
if (fd)
{
if (op == TOKarray)
{
Expression *e;
ArrayExp *ae = (ArrayExp *)this;
e = new DotIdExp(loc, e1, fd->ident);
e = new CallExp(loc, e, ae->arguments);
e = e->semantic(sc);
return e;
}
else
{
// Rewrite +e1 as e1.add()
return build_overload(loc, sc, e1, NULL, fd->ident);
}
}
}
return NULL;
}
Expression *BinExp::op_overload(Scope *sc)
{
//printf("BinExp::op_overload() (%s)\n", toChars());
AggregateDeclaration *ad;
Type *t1 = e1->type->toBasetype();
Type *t2 = e2->type->toBasetype();
Identifier *id = opId();
Identifier *id_r = opId_r();
Match m;
Expressions args1;
Expressions args2;
int argsset = 0;
AggregateDeclaration *ad1;
if (t1->ty == Tclass)
ad1 = ((TypeClass *)t1)->sym;
else if (t1->ty == Tstruct)
ad1 = ((TypeStruct *)t1)->sym;
else
ad1 = NULL;
AggregateDeclaration *ad2;
if (t2->ty == Tclass)
ad2 = ((TypeClass *)t2)->sym;
else if (t2->ty == Tstruct)
ad2 = ((TypeStruct *)t2)->sym;
else
ad2 = NULL;
Dsymbol *s = NULL;
Dsymbol *s_r = NULL;
FuncDeclaration *fd = NULL;
TemplateDeclaration *td = NULL;
if (ad1 && id)
{
s = search_function(ad1, id);
}
if (ad2 && id_r)
{
s_r = search_function(ad2, id_r);
}
if (s || s_r)
{
/* Try:
* a.opfunc(b)
* b.opfunc_r(a)
* and see which is better.
*/
Expression *e;
FuncDeclaration *lastf;
args1.setDim(1);
args1.data[0] = (void*) e1;
args2.setDim(1);
args2.data[0] = (void*) e2;
argsset = 1;
memset(&m, 0, sizeof(m));
m.last = MATCHnomatch;
if (s)
{
fd = s->isFuncDeclaration();
if (fd)
{
overloadResolveX(&m, fd, &args2);
}
else
{ td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, NULL, &args2);
}
}
lastf = m.lastf;
if (s_r)
{
fd = s_r->isFuncDeclaration();
if (fd)
{
overloadResolveX(&m, fd, &args1);
}
else
{ td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, NULL, &args1);
}
}
if (m.count > 1)
{
// Error, ambiguous
error("overloads %s and %s both match argument list for %s",
m.lastf->type->toChars(),
m.nextf->type->toChars(),
m.lastf->toChars());
}
else if (m.last == MATCHnomatch)
{
m.lastf = m.anyf;
}
if (op == TOKplusplus || op == TOKminusminus)
// Kludge because operator overloading regards e++ and e--
// as unary, but it's implemented as a binary.
// Rewrite (e1 ++ e2) as e1.postinc()
// Rewrite (e1 -- e2) as e1.postdec()
e = build_overload(loc, sc, e1, NULL, id);
else if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
// Rewrite (e1 op e2) as e1.opfunc(e2)
e = build_overload(loc, sc, e1, e2, id);
else
// Rewrite (e1 op e2) as e2.opfunc_r(e1)
e = build_overload(loc, sc, e2, e1, id_r);
return e;
}
if (isCommutative())
{
s = NULL;
s_r = NULL;
if (ad1 && id_r)
{
s_r = search_function(ad1, id_r);
}
if (ad2 && id)
{
s = search_function(ad2, id);
}
if (s || s_r)
{
/* Try:
* a.opfunc_r(b)
* b.opfunc(a)
* and see which is better.
*/
Expression *e;
FuncDeclaration *lastf;
if (!argsset)
{ args1.setDim(1);
args1.data[0] = (void*) e1;
args2.setDim(1);
args2.data[0] = (void*) e2;
}
memset(&m, 0, sizeof(m));
m.last = MATCHnomatch;
if (s_r)
{
fd = s_r->isFuncDeclaration();
if (fd)
{
overloadResolveX(&m, fd, &args2);
}
else
{ td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, NULL, &args2);
}
}
lastf = m.lastf;
if (s)
{
fd = s->isFuncDeclaration();
if (fd)
{
overloadResolveX(&m, fd, &args1);
}
else
{ td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, NULL, &args1);
}
}
if (m.count > 1)
{
// Error, ambiguous
error("overloads %s and %s both match argument list for %s",
m.lastf->type->toChars(),
m.nextf->type->toChars(),
m.lastf->toChars());
}
else if (m.last == MATCHnomatch)
{
m.lastf = m.anyf;
}
if (lastf && m.lastf == lastf ||
id_r && m.last == MATCHnomatch)
// Rewrite (e1 op e2) as e1.opfunc_r(e2)
e = build_overload(loc, sc, e1, e2, id_r);
else
// Rewrite (e1 op e2) as e2.opfunc(e1)
e = build_overload(loc, sc, e2, e1, id);
// When reversing operands of comparison operators,
// need to reverse the sense of the op
switch (op)
{
case TOKlt: op = TOKgt; break;
case TOKgt: op = TOKlt; break;
case TOKle: op = TOKge; break;
case TOKge: op = TOKle; break;
// Floating point compares
case TOKule: op = TOKuge; break;
case TOKul: op = TOKug; break;
case TOKuge: op = TOKule; break;
case TOKug: op = TOKul; break;
// These are symmetric
case TOKunord:
case TOKlg:
case TOKleg:
case TOKue:
break;
}
return e;
}
}
return NULL;
}
/***********************************
* Utility to build a function call out of this reference and argument.
*/
static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
{
Expression *e;
//printf("build_overload(id = '%s')\n", id->toChars());
//earg->print();
//earg->type->print();
e = new DotIdExp(loc, ethis, id);
if (earg)
e = new CallExp(loc, e, earg);
else
e = new CallExp(loc, e);
e = e->semantic(sc);
return e;
}
/***************************************
* Search for function funcid in aggregate ad.
*/
Dsymbol *search_function(AggregateDeclaration *ad, Identifier *funcid)
{
Dsymbol *s;
FuncDeclaration *fd;
TemplateDeclaration *td;
s = ad->search(0, funcid, 0);
if (s)
{ Dsymbol *s2;
//printf("search_function: s = '%s'\n", s->kind());
s2 = s->toAlias();
//printf("search_function: s2 = '%s'\n", s2->kind());
fd = s2->isFuncDeclaration();
if (fd && fd->type->ty == Tfunction)
return fd;
td = s2->isTemplateDeclaration();
if (td)
return td;
}
return NULL;
}
/*****************************************
* Given array of arguments and an aggregate type,
* if any of the argument types are missing, attempt to infer
* them from the aggregate type.
*/
void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr)
{
if (!arguments || !arguments->dim)
return;
/* Return if no arguments need types.
*/
for (size_t u = 0; 1; u++)
{ if (u == arguments->dim)
return;
Argument *arg = (Argument *)arguments->data[u];
if (!arg->type)
break;
}
AggregateDeclaration *ad;
FuncDeclaration *fd;
Argument *arg = (Argument *)arguments->data[0];
Type *taggr = aggr->type;
if (!taggr)
return;
Type *tab = taggr->toBasetype();
switch (tab->ty)
{
case Tarray:
case Tsarray:
case Ttuple:
if (arguments->dim == 2)
{
if (!arg->type)
arg->type = Type::tsize_t; // key type
arg = (Argument *)arguments->data[1];
}
if (!arg->type && tab->ty != Ttuple)
arg->type = tab->nextOf(); // value type
break;
case Taarray:
{ TypeAArray *taa = (TypeAArray *)tab;
if (arguments->dim == 2)
{
if (!arg->type)
arg->type = taa->index; // key type
arg = (Argument *)arguments->data[1];
}
if (!arg->type)
arg->type = taa->next; // value type
break;
}
case Tclass:
ad = ((TypeClass *)tab)->sym;
goto Laggr;
case Tstruct:
ad = ((TypeStruct *)tab)->sym;
goto Laggr;
Laggr:
#if 0
if (arguments->dim == 1)
{
if (!arg->type)
{
/* Look for an opNext() overload
*/
Dsymbol *s = search_function(ad, Id::next);
fd = s ? s->isFuncDeclaration() : NULL;
if (!fd)
goto Lapply;
arg->type = fd->type->next;
}
break;
}
#endif
Lapply:
{ /* Look for an
* int opApply(int delegate(ref Type [, ...]) dg);
* overload
*/
Dsymbol *s = search_function(ad,
(op == TOKforeach_reverse) ? Id::applyReverse
: Id::apply);
if (s)
{
fd = s->isFuncDeclaration();
if (fd)
inferApplyArgTypesX(fd, arguments);
}
break;
}
case Tdelegate:
{
if (0 && aggr->op == TOKdelegate)
{ DelegateExp *de = (DelegateExp *)aggr;
fd = de->func->isFuncDeclaration();
if (fd)
inferApplyArgTypesX(fd, arguments);
}
else
{
inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments);
}
break;
}
default:
break; // ignore error, caught later
}
}
/********************************
* Recursive helper function,
* analogous to func.overloadResolveX().
*/
int fp3(void *param, FuncDeclaration *f)
{
Arguments *arguments = (Arguments *)param;
TypeFunction *tf = (TypeFunction *)f->type;
if (inferApplyArgTypesY(tf, arguments) == 1)
return 0;
if (arguments->dim == 0)
return 1;
return 0;
}
static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
{
overloadApply(fstart, &fp3, arguments);
}
#if 0
static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
{
Declaration *d;
Declaration *next;
for (d = fstart; d; d = next)
{
FuncDeclaration *f;
FuncAliasDeclaration *fa;
AliasDeclaration *a;
fa = d->isFuncAliasDeclaration();
if (fa)
{
inferApplyArgTypesX(fa->funcalias, arguments);
next = fa->overnext;
}
else if ((f = d->isFuncDeclaration()) != NULL)
{
next = f->overnext;
TypeFunction *tf = (TypeFunction *)f->type;
if (inferApplyArgTypesY(tf, arguments) == 1)
continue;
if (arguments->dim == 0)
return;
}
else if ((a = d->isAliasDeclaration()) != NULL)
{
Dsymbol *s = a->toAlias();
next = s->isDeclaration();
if (next == a)
break;
if (next == fstart)
break;
}
else
{ d->error("is aliased to a function");
break;
}
}
}
#endif
/******************************
* Infer arguments from type of function.
* Returns:
* 0 match for this function
* 1 no match for this function
*/
static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments)
{ size_t nparams;
Argument *p;
if (Argument::dim(tf->parameters) != 1)
goto Lnomatch;
p = Argument::getNth(tf->parameters, 0);
if (p->type->ty != Tdelegate)
goto Lnomatch;
tf = (TypeFunction *)p->type->nextOf();
assert(tf->ty == Tfunction);
/* We now have tf, the type of the delegate. Match it against
* the arguments, filling in missing argument types.
*/
nparams = Argument::dim(tf->parameters);
if (nparams == 0 || tf->varargs)
goto Lnomatch; // not enough parameters
if (arguments->dim != nparams)
goto Lnomatch; // not enough parameters
for (size_t u = 0; u < nparams; u++)
{
Argument *arg = (Argument *)arguments->data[u];
Argument *param = Argument::getNth(tf->parameters, u);
if (arg->type)
{ if (!arg->type->equals(param->type))
{
/* Cannot resolve argument types. Indicate an
* error by setting the number of arguments to 0.
*/
arguments->dim = 0;
goto Lmatch;
}
continue;
}
arg->type = param->type;
}
Lmatch:
return 0;
Lnomatch:
return 1;
}
/**************************************
*/
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments)
{
FuncDeclaration *fd;
assert(td);
fd = td->deduce(sc, loc, targsi, arguments);
if (!fd)
return;
m->anyf = fd;
if (m->last >= MATCHexact)
{
m->nextf = fd;
m->count++;
}
else
{
m->last = MATCHexact;
m->lastf = fd;
m->count = 1;
}
}

750
dmd/optimize.c Normal file
View File

@@ -0,0 +1,750 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <math.h>
#if __DMC__
#include <complex.h>
#endif
#include "lexer.h"
#include "mtype.h"
#include "expression.h"
#include "declaration.h"
#include "aggregate.h"
#include "init.h"
#ifdef IN_GCC
#include "d-gcc-real.h"
/* %% fix? */
extern "C" bool real_isnan (const real_t *);
#endif
static real_t zero; // work around DMC bug for now
/*************************************
* If expression is a variable with a const initializer,
* return that initializer.
*/
Expression *fromConstInitializer(Expression *e1)
{
//printf("fromConstInitializer(%s)\n", e1->toChars());
if (e1->op == TOKvar)
{ VarExp *ve = (VarExp *)e1;
VarDeclaration *v = ve->var->isVarDeclaration();
if (v && v->isConst() && v->init)
{ Expression *ei = v->init->toExpression();
if (ei && ei->type)
e1 = ei;
}
}
return e1;
}
Expression *Expression::optimize(int result)
{
//printf("Expression::optimize(result = x%x) %s\n", result, toChars());
return this;
}
Expression *VarExp::optimize(int result)
{
if (result & WANTinterpret)
{
return fromConstInitializer(this);
}
return this;
}
Expression *TupleExp::optimize(int result)
{
for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)exps->data[i];
e = e->optimize(WANTvalue | (result & WANTinterpret));
exps->data[i] = (void *)e;
}
return this;
}
Expression *ArrayLiteralExp::optimize(int result)
{
if (elements)
{
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (Expression *)elements->data[i];
e = e->optimize(WANTvalue | (result & WANTinterpret));
elements->data[i] = (void *)e;
}
}
return this;
}
Expression *AssocArrayLiteralExp::optimize(int result)
{
assert(keys->dim == values->dim);
for (size_t i = 0; i < keys->dim; i++)
{ Expression *e = (Expression *)keys->data[i];
e = e->optimize(WANTvalue | (result & WANTinterpret));
keys->data[i] = (void *)e;
e = (Expression *)values->data[i];
e = e->optimize(WANTvalue | (result & WANTinterpret));
values->data[i] = (void *)e;
}
return this;
}
Expression *StructLiteralExp::optimize(int result)
{
if (elements)
{
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (Expression *)elements->data[i];
if (!e)
continue;
e = e->optimize(WANTvalue | (result & WANTinterpret));
elements->data[i] = (void *)e;
}
}
return this;
}
Expression *TypeExp::optimize(int result)
{
return this;
}
Expression *UnaExp::optimize(int result)
{
e1 = e1->optimize(result);
return this;
}
Expression *NegExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
if (e1->isConst() == 1)
{
e = Neg(type, e1);
}
else
e = this;
return e;
}
Expression *ComExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
if (e1->isConst() == 1)
{
e = Com(type, e1);
}
else
e = this;
return e;
}
Expression *NotExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
if (e1->isConst() == 1)
{
e = Not(type, e1);
}
else
e = this;
return e;
}
Expression *BoolExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
if (e1->isConst() == 1)
{
e = Bool(type, e1);
}
else
e = this;
return e;
}
Expression *AddrExp::optimize(int result)
{ Expression *e;
//printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
e1 = e1->optimize(result);
// Convert &*ex to ex
if (e1->op == TOKstar)
{ Expression *ex;
ex = ((PtrExp *)e1)->e1;
if (type->equals(ex->type))
e = ex;
else
{
e = ex->copy();
e->type = type;
}
return e;
}
if (e1->op == TOKvar)
{ VarExp *ve = (VarExp *)e1;
if (!ve->var->isOut() && !ve->var->isRef() &&
!ve->var->isImportedSymbol())
{
e = new SymOffExp(loc, ve->var, 0);
e->type = type;
return e;
}
}
if (e1->op == TOKindex)
{ // Convert &array[n] to &array+n
IndexExp *ae = (IndexExp *)e1;
if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
{
integer_t index = ae->e2->toInteger();
VarExp *ve = (VarExp *)ae->e1;
if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit
&& !ve->var->isImportedSymbol())
{
TypeSArray *ts = (TypeSArray *)ve->type;
integer_t dim = ts->dim->toInteger();
if (index < 0 || index >= dim)
error("array index %jd is out of bounds [0..%jd]", index, dim);
e = new SymOffExp(loc, ve->var, index * ts->next->size());
e->type = type;
return e;
}
}
}
return this;
}
Expression *PtrExp::optimize(int result)
{
//printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
e1 = e1->optimize(result);
// Convert *&ex to ex
if (e1->op == TOKaddress)
{ Expression *e;
Expression *ex;
ex = ((AddrExp *)e1)->e1;
if (type->equals(ex->type))
e = ex;
else
{
e = ex->copy();
e->type = type;
}
return e;
}
// Constant fold *(&structliteral + offset)
if (e1->op == TOKadd)
{
Expression *e;
e = Ptr(type, e1);
if (e != EXP_CANT_INTERPRET)
return e;
}
return this;
}
Expression *CallExp::optimize(int result)
{ Expression *e = this;
e1 = e1->optimize(result);
if (e1->op == TOKvar && result & WANTinterpret)
{
FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
if (fd)
{
Expression *eresult = fd->interpret(NULL, arguments);
if (eresult)
e = eresult;
else if (result & WANTinterpret)
error("cannot evaluate %s at compile time", toChars());
}
}
return e;
}
Expression *CastExp::optimize(int result)
{
//printf("CastExp::optimize(result = %d) %s\n", result, toChars());
//printf("from %s to %s\n", type->toChars(), to->toChars());
//printf("from %s\n", type->toChars());
//printf("type = %p\n", type);
assert(type);
enum TOK op1 = e1->op;
e1 = e1->optimize(result);
if (result & WANTinterpret)
e1 = fromConstInitializer(e1);
if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
(type->ty == Tpointer || type->ty == Tarray) &&
type->next->equals(e1->type->next)
)
{
e1->type = type;
return e1;
}
/* The first test here is to prevent infinite loops
*/
if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
return e1->castTo(NULL, to);
if (e1->op == TOKnull &&
(type->ty == Tpointer || type->ty == Tclass))
{
e1->type = type;
return e1;
}
if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
{
// See if we can remove an unnecessary cast
ClassDeclaration *cdfrom;
ClassDeclaration *cdto;
int offset;
cdfrom = e1->type->isClassHandle();
cdto = type->isClassHandle();
if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
{
e1->type = type;
return e1;
}
}
Expression *e;
if (e1->isConst())
{
if (e1->op == TOKsymoff)
{
if (type->size() == e1->type->size() &&
type->toBasetype()->ty != Tsarray)
{
e1->type = type;
return e1;
}
return this;
}
if (to->toBasetype()->ty == Tvoid)
e = this;
else
e = Cast(type, to, e1);
}
else
e = this;
return e;
}
Expression *BinExp::optimize(int result)
{
//printf("BinExp::optimize(result = %d) %s\n", result, toChars());
e1 = e1->optimize(result);
e2 = e2->optimize(result);
return this;
}
Expression *AddExp::optimize(int result)
{ Expression *e;
//printf("AddExp::optimize(%s)\n", toChars());
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() && e2->isConst())
{
if (e1->op == TOKsymoff && e2->op == TOKsymoff)
return this;
e = Add(type, e1, e2);
}
else
e = this;
return e;
}
Expression *MinExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() && e2->isConst())
{
if (e2->op == TOKsymoff)
return this;
e = Min(type, e1, e2);
}
else
e = this;
return e;
}
Expression *MulExp::optimize(int result)
{ Expression *e;
//printf("MulExp::optimize(result = %d) %s\n", result, toChars());
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
{
e = Mul(type, e1, e2);
}
else
e = this;
return e;
}
Expression *DivExp::optimize(int result)
{ Expression *e;
//printf("DivExp::optimize(%s)\n", toChars());
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
{
e = Div(type, e1, e2);
}
else
e = this;
return e;
}
Expression *ModExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
{
e = Mod(type, e1, e2);
}
else
e = this;
return e;
}
Expression *ShlExp::optimize(int result)
{ Expression *e;
//printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
e1 = e1->optimize(result);
e2 = e2->optimize(result);
e = this;
if (e2->isConst() == 1)
{
integer_t i2 = e2->toInteger();
if (i2 < 0 || i2 > e1->type->size() * 8)
{ error("shift left by %jd exceeds %zu", i2, e2->type->size() * 8);
e2 = new IntegerExp(0);
}
if (e1->isConst() == 1)
e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type);
}
return e;
}
Expression *ShrExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
{
e = Shr(type, e1, e2);
}
else
e = this;
return e;
}
Expression *UshrExp::optimize(int result)
{ Expression *e;
//printf("UshrExp::optimize() %s\n", toChars());
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
{
e = Ushr(type, e1, e2);
}
else
e = this;
return e;
}
Expression *AndExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
e = And(type, e1, e2);
else
e = this;
return e;
}
Expression *OrExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
e = Or(type, e1, e2);
else
e = this;
return e;
}
Expression *XorExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
e = Xor(type, e1, e2);
else
e = this;
return e;
}
Expression *CommaExp::optimize(int result)
{ Expression *e;
//printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
e1 = e1->optimize(result & WANTinterpret);
e2 = e2->optimize(result);
if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
{
e = e2;
if (e)
e->type = type;
}
else
e = this;
//printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
return e;
}
Expression *ArrayLengthExp::optimize(int result)
{ Expression *e;
//printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
e = this;
if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
{
e = ArrayLength(type, e1);
}
return e;
}
Expression *EqualExp::optimize(int result)
{ Expression *e;
//printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
e = this;
Expression *e1 = fromConstInitializer(this->e1);
Expression *e2 = fromConstInitializer(this->e2);
e = Equal(op, type, e1, e2);
if (e == EXP_CANT_INTERPRET)
e = this;
return e;
}
Expression *IdentityExp::optimize(int result)
{ Expression *e;
//printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
e = this;
if (this->e1->isConst() && this->e2->isConst())
{
e = Identity(op, type, this->e1, this->e2);
}
return e;
}
Expression *IndexExp::optimize(int result)
{ Expression *e;
//printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
if (result & WANTinterpret)
e1 = fromConstInitializer(e1);
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
e = Index(type, e1, e2);
if (e == EXP_CANT_INTERPRET)
e = this;
return e;
}
Expression *SliceExp::optimize(int result)
{ Expression *e;
//printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
e = this;
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
if (!lwr)
{ if (e1->op == TOKstring)
{ // Convert slice of string literal into dynamic array
Type *t = e1->type->toBasetype();
if (t->next)
e = e1->castTo(NULL, t->next->arrayOf());
}
return e;
}
if (result & WANTinterpret)
e1 = fromConstInitializer(e1);
lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
upr = upr->optimize(WANTvalue | (result & WANTinterpret));
e = Slice(type, e1, lwr, upr);
if (e == EXP_CANT_INTERPRET)
e = this;
return e;
}
Expression *AndAndExp::optimize(int result)
{ Expression *e;
//printf("AndAndExp::optimize(%d) %s\n", result, toChars());
e1 = e1->optimize(WANTflags | (result & WANTinterpret));
e = this;
if (e1->isBool(FALSE))
{
e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
e->type = type;
e = e->optimize(result);
}
else
{
e2 = e2->optimize(WANTflags | (result & WANTinterpret));
if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
error("void has no value");
if (e1->isConst())
{
if (e2->isConst())
{ int n1 = e1->isBool(1);
int n2 = e2->isBool(1);
e = new IntegerExp(loc, n1 && n2, type);
}
else if (e1->isBool(TRUE))
e = new BoolExp(loc, e2, type);
}
}
return e;
}
Expression *OrOrExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(WANTflags | (result & WANTinterpret));
e = this;
if (e1->isBool(TRUE))
{ // Replace with (e1, 1)
e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
e->type = type;
e = e->optimize(result);
}
else
{
e2 = e2->optimize(WANTflags | (result & WANTinterpret));
if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
error("void has no value");
if (e1->isConst())
{
if (e2->isConst())
{ int n1 = e1->isBool(1);
int n2 = e2->isBool(1);
e = new IntegerExp(loc, n1 || n2, type);
}
else if (e1->isBool(FALSE))
e = new BoolExp(loc, e2, type);
}
}
return e;
}
Expression *CmpExp::optimize(int result)
{ Expression *e;
//printf("CmpExp::optimize() %s\n", toChars());
e1 = e1->optimize(result);
e2 = e2->optimize(result);
if (e1->isConst() == 1 && e2->isConst() == 1)
{
e = Cmp(op, type, this->e1, this->e2);
}
else
e = this;
return e;
}
Expression *CatExp::optimize(int result)
{ Expression *e;
//printf("CatExp::optimize(%d) %s\n", result, toChars());
e1 = e1->optimize(result);
e2 = e2->optimize(result);
e = Cat(type, e1, e2);
if (e == EXP_CANT_INTERPRET)
e = this;
return e;
}
Expression *CondExp::optimize(int result)
{ Expression *e;
econd = econd->optimize(WANTflags | (result & WANTinterpret));
if (econd->isBool(TRUE))
e = e1->optimize(result);
else if (econd->isBool(FALSE))
e = e2->optimize(result);
else
{ e1 = e1->optimize(result);
e2 = e2->optimize(result);
e = this;
}
return e;
}

4907
dmd/parse.c Normal file

File diff suppressed because it is too large Load Diff

135
dmd/parse.h Normal file
View File

@@ -0,0 +1,135 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_PARSE_H
#define DMD_PARSE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "arraytypes.h"
#include "lexer.h"
#include "enum.h"
struct Type;
struct Expression;
struct Declaration;
struct Statement;
struct Import;
struct Initializer;
struct FuncDeclaration;
struct CtorDeclaration;
struct DtorDeclaration;
struct StaticCtorDeclaration;
struct StaticDtorDeclaration;
struct ConditionalDeclaration;
struct InvariantDeclaration;
struct UnitTestDeclaration;
struct NewDeclaration;
struct DeleteDeclaration;
struct Condition;
struct Module;
struct ModuleDeclaration;
struct TemplateDeclaration;
struct TemplateInstance;
struct StaticAssert;
/************************************
* These control how parseStatement() works.
*/
enum ParseStatementFlags
{
PSsemi = 1, // empty ';' statements are allowed
PSscope = 2, // start a new scope
PScurly = 4, // { } statement is required
PScurlyscope = 8, // { } starts a new scope
};
struct Parser : Lexer
{
ModuleDeclaration *md;
enum LINK linkage;
Loc endloc; // set to location of last right curly
int inBrackets; // inside [] of array index or slice
Parser(Module *module, unsigned char *base, unsigned length, int doDocComment);
Array *parseModule();
Array *parseDeclDefs(int once);
Array *parseBlock();
TemplateDeclaration *parseTemplateDeclaration();
TemplateParameters *parseTemplateParameterList();
Dsymbol *parseMixin();
Objects *parseTemplateArgumentList();
StaticAssert *parseStaticAssert();
enum LINK parseLinkage();
Condition *parseDebugCondition();
Condition *parseVersionCondition();
Condition *parseStaticIfCondition();
CtorDeclaration *parseCtor();
DtorDeclaration *parseDtor();
StaticCtorDeclaration *parseStaticCtor();
StaticDtorDeclaration *parseStaticDtor();
InvariantDeclaration *parseInvariant();
UnitTestDeclaration *parseUnitTest();
NewDeclaration *parseNew();
DeleteDeclaration *parseDelete();
Arguments *parseParameters(int *pvarargs);
EnumDeclaration *parseEnum();
Dsymbol *parseAggregate();
BaseClasses *parseBaseClasses();
Import *parseImport(Array *decldefs, int isstatic);
Type *parseBasicType();
Type *parseBasicType2(Type *t);
Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL);
Array *parseDeclarations();
void parseContracts(FuncDeclaration *f);
Statement *parseStatement(int flags);
Initializer *parseInitializer();
void check(Loc loc, enum TOK value);
void check(enum TOK value);
void check(enum TOK value, char *string);
int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt);
int isBasicType(Token **pt);
int isDeclarator(Token **pt, int *haveId, enum TOK endtok);
int isParameters(Token **pt);
int isExpression(Token **pt);
int isTemplateInstance(Token *t, Token **pt);
int skipParens(Token *t, Token **pt);
Expression *parseExpression();
Expression *parsePrimaryExp();
Expression *parseUnaryExp();
Expression *parsePostExp(Expression *e);
Expression *parseMulExp();
Expression *parseAddExp();
Expression *parseShiftExp();
Expression *parseRelExp();
Expression *parseEqualExp();
Expression *parseCmpExp();
Expression *parseAndExp();
Expression *parseXorExp();
Expression *parseOrExp();
Expression *parseAndAndExp();
Expression *parseOrOrExp();
Expression *parseCondExp();
Expression *parseAssignExp();
Expressions *parseArguments();
Expression *parseNewExp(Expression *thisexp);
void addComment(Dsymbol *s, unsigned char *blockComment);
};
#endif /* DMD_PARSE_H */

65
dmd/port.h Normal file
View File

@@ -0,0 +1,65 @@
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
#ifndef PORT_H
#define PORT_H
// Portable wrapper around compiler/system specific things.
// The idea is to minimize #ifdef's in the app code.
#ifndef TYPEDEFS
#define TYPEDEFS
#include <wchar.h>
#if _MSC_VER
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
typedef double d_time;
struct Port
{
static double nan;
static double infinity;
static double dbl_max;
static double dbl_min;
#if __GNUC__
// These conflict with macros in math.h, should rename them
#undef isnan
#undef isfinite
#undef isinfinity
#undef signbit
#endif
static int isNan(double);
static int isFinite(double);
static int isInfinity(double);
static int Signbit(double);
static double floor(double);
static double pow(double x, double y);
static ulonglong strtoull(const char *p, char **pend, int base);
static char *ull_to_string(char *buffer, ulonglong ull);
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
// Convert ulonglong to double
static double ull_to_double(ulonglong ull);
// Get locale-dependent list separator
static char *list_separator();
static wchar_t *wlist_separator();
};
#endif

27
dmd/readme.txt Normal file
View File

@@ -0,0 +1,27 @@
The D Programming Language
Compiler Front End Source
Copyright (c) 1999-2002, by Digital Mars
www.digitalmars.com
All Rights Reserved
This is the source code to the front end Digital Mars D compiler.
It covers the lexical analysis, parsing, and semantic analysis
of the D Programming Language defined in the documents at
www.digitalmars.com/d/
The optimizer, code generator, and object file generator are not part
of this source, hence the source does not currently constitute a complete,
compilable program. However, many people have expressed a strong interested
in producing a D compiler with the GNU compiler sources. This release should
enable that.
These sources are free, they are redistributable and modifiable
under the terms of the GNU General Public License (attached as gpl.txt),
or the Artistic License (attached as artistic.txt).
It does not apply to anything else distributed by Digital Mars,
including D compiler executables.
-Walter Bright

1835
dmd/root.c Normal file

File diff suppressed because it is too large Load Diff

349
dmd/root.h Normal file
View File

@@ -0,0 +1,349 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef ROOT_H
#define ROOT_H
#include <stdlib.h>
#include <stdarg.h>
#if __DMC__
#pragma once
#endif
typedef size_t hash_t;
#include "dchar.h"
char *wchar2ascii(wchar_t *);
int wcharIsAscii(wchar_t *);
char *wchar2ascii(wchar_t *, unsigned len);
int wcharIsAscii(wchar_t *, unsigned len);
int bstrcmp(unsigned char *s1, unsigned char *s2);
char *bstr2str(unsigned char *b);
void error(const char *format, ...);
void error(const wchar_t *format, ...);
void warning(const char *format, ...);
#ifndef TYPEDEFS
#define TYPEDEFS
#if _MSC_VER
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
longlong randomx();
/*
* Root of our class library.
*/
struct OutBuffer;
struct Array;
struct Object
{
Object() { }
virtual ~Object() { }
virtual int equals(Object *o);
/**
* Returns a hash code, useful for things like building hash tables of Objects.
*/
virtual hash_t hashCode();
/**
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
* Useful for sorting Objects.
*/
virtual int compare(Object *obj);
/**
* Pretty-print an Object. Useful for debugging the old-fashioned way.
*/
virtual void print();
virtual char *toChars();
virtual dchar *toDchars();
virtual void toBuffer(OutBuffer *buf);
/**
* Used as a replacement for dynamic_cast. Returns a unique number
* defined by the library user. For Object, the return value is 0.
*/
virtual int dyncast();
/**
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
*/
/*virtual*/ // not used, disable for now
void mark();
};
struct String : Object
{
int ref; // != 0 if this is a reference to someone else's string
char *str; // the string itself
String(char *str, int ref = 1);
~String();
static hash_t calcHash(const char *str, size_t len);
static hash_t calcHash(const char *str);
hash_t hashCode();
unsigned len();
int equals(Object *obj);
int compare(Object *obj);
char *toChars();
void print();
void mark();
};
struct FileName : String
{
FileName(char *str, int ref);
FileName(char *path, char *name);
hash_t hashCode();
int equals(Object *obj);
int compare(Object *obj);
static int absolute(const char *name);
static char *ext(const char *);
char *ext();
static char *name(const char *);
char *name();
static char *path(const char *);
static char *replaceName(char *path, char *name);
static char *combine(char *path, char *name);
static Array *splitPath(const char *path);
static FileName *defaultExt(const char *name, const char *ext);
static FileName *forceExt(const char *name, const char *ext);
int equalsExt(const char *ext);
void CopyTo(FileName *to);
static char *searchPath(Array *path, char *name, int cwd);
static int exists(const char *name);
static void ensurePathExists(const char *path);
};
struct File : Object
{
int ref; // != 0 if this is a reference to someone else's buffer
unsigned char *buffer; // data for our file
unsigned len; // amount of data in buffer[]
void *touchtime; // system time to use for file
FileName *name; // name of our file
File(char *);
File(FileName *);
~File();
void mark();
char *toChars();
/* Read file, return !=0 if error
*/
int read();
/* Write file, either succeed or fail
* with error message & exit.
*/
void readv();
/* Read file, return !=0 if error
*/
int mmread();
/* Write file, either succeed or fail
* with error message & exit.
*/
void mmreadv();
/* Write file, return !=0 if error
*/
int write();
/* Write file, either succeed or fail
* with error message & exit.
*/
void writev();
/* Return !=0 if file exists.
* 0: file doesn't exist
* 1: normal file
* 2: directory
*/
/* Append to file, return !=0 if error
*/
int append();
/* Append to file, either succeed or fail
* with error message & exit.
*/
void appendv();
/* Return !=0 if file exists.
* 0: file doesn't exist
* 1: normal file
* 2: directory
*/
int exists();
/* Given wildcard filespec, return an array of
* matching File's.
*/
static Array *match(char *);
static Array *match(FileName *);
// Compare file times.
// Return <0 this < f
// =0 this == f
// >0 this > f
int compareTime(File *f);
// Read system file statistics
void stat();
/* Set buffer
*/
void setbuffer(void *buffer, unsigned len)
{
this->buffer = (unsigned char *)buffer;
this->len = len;
}
void checkoffset(size_t offset, size_t nbytes);
void remove(); // delete file
};
struct OutBuffer : Object
{
unsigned char *data;
unsigned offset;
unsigned size;
OutBuffer();
~OutBuffer();
void *extractData();
void mark();
void reserve(unsigned nbytes);
void setsize(unsigned size);
void reset();
void write(const void *data, unsigned nbytes);
void writebstring(unsigned char *string);
void writestring(char *string);
void writedstring(const char *string);
void writedstring(const wchar_t *string);
void prependstring(char *string);
void writenl(); // write newline
void writeByte(unsigned b);
void writebyte(unsigned b) { writeByte(b); }
void writeUTF8(unsigned b);
void writedchar(unsigned b);
void prependbyte(unsigned b);
void writeword(unsigned w);
void writeUTF16(unsigned w);
void write4(unsigned w);
void write(OutBuffer *buf);
void write(Object *obj);
void fill0(unsigned nbytes);
void align(unsigned size);
void vprintf(const char *format, va_list args);
void printf(const char *format, ...);
#if M_UNICODE
void vprintf(const unsigned short *format, va_list args);
void printf(const unsigned short *format, ...);
#endif
void bracket(char left, char right);
unsigned bracket(unsigned i, char *left, unsigned j, char *right);
void spread(unsigned offset, unsigned nbytes);
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
void remove(unsigned offset, unsigned nbytes);
char *toChars();
char *extractString();
};
struct Array : Object
{
unsigned dim;
unsigned allocdim;
void **data;
Array();
~Array();
void mark();
char *toChars();
void reserve(unsigned nentries);
void setDim(unsigned newdim);
void fixDim();
void push(void *ptr);
void *pop();
void shift(void *ptr);
void insert(unsigned index, void *ptr);
void insert(unsigned index, Array *a);
void append(Array *a);
void remove(unsigned i);
void zero();
void *tos();
void sort();
Array *copy();
};
struct Bits : Object
{
unsigned bitdim;
unsigned allocdim;
unsigned *data;
Bits();
~Bits();
void mark();
void resize(unsigned bitdim);
void set(unsigned bitnum);
void clear(unsigned bitnum);
int test(unsigned bitnum);
void set();
void clear();
void copy(Bits *from);
Bits *clone();
void sub(Bits *b);
};
#endif

357
dmd/scope.c Normal file
View File

@@ -0,0 +1,357 @@
// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "mars.h"
#include "init.h"
#include "identifier.h"
#include "attrib.h"
#include "dsymbol.h"
#include "scope.h"
#include "declaration.h"
#include "aggregate.h"
#include "module.h"
#include "id.h"
Scope *Scope::freelist = NULL;
void *Scope::operator new(size_t size)
{
if (freelist)
{
Scope *s = freelist;
freelist = s->enclosing;
//printf("freelist %p\n", s);
assert(s->flags & SCOPEfree);
s->flags &= ~SCOPEfree;
return s;
}
void *p = ::operator new(size);
//printf("new %p\n", p);
return p;
}
Scope::Scope()
{ // Create root scope
//printf("Scope::Scope() %p\n", this);
this->module = NULL;
this->scopesym = NULL;
this->sd = NULL;
this->enclosing = NULL;
this->parent = NULL;
this->sw = NULL;
this->tf = NULL;
this->sbreak = NULL;
this->scontinue = NULL;
this->fes = NULL;
this->structalign = global.structalign;
this->func = NULL;
this->slabel = NULL;
this->linkage = LINKd;
this->protection = PROTpublic;
this->explicitProtection = 0;
this->stc = 0;
this->offset = 0;
this->inunion = 0;
this->incontract = 0;
this->nofree = 0;
this->noctor = 0;
this->intypeof = 0;
this->parameterSpecialization = 0;
this->callSuper = 0;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = NULL;
}
Scope::Scope(Scope *enclosing)
{
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
assert(!(enclosing->flags & SCOPEfree));
this->module = enclosing->module;
this->func = enclosing->func;
this->parent = enclosing->parent;
this->scopesym = NULL;
this->sd = NULL;
this->sw = enclosing->sw;
this->tf = enclosing->tf;
this->sbreak = enclosing->sbreak;
this->scontinue = enclosing->scontinue;
this->fes = enclosing->fes;
this->structalign = enclosing->structalign;
this->enclosing = enclosing;
#ifdef DEBUG
if (enclosing->enclosing)
assert(!(enclosing->enclosing->flags & SCOPEfree));
if (this == enclosing->enclosing)
{
printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
}
assert(this != enclosing->enclosing);
#endif
this->slabel = NULL;
this->linkage = enclosing->linkage;
this->protection = enclosing->protection;
this->explicitProtection = enclosing->explicitProtection;
this->stc = enclosing->stc;
this->offset = 0;
this->inunion = enclosing->inunion;
this->incontract = enclosing->incontract;
this->nofree = 0;
this->noctor = enclosing->noctor;
this->intypeof = enclosing->intypeof;
this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
assert(this != enclosing);
}
Scope *Scope::createGlobal(Module *module)
{
Scope *sc;
sc = new Scope();
sc->module = module;
sc->scopesym = new ScopeDsymbol();
sc->scopesym->symtab = new DsymbolTable();
// Add top level package as member of this global scope
Dsymbol *m = module;
while (m->parent)
m = m->parent;
m->addMember(NULL, sc->scopesym, 1);
m->parent = NULL; // got changed by addMember()
// Create the module scope underneath the global scope
sc = sc->push(module);
sc->parent = module;
return sc;
}
Scope *Scope::push()
{
//printf("Scope::push()\n");
Scope *s = new Scope(this);
assert(this != s);
return s;
}
Scope *Scope::push(ScopeDsymbol *ss)
{
//printf("Scope::push(%s)\n", ss->toChars());
Scope *s = push();
s->scopesym = ss;
return s;
}
Scope *Scope::pop()
{
//printf("Scope::pop() %p nofree = %d\n", this, nofree);
Scope *enc = enclosing;
if (enclosing)
enclosing->callSuper |= callSuper;
if (!nofree)
{ enclosing = freelist;
freelist = this;
flags |= SCOPEfree;
}
return enc;
}
void Scope::mergeCallSuper(Loc loc, unsigned cs)
{
// This does a primitive flow analysis to support the restrictions
// regarding when and how constructors can appear.
// It merges the results of two paths.
// The two paths are callSuper and cs; the result is merged into callSuper.
if (cs != callSuper)
{ int a;
int b;
callSuper |= cs & (CSXany_ctor | CSXlabel);
if (cs & CSXreturn)
{
}
else if (callSuper & CSXreturn)
{
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
}
else
{
a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0;
b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
if (a != b)
error(loc, "one path skips constructor");
callSuper |= cs;
}
}
}
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
{ Dsymbol *s;
Scope *sc;
//printf("Scope::search(%p, '%s')\n", this, ident->toChars());
if (ident == Id::empty)
{
// Look for module scope
for (sc = this; sc; sc = sc->enclosing)
{
assert(sc != sc->enclosing);
if (sc->scopesym)
{
s = sc->scopesym->isModule();
if (s)
{
//printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
if (pscopesym)
*pscopesym = sc->scopesym;
return s;
}
}
}
return NULL;
}
for (sc = this; sc; sc = sc->enclosing)
{
assert(sc != sc->enclosing);
if (sc->scopesym)
{
//printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
s = sc->scopesym->search(loc, ident, 0);
if (s)
{
if ((global.params.warnings ||
global.params.Dversion > 1) &&
ident == Id::length &&
sc->scopesym->isArrayScopeSymbol() &&
sc->enclosing &&
sc->enclosing->search(loc, ident, NULL))
{
if (global.params.warnings)
fprintf(stdmsg, "warning - ");
error(s->loc, "array 'length' hides other 'length' name in outer scope");
}
//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
if (pscopesym)
*pscopesym = sc->scopesym;
return s;
}
}
}
return NULL;
}
Dsymbol *Scope::insert(Dsymbol *s)
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
//printf("\tsc = %p\n", sc);
if (sc->scopesym)
{
//printf("\t\tsc->scopesym = %p\n", sc->scopesym);
if (!sc->scopesym->symtab)
sc->scopesym->symtab = new DsymbolTable();
return sc->scopesym->symtab->insert(s);
}
}
assert(0);
return NULL;
}
/********************************************
* Search enclosing scopes for ClassDeclaration.
*/
ClassDeclaration *Scope::getClassScope()
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
ClassDeclaration *cd;
if (sc->scopesym)
{
cd = sc->scopesym->isClassDeclaration();
if (cd)
return cd;
}
}
return NULL;
}
/********************************************
* Search enclosing scopes for ClassDeclaration.
*/
AggregateDeclaration *Scope::getStructClassScope()
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
AggregateDeclaration *ad;
if (sc->scopesym)
{
ad = sc->scopesym->isClassDeclaration();
if (ad)
return ad;
else
{ ad = sc->scopesym->isStructDeclaration();
if (ad)
return ad;
}
}
}
return NULL;
}
/*******************************************
* For TemplateDeclarations, we need to remember the Scope
* where it was declared. So mark the Scope as not
* to be free'd.
*/
void Scope::setNoFree()
{ Scope *sc;
//int i = 0;
//printf("Scope::setNoFree(this = %p)\n", this);
for (sc = this; sc; sc = sc->enclosing)
{
//printf("\tsc = %p\n", sc);
sc->nofree = 1;
assert(!(flags & SCOPEfree));
//assert(sc != sc->enclosing);
//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
//if (++i == 10)
//assert(0);
}
}

109
dmd/scope.h Normal file
View File

@@ -0,0 +1,109 @@
// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_SCOPE_H
#define DMD_SCOPE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
struct Dsymbol;
struct ScopeDsymbol;
struct Array;
struct Identifier;
struct Module;
struct Statement;
struct SwitchStatement;
struct TryFinallyStatement;
struct LabelStatement;
struct ForeachStatement;
struct ClassDeclaration;
struct AggregateDeclaration;
struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
struct DocComment;
enum LINK;
enum PROT;
struct Scope
{
Scope *enclosing; // enclosing Scope
Module *module; // Root module
ScopeDsymbol *scopesym; // current symbol
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
// sd gets the addMember()
FuncDeclaration *func; // function we are in
Dsymbol *parent; // parent to use
LabelStatement *slabel; // enclosing labelled statement
SwitchStatement *sw; // enclosing switch statement
TryFinallyStatement *tf; // enclosing try finally statement
Statement *sbreak; // enclosing statement that supports "break"
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
unsigned offset; // next offset to use in aggregate
int inunion; // we're processing members of a union
int incontract; // we're inside contract code
int nofree; // set if shouldn't free it
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
int parameterSpecialization; // if in template parameter specialization
unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this()
#define CSXsuper_ctor 2 // called super()
#define CSXthis 4 // referenced this
#define CSXsuper 8 // referenced super
#define CSXlabel 0x10 // seen a label
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
unsigned structalign; // alignment for struct members
enum LINK linkage; // linkage for external functions
enum PROT protection; // protection for class members
int explicitProtection; // set if in an explicit protection attribute
unsigned stc; // storage class
unsigned flags;
#define SCOPEctor 1 // constructor type
#define SCOPEstaticif 2 // inside static if
#define SCOPEfree 4 // is on free list
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec
OutBuffer *docbuf; // buffer for documentation output
static Scope *freelist;
static void *operator new(size_t sz);
static Scope *createGlobal(Module *module);
Scope();
Scope(Module *module);
Scope(Scope *enclosing);
Scope *push();
Scope *push(ScopeDsymbol *ss);
Scope *pop();
void mergeCallSuper(Loc loc, unsigned cs);
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
Dsymbol *insert(Dsymbol *s);
ClassDeclaration *getClassScope();
AggregateDeclaration *getStructClassScope();
void setNoFree();
};
#endif /* DMD_SCOPE_H */

3564
dmd/statement.c Normal file

File diff suppressed because it is too large Load Diff

751
dmd/statement.h Normal file
View File

@@ -0,0 +1,751 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_STATEMENT_H
#define DMD_STATEMENT_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "arraytypes.h"
#include "dsymbol.h"
#include "lexer.h"
struct OutBuffer;
struct Scope;
struct Expression;
struct LabelDsymbol;
struct Identifier;
struct IfStatement;
struct DeclarationStatement;
struct DefaultStatement;
struct VarDeclaration;
struct Condition;
struct Module;
struct Token;
struct InlineCostState;
struct InlineDoState;
struct InlineScanState;
struct ReturnStatement;
struct CompoundStatement;
struct Argument;
struct StaticAssert;
struct AsmStatement;
struct GotoStatement;
struct ScopeStatement;
struct TryCatchStatement;
struct HdrGenState;
struct InterState;
enum TOK;
namespace llvm
{
class Value;
}
// Back end
struct IRState;
struct Blockx;
#if IN_GCC
union tree_node; typedef union tree_node block;
union tree_node; typedef union tree_node elem;
#else
struct block;
struct elem;
#endif
struct code;
struct Statement : Object
{
Loc loc;
Statement(Loc loc);
virtual Statement *syntaxCopy();
void print();
char *toChars();
void error(const char *format, ...);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual TryCatchStatement *isTryCatchStatement() { return NULL; }
virtual GotoStatement *isGotoStatement() { return NULL; }
virtual AsmStatement *isAsmStatement() { return NULL; }
#ifdef _DH
int incontract;
#endif
virtual ScopeStatement *isScopeStatement() { return NULL; }
virtual Statement *semantic(Scope *sc);
Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
virtual int hasBreak();
virtual int hasContinue();
virtual int usesEH();
virtual int fallOffEnd();
virtual int comeFrom();
virtual void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
virtual Statements *flatten(Scope *sc);
virtual Expression *interpret(InterState *istate);
virtual int inlineCost(InlineCostState *ics);
virtual Expression *doInline(InlineDoState *ids);
virtual Statement *inlineScan(InlineScanState *iss);
// Back end
virtual void toIR(IRState *irs);
// Avoid dynamic_cast
virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
virtual CompoundStatement *isCompoundStatement() { return NULL; }
virtual ReturnStatement *isReturnStatement() { return NULL; }
virtual IfStatement *isIfStatement() { return NULL; }
};
struct ExpStatement : Statement
{
Expression *exp;
ExpStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
int fallOffEnd();
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct CompileStatement : Statement
{
Expression *exp;
CompileStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
};
struct DeclarationStatement : ExpStatement
{
// Doing declarations as an expression, rather than a statement,
// makes inlining functions much easier.
DeclarationStatement(Loc loc, Dsymbol *s);
DeclarationStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
DeclarationStatement *isDeclarationStatement() { return this; }
};
struct CompoundStatement : Statement
{
Statements *statements;
CompoundStatement(Loc loc, Statements *s);
CompoundStatement(Loc loc, Statement *s1, Statement *s2);
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
int usesEH();
int fallOffEnd();
int comeFrom();
Statements *flatten(Scope *sc);
ReturnStatement *isReturnStatement();
Expression *interpret(InterState *istate);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
CompoundStatement *isCompoundStatement() { return this; }
};
/* The purpose of this is so that continue will go to the next
* of the statements, and break will go to the end of the statements.
*/
struct UnrolledLoopStatement : Statement
{
Statements *statements;
UnrolledLoopStatement(Loc loc, Statements *statements);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct ScopeStatement : Statement
{
Statement *statement;
ScopeStatement(Loc loc, Statement *s);
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
ScopeStatement *isScopeStatement() { return this; }
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct WhileStatement : Statement
{
Expression *condition;
Statement *body;
WhileStatement(Loc loc, Expression *c, Statement *b);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct DoStatement : Statement
{
Statement *body;
Expression *condition;
DoStatement(Loc loc, Statement *b, Expression *c);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct ForStatement : Statement
{
Statement *init;
Expression *condition;
Expression *increment;
Statement *body;
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
int hasBreak();
int hasContinue();
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct ForeachStatement : Statement
{
enum TOK op; // TOKforeach or TOKforeach_reverse
Arguments *arguments; // array of Argument*'s
Expression *aggr;
Statement *body;
VarDeclaration *key;
VarDeclaration *value;
FuncDeclaration *func; // function we're lexically in
Array cases; // put breaks, continues, gotos and returns here
Array gotos; // forward referenced goto's go here
ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct IfStatement : Statement
{
Argument *arg;
Expression *condition;
Statement *ifbody;
Statement *elsebody;
VarDeclaration *match; // for MatchExpression results
IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int usesEH();
int fallOffEnd();
IfStatement *isIfStatement() { return this; }
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct ConditionalStatement : Statement
{
Condition *condition;
Statement *ifbody;
Statement *elsebody;
ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
int usesEH();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct PragmaStatement : Statement
{
Identifier *ident;
Expressions *args; // array of Expression's
Statement *body;
PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int usesEH();
int fallOffEnd();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct StaticAssertStatement : Statement
{
StaticAssert *sa;
StaticAssertStatement(StaticAssert *sa);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct SwitchStatement : Statement
{
Expression *condition;
Statement *body;
DefaultStatement *sdefault;
Array gotoCases; // array of unresolved GotoCaseStatement's
Array *cases; // array of CaseStatement's
int hasNoDefault; // !=0 if no default statement
SwitchStatement(Loc loc, Expression *c, Statement *b);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int usesEH();
int fallOffEnd();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct CaseStatement : Statement
{
Expression *exp;
Statement *statement;
int index; // which case it is (since we sort this)
block *cblock; // back end: label for the block
CaseStatement(Loc loc, Expression *exp, Statement *s);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int compare(Object *obj);
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct DefaultStatement : Statement
{
Statement *statement;
#if IN_GCC
block *cblock; // back end: label for the block
#endif
DefaultStatement(Loc loc, Statement *s);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct GotoDefaultStatement : Statement
{
SwitchStatement *sw;
GotoDefaultStatement(Loc loc);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
int fallOffEnd();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toIR(IRState *irs);
};
struct GotoCaseStatement : Statement
{
Expression *exp; // NULL, or which case to goto
CaseStatement *cs; // case statement it resolves to
GotoCaseStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
int fallOffEnd();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toIR(IRState *irs);
};
struct SwitchErrorStatement : Statement
{
SwitchErrorStatement(Loc loc);
int fallOffEnd();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toIR(IRState *irs);
};
struct ReturnStatement : Statement
{
Expression *exp;
ReturnStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
int fallOffEnd();
Expression *interpret(InterState *istate);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
ReturnStatement *isReturnStatement() { return this; }
};
struct BreakStatement : Statement
{
Identifier *ident;
BreakStatement(Loc loc, Identifier *ident);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
int fallOffEnd();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toIR(IRState *irs);
};
struct ContinueStatement : Statement
{
Identifier *ident;
ContinueStatement(Loc loc, Identifier *ident);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
int fallOffEnd();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toIR(IRState *irs);
};
struct SynchronizedStatement : Statement
{
Expression *exp;
Statement *body;
SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
int fallOffEnd();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
// Back end
elem *esync;
SynchronizedStatement(Loc loc, elem *esync, Statement *body);
void toIR(IRState *irs);
};
struct WithStatement : Statement
{
Expression *exp;
Statement *body;
VarDeclaration *wthis;
WithStatement(Loc loc, Expression *exp, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int usesEH();
int fallOffEnd();
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct TryCatchStatement : Statement
{
Statement *body;
Array *catches;
TryCatchStatement(Loc loc, Statement *body, Array *catches);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int usesEH();
int fallOffEnd();
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
TryCatchStatement *isTryCatchStatement() { return this; }
};
struct Catch : Object
{
Loc loc;
Type *type;
Identifier *ident;
VarDeclaration *var;
Statement *handler;
Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
Catch *syntaxCopy();
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct TryFinallyStatement : Statement
{
Statement *body;
Statement *finalbody;
TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
int fallOffEnd();
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct OnScopeStatement : Statement
{
TOK tok;
Statement *statement;
OnScopeStatement(Loc loc, TOK tok, Statement *statement);
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
int usesEH();
void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
void toIR(IRState *irs);
};
struct ThrowStatement : Statement
{
Expression *exp;
ThrowStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int fallOffEnd();
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct VolatileStatement : Statement
{
Statement *statement;
VolatileStatement(Loc loc, Statement *statement);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
int fallOffEnd();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct GotoStatement : Statement
{
Identifier *ident;
LabelDsymbol *label;
TryFinallyStatement *tf;
GotoStatement(Loc loc, Identifier *ident);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int fallOffEnd();
Expression *interpret(InterState *istate);
void toIR(IRState *irs);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
GotoStatement *isGotoStatement() { return this; }
};
struct LabelStatement : Statement
{
Identifier *ident;
Statement *statement;
TryFinallyStatement *tf;
block *lblock; // back end
int isReturnLabel;
LabelStatement(Loc loc, Identifier *ident, Statement *statement);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
int usesEH();
int fallOffEnd();
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct LabelDsymbol : Dsymbol
{
LabelStatement *statement;
#if IN_GCC
unsigned asmLabelNum; // GCC-specific
#endif
LabelDsymbol(Identifier *ident);
LabelDsymbol *isLabel();
};
struct AsmStatement : Statement
{
Token *tokens;
code *asmcode;
unsigned asmalign; // alignment of this statement
unsigned refparam; // !=0 if function parameter is referenced
unsigned naked; // !=0 if function is to be naked
unsigned regs; // mask of registers modified
AsmStatement(Loc loc, Token *tokens);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int comeFrom();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual AsmStatement *isAsmStatement() { return this; }
void toIR(IRState *irs);
};
#endif /* DMD_STATEMENT_H */

109
dmd/staticassert.c Normal file
View File

@@ -0,0 +1,109 @@
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "dsymbol.h"
#include "staticassert.h"
#include "expression.h"
#include "id.h"
#include "hdrgen.h"
/********************************* AttribDeclaration ****************************/
StaticAssert::StaticAssert(Loc loc, Expression *exp, Expression *msg)
: Dsymbol(Id::empty)
{
this->loc = loc;
this->exp = exp;
this->msg = msg;
}
Dsymbol *StaticAssert::syntaxCopy(Dsymbol *s)
{
StaticAssert *sa;
assert(!s);
sa = new StaticAssert(loc, exp->syntaxCopy(), msg ? msg->syntaxCopy() : NULL);
return sa;
}
int StaticAssert::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
return 0; // we didn't add anything
}
void StaticAssert::semantic(Scope *sc)
{
}
void StaticAssert::semantic2(Scope *sc)
{
Expression *e;
e = exp->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
if (e->isBool(FALSE))
{
if (msg)
{ HdrGenState hgs;
OutBuffer buf;
msg = msg->semantic(sc);
msg = msg->optimize(WANTvalue | WANTinterpret);
hgs.console = 1;
msg->toCBuffer(&buf, &hgs);
error("%s", buf.toChars());
}
else
error("is false");
if (!global.gag)
fatal();
}
else if (!e->isBool(TRUE))
{
error("(%s) is not evaluatable at compile time", exp->toChars());
}
}
int StaticAssert::oneMember(Dsymbol **ps)
{
//printf("StaticAssert::oneMember())\n");
*ps = NULL;
return TRUE;
}
void StaticAssert::inlineScan()
{
}
void StaticAssert::toObjFile()
{
}
char *StaticAssert::kind()
{
return "static assert";
}
void StaticAssert::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring(kind());
buf->writeByte('(');
exp->toCBuffer(buf, hgs);
if (msg)
{
buf->writeByte(',');
msg->toCBuffer(buf, hgs);
}
buf->writestring(");");
buf->writenl();
}

43
dmd/staticassert.h Normal file
View File

@@ -0,0 +1,43 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_STATICASSERT_H
#define DMD_STATICASSERT_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Expression;
#ifdef _DH
struct HdrGenState;
#endif
struct StaticAssert : Dsymbol
{
Expression *exp;
Expression *msg;
StaticAssert(Loc loc, Expression *exp, Expression *msg);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void inlineScan();
int oneMember(Dsymbol **ps);
void toObjFile();
char *kind();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif

139
dmd/stringtable.c Normal file
View File

@@ -0,0 +1,139 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "root.h"
#include "mem.h"
#include "dchar.h"
#include "lstring.h"
#include "stringtable.h"
StringTable::StringTable(unsigned size)
{
table = (void **)mem.calloc(size, sizeof(void *));
tabledim = size;
count = 0;
}
StringTable::~StringTable()
{
unsigned i;
// Zero out dangling pointers to help garbage collector.
// Should zero out StringEntry's too.
for (i = 0; i < count; i++)
table[i] = NULL;
mem.free(table);
table = NULL;
}
struct StringEntry
{
StringEntry *left;
StringEntry *right;
hash_t hash;
StringValue value;
static StringEntry *alloc(const dchar *s, unsigned len);
};
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
{
StringEntry *se;
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
se->value.lstring.length = len;
se->hash = Dchar::calcHash(s,len);
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
return se;
}
void **StringTable::search(const dchar *s, unsigned len)
{
hash_t hash;
unsigned u;
int cmp;
StringEntry **se;
//printf("StringTable::search(%p,%d)\n",s,len);
hash = Dchar::calcHash(s,len);
u = hash % tabledim;
se = (StringEntry **)&table[u];
//printf("\thash = %d, u = %d\n",hash,u);
while (*se)
{
cmp = (*se)->hash - hash;
if (cmp == 0)
{
cmp = (*se)->value.lstring.len() - len;
if (cmp == 0)
{
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
if (cmp == 0)
break;
}
}
if (cmp < 0)
se = &(*se)->left;
else
se = &(*se)->right;
}
//printf("\treturn %p, %p\n",se, (*se));
return (void **)se;
}
StringValue *StringTable::lookup(const dchar *s, unsigned len)
{ StringEntry *se;
se = *(StringEntry **)search(s,len);
if (se)
return &se->value;
else
return NULL;
}
StringValue *StringTable::update(const dchar *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
pse = (StringEntry **)search(s,len);
se = *pse;
if (!se) // not in table: so create new entry
{
se = StringEntry::alloc(s, len);
*pse = se;
}
return &se->value;
}
StringValue *StringTable::insert(const dchar *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
pse = (StringEntry **)search(s,len);
se = *pse;
if (se)
return NULL; // error: already in table
else
{
se = StringEntry::alloc(s, len);
*pse = se;
}
return &se->value;
}

48
dmd/stringtable.h Normal file
View File

@@ -0,0 +1,48 @@
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef STRINGTABLE_H
#define STRINGTABLE_H
#if __SC__
#pragma once
#endif
#include "root.h"
#include "dchar.h"
#include "lstring.h"
struct StringValue
{
union
{ int intvalue;
void *ptrvalue;
dchar *string;
};
Lstring lstring;
};
struct StringTable : Object
{
void **table;
unsigned count;
unsigned tabledim;
StringTable(unsigned size = 37);
~StringTable();
StringValue *lookup(const dchar *s, unsigned len);
StringValue *insert(const dchar *s, unsigned len);
StringValue *update(const dchar *s, unsigned len);
private:
void **search(const dchar *s, unsigned len);
};
#endif

488
dmd/struct.c Normal file
View File

@@ -0,0 +1,488 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "aggregate.h"
#include "scope.h"
#include "mtype.h"
#include "declaration.h"
#include "module.h"
#include "id.h"
#include "statement.h"
/********************************* AggregateDeclaration ****************************/
AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
: ScopeDsymbol(id)
{
this->loc = loc;
storage_class = 0;
protection = PROTpublic;
type = NULL;
handle = NULL;
structsize = 0; // size of struct
alignsize = 0; // size of struct for alignment purposes
structalign = 0; // struct member alignment in effect
hasUnions = 0;
sizeok = 0; // size not determined yet
isdeprecated = 0;
inv = NULL;
aggNew = NULL;
aggDelete = NULL;
stag = NULL;
sinit = NULL;
scope = NULL;
llvmType = NULL;
llvmVtbl = NULL;
llvmInitZ = NULL;
llvmInProgress = false;
}
enum PROT AggregateDeclaration::prot()
{
return protection;
}
void AggregateDeclaration::semantic2(Scope *sc)
{
//printf("AggregateDeclaration::semantic2(%s)\n", toChars());
if (scope)
{ error("has forward references");
return;
}
if (members)
{
sc = sc->push(this);
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
s->semantic2(sc);
}
sc->pop();
}
}
void AggregateDeclaration::semantic3(Scope *sc)
{ int i;
//printf("AggregateDeclaration::semantic3(%s)\n", toChars());
if (members)
{
sc = sc->push(this);
for (i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
s->semantic3(sc);
}
sc->pop();
}
}
void AggregateDeclaration::inlineScan()
{ int i;
//printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
if (members)
{
for (i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
//printf("inline scan aggregate symbol '%s'\n", s->toChars());
s->inlineScan();
}
}
}
unsigned AggregateDeclaration::size(Loc loc)
{
//printf("AggregateDeclaration::size() = %d\n", structsize);
if (!members)
error(loc, "unknown size");
if (sizeok != 1)
{ error(loc, "no size yet for forward reference");
//*(char*)0=0;
}
return structsize;
}
Type *AggregateDeclaration::getType()
{
return type;
}
int AggregateDeclaration::isDeprecated()
{
return isdeprecated;
}
/****************************
* Do byte or word alignment as necessary.
* Align sizes of 0, as we may not know array sizes yet.
*/
void AggregateDeclaration::alignmember(unsigned salign, unsigned size, unsigned *poffset)
{
//printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
if (salign > 1)
{ int sa;
switch (size)
{ case 1:
break;
case 2:
case_2:
*poffset = (*poffset + 1) & ~1; // align to word
break;
case 3:
case 4:
if (salign == 2)
goto case_2;
*poffset = (*poffset + 3) & ~3; // align to dword
break;
default:
*poffset = (*poffset + salign - 1) & ~(salign - 1);
break;
}
}
//printf("result = %d\n",offset);
}
void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
{
unsigned memsize; // size of member
unsigned memalignsize; // size of member for alignment purposes
unsigned xalign; // alignment boundaries
//printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
// Check for forward referenced types which will fail the size() call
Type *t = v->type->toBasetype();
if (t->ty == Tstruct /*&& isStructDeclaration()*/)
{ TypeStruct *ts = (TypeStruct *)t;
if (ts->sym->sizeok != 1)
{
sizeok = 2; // cannot finish; flag as forward referenced
return;
}
}
if (t->ty == Tident)
{
sizeok = 2; // cannot finish; flag as forward referenced
return;
}
memsize = v->type->size(loc);
memalignsize = v->type->alignsize();
xalign = v->type->memalign(sc->structalign);
alignmember(xalign, memalignsize, &sc->offset);
v->offset = sc->offset;
sc->offset += memsize;
if (sc->offset > structsize)
structsize = sc->offset;
if (sc->structalign < memalignsize)
memalignsize = sc->structalign;
if (alignsize < memalignsize)
alignsize = memalignsize;
//printf("\talignsize = %d\n", alignsize);
v->storage_class |= STCfield;
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
fields.push(v);
}
/********************************* StructDeclaration ****************************/
StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
: AggregateDeclaration(loc, id)
{
zeroInit = 0; // assume false until we do semantic processing
// For forward references
type = new TypeStruct(this);
}
Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
{
StructDeclaration *sd;
if (s)
sd = (StructDeclaration *)s;
else
sd = new StructDeclaration(loc, ident);
ScopeDsymbol::syntaxCopy(sd);
return sd;
}
void StructDeclaration::semantic(Scope *sc)
{ int i;
Scope *sc2;
//printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
//static int count; if (++count == 20) *(char*)0=0;
assert(type);
if (!members) // if forward reference
return;
if (symtab)
{ if (!scope)
return; // semantic() already completed
}
else
symtab = new DsymbolTable();
Scope *scx = NULL;
if (scope)
{ sc = scope;
scx = scope; // save so we don't make redundant copies
scope = NULL;
}
parent = sc->parent;
handle = type->pointerTo();
structalign = sc->structalign;
protection = sc->protection;
assert(!isAnonymous());
if (sc->stc & STCabstract)
error("structs, unions cannot be abstract");
if (sizeok == 0) // if not already done the addMember step
{
for (i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
//printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
s->addMember(sc, this, 1);
}
}
sizeok = 0;
sc2 = sc->push(this);
sc2->stc = 0;
sc2->parent = this;
if (isUnionDeclaration())
sc2->inunion = 1;
sc2->protection = PROTpublic;
sc2->explicitProtection = 0;
int members_dim = members->dim;
for (i = 0; i < members_dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
s->semantic(sc2);
if (isUnionDeclaration())
sc2->offset = 0;
#if 0
if (sizeok == 2)
{ //printf("forward reference\n");
break;
}
#endif
}
/* The TypeInfo_Struct is expecting an opEquals and opCmp with
* a parameter that is a pointer to the struct. But if there
* isn't one, but is an opEquals or opCmp with a value, write
* another that is a shell around the value:
* int opCmp(struct *p) { return opCmp(*p); }
*/
TypeFunction *tfeqptr;
{
Arguments *arguments = new Arguments;
Argument *arg = new Argument(STCin, handle, Id::p, NULL);
arguments->push(arg);
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
}
TypeFunction *tfeq;
{
Arguments *arguments = new Arguments;
Argument *arg = new Argument(STCin, type, NULL, NULL);
arguments->push(arg);
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeq = (TypeFunction *)tfeq->semantic(0, sc);
}
Identifier *id = Id::eq;
for (int i = 0; i < 2; i++)
{
Dsymbol *s = search_function(this, id);
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{ FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
if (!fd)
{ fd = fdx->overloadExactMatch(tfeq);
if (fd)
{ // Create the thunk, fdptr
FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
Expression *e = new IdentifierExp(loc, Id::p);
e = new PtrExp(loc, e);
Expressions *args = new Expressions();
args->push(e);
e = new IdentifierExp(loc, id);
e = new CallExp(loc, e, args);
fdptr->fbody = new ReturnStatement(loc, e);
ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
assert(s);
s->members->push(fdptr);
fdptr->addMember(sc, s, 1);
fdptr->semantic(sc2);
}
}
}
id = Id::cmp;
}
sc2->pop();
if (sizeok == 2)
{ // semantic() failed because of forward references.
// Unwind what we did, and defer it for later
fields.setDim(0);
structsize = 0;
alignsize = 0;
structalign = 0;
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
//printf("\tdeferring %s\n", toChars());
return;
}
// 0 sized struct's are set to 1 byte
if (structsize == 0)
{
structsize = 1;
alignsize = 1;
}
// Round struct size up to next alignsize boundary.
// This will ensure that arrays of structs will get their internals
// aligned properly.
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
sizeok = 1;
Module::dprogress++;
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
// Determine if struct is all zeros or not
zeroInit = 1;
for (i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *vd = s->isVarDeclaration();
if (vd && !vd->isDataseg())
{
if (vd->init)
{
// Should examine init to see if it is really all 0's
zeroInit = 0;
break;
}
else
{
if (!vd->type->isZeroInit())
{
zeroInit = 0;
break;
}
}
}
}
/* Look for special member functions.
*/
inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0);
aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
if (sc->func)
{
semantic2(sc);
semantic3(sc);
}
}
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ int i;
buf->printf("%s ", kind());
if (!isAnonymous())
buf->writestring(toChars());
if (!members)
{
buf->writeByte(';');
buf->writenl();
return;
}
buf->writenl();
buf->writeByte('{');
buf->writenl();
for (i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
}
buf->writeByte('}');
buf->writenl();
}
char *StructDeclaration::kind()
{
return "struct";
}
/********************************* UnionDeclaration ****************************/
UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
: StructDeclaration(loc, id)
{
}
Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
{
UnionDeclaration *ud;
if (s)
ud = (UnionDeclaration *)s;
else
ud = new UnionDeclaration(loc, ident);
StructDeclaration::syntaxCopy(ud);
return ud;
}
char *UnionDeclaration::kind()
{
return "union";
}

3959
dmd/template.c Normal file

File diff suppressed because it is too large Load Diff

324
dmd/template.h Normal file
View File

@@ -0,0 +1,324 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_TEMPLATE_H
#define DMD_TEMPLATE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "arraytypes.h"
#include "dsymbol.h"
#include "mtype.h"
struct OutBuffer;
struct Identifier;
struct TemplateInstance;
struct TemplateParameter;
struct TemplateTypeParameter;
struct TemplateValueParameter;
struct TemplateAliasParameter;
struct TemplateTupleParameter;
struct Type;
struct TypeTypeof;
struct Scope;
struct Expression;
struct AliasDeclaration;
struct FuncDeclaration;
struct HdrGenState;
enum MATCH;
struct Tuple : Object
{
Objects objects;
int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
};
struct TemplateDeclaration : ScopeDsymbol
{
TemplateParameters *parameters; // array of TemplateParameter's
Array instances; // array of TemplateInstance's
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
TemplateDeclaration *overroot; // first in overnext list
Scope *scope;
Dsymbol *onemember; // if !=NULL then one member of this template
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, Array *decldefs);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
char *toChars();
void emitComment(Scope *sc);
// void toDocBuffer(OutBuffer *buf);
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
int leastAsSpecialized(TemplateDeclaration *td2);
MATCH deduceMatch(Objects *targsi, Expressions *fargs, Objects *dedargs);
FuncDeclaration *deduce(Scope *sc, Loc loc, Objects *targsi, Expressions *fargs);
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
TemplateDeclaration *isTemplateDeclaration() { return this; }
TemplateTupleParameter *isVariadic();
};
struct TemplateParameter
{
/* For type-parameter:
* template Foo(ident) // specType is set to NULL
* template Foo(ident : specType)
* For value-parameter:
* template Foo(valType ident) // specValue is set to NULL
* template Foo(valType ident : specValue)
* For alias-parameter:
* template Foo(alias ident)
*/
Loc loc;
Identifier *ident;
Declaration *sparam;
TemplateParameter(Loc loc, Identifier *ident);
virtual TemplateTypeParameter *isTemplateTypeParameter();
virtual TemplateValueParameter *isTemplateValueParameter();
virtual TemplateAliasParameter *isTemplateAliasParameter();
virtual TemplateTupleParameter *isTemplateTupleParameter();
virtual TemplateParameter *syntaxCopy() = 0;
virtual void declareParameter(Scope *sc) = 0;
virtual void semantic(Scope *) = 0;
virtual void print(Object *oarg, Object *oded) = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
virtual Object *specialization() = 0;
virtual Object *defaultArg(Scope *sc) = 0;
/* If TemplateParameter's match as far as overloading goes.
*/
virtual int overloadMatch(TemplateParameter *) = 0;
/* Match actual argument against parameter.
*/
virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) = 0;
/* Create dummy argument based on parameter.
*/
virtual void *dummyArg() = 0;
};
struct TemplateTypeParameter : TemplateParameter
{
/* Syntax:
* ident : specType = defaultType
*/
Type *specType; // type parameter: if !=NULL, this is the type specialization
Type *defaultType;
TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
TemplateTypeParameter *isTemplateTypeParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
void *dummyArg();
};
struct TemplateValueParameter : TemplateParameter
{
/* Syntax:
* valType ident : specValue = defaultValue
*/
Type *valType;
Expression *specValue;
Expression *defaultValue;
static Expression *edummy;
TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
TemplateValueParameter *isTemplateValueParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
void *dummyArg();
};
struct TemplateAliasParameter : TemplateParameter
{
/* Syntax:
* ident : specAlias = defaultAlias
*/
Type *specAliasT;
Dsymbol *specAlias;
Type *defaultAlias;
static Dsymbol *sdummy;
TemplateAliasParameter(Loc loc, Identifier *ident, Type *specAliasT, Type *defaultAlias);
TemplateAliasParameter *isTemplateAliasParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
void *dummyArg();
};
struct TemplateTupleParameter : TemplateParameter
{
/* Syntax:
* ident ...
*/
TemplateTupleParameter(Loc loc, Identifier *ident);
TemplateTupleParameter *isTemplateTupleParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
void *dummyArg();
};
struct TemplateInstance : ScopeDsymbol
{
/* Given:
* foo!(args) =>
* name = foo
* tiargs = args
*/
Identifier *name;
//Array idents;
Objects *tiargs; // Array of Types/Expressions of template
// instance arguments [int*, char, 10*10]
Objects tdtypes; // Array of Types/Expressions corresponding
// to TemplateDeclaration.parameters
// [int, char, 100]
TemplateDeclaration *tempdecl; // referenced by foo.bar.abc
TemplateInstance *inst; // refer to existing instance
ScopeDsymbol *argsym; // argument symbol table
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
// sole member
WithScopeSymbol *withsym; // if a member of a with statement
int semanticdone; // has semantic() been done?
int nest; // for recursion detection
int havetempdecl; // 1 if used second constructor
Dsymbol *isnested; // if referencing local symbols, this is the context
int errors; // 1 if compiled with errors
#ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol
will be emitted in the output or not before the symbol
is used. This can be different from getModule(). */
Module * objFileModule;
#endif
TemplateInstance(Loc loc, Identifier *temp_id);
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
static Objects *arraySyntaxCopy(Objects *objs);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Dsymbol *toAlias(); // resolve real symbol
char *kind();
int oneMember(Dsymbol **ps);
char *toChars();
char *mangle();
void toObjFile(); // compile to .obj file
// Internal
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs);
void semanticTiargs(Scope *sc);
TemplateDeclaration *findTemplateDeclaration(Scope *sc);
TemplateDeclaration *findBestMatch(Scope *sc);
void declareParameters(Scope *sc);
int isNested(Objects *tiargs);
Identifier *genIdent();
TemplateInstance *isTemplateInstance() { return this; }
AliasDeclaration *isAliasDeclaration();
};
struct TemplateMixin : TemplateInstance
{
Array *idents;
Type *tqual;
Scope *scope; // for forward referencing
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
char *kind();
int oneMember(Dsymbol **ps);
int hasPointers();
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toObjFile(); // compile to .obj file
TemplateMixin *isTemplateMixin() { return this; }
};
Expression *isExpression(Object *o);
Dsymbol *isDsymbol(Object *o);
Type *isType(Object *o);
Tuple *isTuple(Object *o);
Type *getType(Object *o);
Dsymbol *getDsymbol(Object *o);
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
#endif /* DMD_TEMPLATE_H */

45
dmd/total.h Normal file
View File

@@ -0,0 +1,45 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_TOTAL_H
#define DMD_TOTAL_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <wchar.h>
#include "root.h"
#include "stringtable.h"
#include "arraytypes.h"
#include "mars.h"
#include "lexer.h"
#include "parse.h"
#include "identifier.h"
#include "enum.h"
#include "aggregate.h"
#include "mtype.h"
#include "expression.h"
#include "declaration.h"
#include "statement.h"
#include "scope.h"
#include "import.h"
#include "module.h"
#include "id.h"
#include "cond.h"
#include "version.h"
#endif /* DMD_TOTAL_H */

323
dmd/unialpha.c Normal file
View File

@@ -0,0 +1,323 @@
// Copyright (c) 2003 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <assert.h>
/*******************************
* Return !=0 if unicode alpha.
* Use table from C99 Appendix D.
*/
int isUniAlpha(unsigned u)
{
static unsigned short table[][2] =
{
{ 0x00AA, 0x00AA },
{ 0x00B5, 0x00B5 },
{ 0x00B7, 0x00B7 },
{ 0x00BA, 0x00BA },
{ 0x00C0, 0x00D6 },
{ 0x00D8, 0x00F6 },
{ 0x00F8, 0x01F5 },
{ 0x01FA, 0x0217 },
{ 0x0250, 0x02A8 },
{ 0x02B0, 0x02B8 },
{ 0x02BB, 0x02BB },
{ 0x02BD, 0x02C1 },
{ 0x02D0, 0x02D1 },
{ 0x02E0, 0x02E4 },
{ 0x037A, 0x037A },
{ 0x0386, 0x0386 },
{ 0x0388, 0x038A },
{ 0x038C, 0x038C },
{ 0x038E, 0x03A1 },
{ 0x03A3, 0x03CE },
{ 0x03D0, 0x03D6 },
{ 0x03DA, 0x03DA },
{ 0x03DC, 0x03DC },
{ 0x03DE, 0x03DE },
{ 0x03E0, 0x03E0 },
{ 0x03E2, 0x03F3 },
{ 0x0401, 0x040C },
{ 0x040E, 0x044F },
{ 0x0451, 0x045C },
{ 0x045E, 0x0481 },
{ 0x0490, 0x04C4 },
{ 0x04C7, 0x04C8 },
{ 0x04CB, 0x04CC },
{ 0x04D0, 0x04EB },
{ 0x04EE, 0x04F5 },
{ 0x04F8, 0x04F9 },
{ 0x0531, 0x0556 },
{ 0x0559, 0x0559 },
{ 0x0561, 0x0587 },
{ 0x05B0, 0x05B9 },
{ 0x05BB, 0x05BD },
{ 0x05BF, 0x05BF },
{ 0x05C1, 0x05C2 },
{ 0x05D0, 0x05EA },
{ 0x05F0, 0x05F2 },
{ 0x0621, 0x063A },
{ 0x0640, 0x0652 },
{ 0x0660, 0x0669 },
{ 0x0670, 0x06B7 },
{ 0x06BA, 0x06BE },
{ 0x06C0, 0x06CE },
{ 0x06D0, 0x06DC },
{ 0x06E5, 0x06E8 },
{ 0x06EA, 0x06ED },
{ 0x06F0, 0x06F9 },
{ 0x0901, 0x0903 },
{ 0x0905, 0x0939 },
{ 0x093D, 0x093D },
{ 0x093E, 0x094D },
{ 0x0950, 0x0952 },
{ 0x0958, 0x0963 },
{ 0x0966, 0x096F },
{ 0x0981, 0x0983 },
{ 0x0985, 0x098C },
{ 0x098F, 0x0990 },
{ 0x0993, 0x09A8 },
{ 0x09AA, 0x09B0 },
{ 0x09B2, 0x09B2 },
{ 0x09B6, 0x09B9 },
{ 0x09BE, 0x09C4 },
{ 0x09C7, 0x09C8 },
{ 0x09CB, 0x09CD },
{ 0x09DC, 0x09DD },
{ 0x09DF, 0x09E3 },
{ 0x09E6, 0x09EF },
{ 0x09F0, 0x09F1 },
{ 0x0A02, 0x0A02 },
{ 0x0A05, 0x0A0A },
{ 0x0A0F, 0x0A10 },
{ 0x0A13, 0x0A28 },
{ 0x0A2A, 0x0A30 },
{ 0x0A32, 0x0A33 },
{ 0x0A35, 0x0A36 },
{ 0x0A38, 0x0A39 },
{ 0x0A3E, 0x0A42 },
{ 0x0A47, 0x0A48 },
{ 0x0A4B, 0x0A4D },
{ 0x0A59, 0x0A5C },
{ 0x0A5E, 0x0A5E },
{ 0x0A66, 0x0A6F },
{ 0x0A74, 0x0A74 },
{ 0x0A81, 0x0A83 },
{ 0x0A85, 0x0A8B },
{ 0x0A8D, 0x0A8D },
{ 0x0A8F, 0x0A91 },
{ 0x0A93, 0x0AA8 },
{ 0x0AAA, 0x0AB0 },
{ 0x0AB2, 0x0AB3 },
{ 0x0AB5, 0x0AB9 },
{ 0x0ABD, 0x0AC5 },
{ 0x0AC7, 0x0AC9 },
{ 0x0ACB, 0x0ACD },
{ 0x0AD0, 0x0AD0 },
{ 0x0AE0, 0x0AE0 },
{ 0x0AE6, 0x0AEF },
{ 0x0B01, 0x0B03 },
{ 0x0B05, 0x0B0C },
{ 0x0B0F, 0x0B10 },
{ 0x0B13, 0x0B28 },
{ 0x0B2A, 0x0B30 },
{ 0x0B32, 0x0B33 },
{ 0x0B36, 0x0B39 },
{ 0x0B3D, 0x0B3D },
{ 0x0B3E, 0x0B43 },
{ 0x0B47, 0x0B48 },
{ 0x0B4B, 0x0B4D },
{ 0x0B5C, 0x0B5D },
{ 0x0B5F, 0x0B61 },
{ 0x0B66, 0x0B6F },
{ 0x0B82, 0x0B83 },
{ 0x0B85, 0x0B8A },
{ 0x0B8E, 0x0B90 },
{ 0x0B92, 0x0B95 },
{ 0x0B99, 0x0B9A },
{ 0x0B9C, 0x0B9C },
{ 0x0B9E, 0x0B9F },
{ 0x0BA3, 0x0BA4 },
{ 0x0BA8, 0x0BAA },
{ 0x0BAE, 0x0BB5 },
{ 0x0BB7, 0x0BB9 },
{ 0x0BBE, 0x0BC2 },
{ 0x0BC6, 0x0BC8 },
{ 0x0BCA, 0x0BCD },
{ 0x0BE7, 0x0BEF },
{ 0x0C01, 0x0C03 },
{ 0x0C05, 0x0C0C },
{ 0x0C0E, 0x0C10 },
{ 0x0C12, 0x0C28 },
{ 0x0C2A, 0x0C33 },
{ 0x0C35, 0x0C39 },
{ 0x0C3E, 0x0C44 },
{ 0x0C46, 0x0C48 },
{ 0x0C4A, 0x0C4D },
{ 0x0C60, 0x0C61 },
{ 0x0C66, 0x0C6F },
{ 0x0C82, 0x0C83 },
{ 0x0C85, 0x0C8C },
{ 0x0C8E, 0x0C90 },
{ 0x0C92, 0x0CA8 },
{ 0x0CAA, 0x0CB3 },
{ 0x0CB5, 0x0CB9 },
{ 0x0CBE, 0x0CC4 },
{ 0x0CC6, 0x0CC8 },
{ 0x0CCA, 0x0CCD },
{ 0x0CDE, 0x0CDE },
{ 0x0CE0, 0x0CE1 },
{ 0x0CE6, 0x0CEF },
{ 0x0D02, 0x0D03 },
{ 0x0D05, 0x0D0C },
{ 0x0D0E, 0x0D10 },
{ 0x0D12, 0x0D28 },
{ 0x0D2A, 0x0D39 },
{ 0x0D3E, 0x0D43 },
{ 0x0D46, 0x0D48 },
{ 0x0D4A, 0x0D4D },
{ 0x0D60, 0x0D61 },
{ 0x0D66, 0x0D6F },
{ 0x0E01, 0x0E3A },
{ 0x0E40, 0x0E5B },
// { 0x0E50, 0x0E59 },
{ 0x0E81, 0x0E82 },
{ 0x0E84, 0x0E84 },
{ 0x0E87, 0x0E88 },
{ 0x0E8A, 0x0E8A },
{ 0x0E8D, 0x0E8D },
{ 0x0E94, 0x0E97 },
{ 0x0E99, 0x0E9F },
{ 0x0EA1, 0x0EA3 },
{ 0x0EA5, 0x0EA5 },
{ 0x0EA7, 0x0EA7 },
{ 0x0EAA, 0x0EAB },
{ 0x0EAD, 0x0EAE },
{ 0x0EB0, 0x0EB9 },
{ 0x0EBB, 0x0EBD },
{ 0x0EC0, 0x0EC4 },
{ 0x0EC6, 0x0EC6 },
{ 0x0EC8, 0x0ECD },
{ 0x0ED0, 0x0ED9 },
{ 0x0EDC, 0x0EDD },
{ 0x0F00, 0x0F00 },
{ 0x0F18, 0x0F19 },
{ 0x0F20, 0x0F33 },
{ 0x0F35, 0x0F35 },
{ 0x0F37, 0x0F37 },
{ 0x0F39, 0x0F39 },
{ 0x0F3E, 0x0F47 },
{ 0x0F49, 0x0F69 },
{ 0x0F71, 0x0F84 },
{ 0x0F86, 0x0F8B },
{ 0x0F90, 0x0F95 },
{ 0x0F97, 0x0F97 },
{ 0x0F99, 0x0FAD },
{ 0x0FB1, 0x0FB7 },
{ 0x0FB9, 0x0FB9 },
{ 0x10A0, 0x10C5 },
{ 0x10D0, 0x10F6 },
{ 0x1E00, 0x1E9B },
{ 0x1EA0, 0x1EF9 },
{ 0x1F00, 0x1F15 },
{ 0x1F18, 0x1F1D },
{ 0x1F20, 0x1F45 },
{ 0x1F48, 0x1F4D },
{ 0x1F50, 0x1F57 },
{ 0x1F59, 0x1F59 },
{ 0x1F5B, 0x1F5B },
{ 0x1F5D, 0x1F5D },
{ 0x1F5F, 0x1F7D },
{ 0x1F80, 0x1FB4 },
{ 0x1FB6, 0x1FBC },
{ 0x1FBE, 0x1FBE },
{ 0x1FC2, 0x1FC4 },
{ 0x1FC6, 0x1FCC },
{ 0x1FD0, 0x1FD3 },
{ 0x1FD6, 0x1FDB },
{ 0x1FE0, 0x1FEC },
{ 0x1FF2, 0x1FF4 },
{ 0x1FF6, 0x1FFC },
{ 0x203F, 0x2040 },
{ 0x207F, 0x207F },
{ 0x2102, 0x2102 },
{ 0x2107, 0x2107 },
{ 0x210A, 0x2113 },
{ 0x2115, 0x2115 },
{ 0x2118, 0x211D },
{ 0x2124, 0x2124 },
{ 0x2126, 0x2126 },
{ 0x2128, 0x2128 },
{ 0x212A, 0x2131 },
{ 0x2133, 0x2138 },
{ 0x2160, 0x2182 },
{ 0x3005, 0x3007 },
{ 0x3021, 0x3029 },
{ 0x3041, 0x3093 },
{ 0x309B, 0x309C },
{ 0x30A1, 0x30F6 },
{ 0x30FB, 0x30FC },
{ 0x3105, 0x312C },
{ 0x4E00, 0x9FA5 },
{ 0xAC00, 0xD7A3 },
};
#ifdef DEBUG
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
{
//printf("%x\n", table[i][0]);
assert(table[i][0] <= table[i][1]);
if (i < sizeof(table) / sizeof(table[0]) - 1)
assert(table[i][1] < table[i + 1][0]);
}
#endif
if (u > 0xD7A3)
goto Lisnot;
// Binary search
int mid;
int low;
int high;
low = 0;
high = sizeof(table) / sizeof(table[0]) - 1;
while (low <= high)
{
mid = (low + high) >> 1;
if (u < table[mid][0])
high = mid - 1;
else if (u > table[mid][1])
low = mid + 1;
else
goto Lis;
}
Lisnot:
#ifdef DEBUG
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
{
assert(u < table[i][0] || u > table[i][1]);
}
#endif
return 0;
Lis:
#ifdef DEBUG
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
{
if (u >= table[i][0] && u <= table[i][1])
return 1;
}
assert(0); // should have been in table
#endif
return 1;
}

193
dmd/utf.c Normal file
View File

@@ -0,0 +1,193 @@
// utf.c
// Copyright (c) 2003 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
// Description of UTF-8 at:
// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
#include <stdio.h>
#include <assert.h>
#include "utf.h"
int utf_isValidDchar(dchar_t c)
{
return c < 0xD800 ||
(c > 0xDFFF && c <= 0x10FFFF && c != 0xFFFE && c != 0xFFFF);
}
/********************************************
* Decode a single UTF-8 character sequence.
* Returns:
* NULL success
* !=NULL error message string
*/
char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult)
{
dchar_t V;
size_t i = *pidx;
unsigned char u = s[i];
assert(i >= 0 && i < len);
if (u & 0x80)
{ unsigned n;
unsigned char u2;
/* The following encodings are valid, except for the 5 and 6 byte
* combinations:
* 0xxxxxxx
* 110xxxxx 10xxxxxx
* 1110xxxx 10xxxxxx 10xxxxxx
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
for (n = 1; ; n++)
{
if (n > 4)
goto Lerr; // only do the first 4 of 6 encodings
if (((u << n) & 0x80) == 0)
{
if (n == 1)
goto Lerr;
break;
}
}
// Pick off (7 - n) significant bits of B from first byte of octet
V = (dchar_t)(u & ((1 << (7 - n)) - 1));
if (i + (n - 1) >= len)
goto Lerr; // off end of string
/* The following combinations are overlong, and illegal:
* 1100000x (10xxxxxx)
* 11100000 100xxxxx (10xxxxxx)
* 11110000 1000xxxx (10xxxxxx 10xxxxxx)
* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
*/
u2 = s[i + 1];
if ((u & 0xFE) == 0xC0 ||
(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
(u == 0xFC && (u2 & 0xFC) == 0x80))
goto Lerr; // overlong combination
for (unsigned j = 1; j != n; j++)
{
u = s[i + j];
if ((u & 0xC0) != 0x80)
goto Lerr; // trailing bytes are 10xxxxxx
V = (V << 6) | (u & 0x3F);
}
if (!utf_isValidDchar(V))
goto Lerr;
i += n;
}
else
{
V = (dchar_t) u;
i++;
}
assert(utf_isValidDchar(V));
*pidx = i;
*presult = V;
return NULL;
Lerr:
*presult = (dchar_t) s[i];
*pidx = i + 1;
return "invalid UTF-8 sequence";
}
/***************************************************
* Validate a UTF-8 string.
* Returns:
* NULL success
* !=NULL error message string
*/
char *utf_validateString(unsigned char *s, size_t len)
{
size_t idx;
char *err = NULL;
dchar_t dc;
for (idx = 0; idx < len; )
{
err = utf_decodeChar(s, len, &idx, &dc);
if (err)
break;
}
return err;
}
/********************************************
* Decode a single UTF-16 character sequence.
* Returns:
* NULL success
* !=NULL error message string
*/
char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult)
{
char *msg;
size_t i = *pidx;
unsigned u = s[i];
assert(i >= 0 && i < len);
if (u & ~0x7F)
{ if (u >= 0xD800 && u <= 0xDBFF)
{ unsigned u2;
if (i + 1 == len)
{ msg = "surrogate UTF-16 high value past end of string";
goto Lerr;
}
u2 = s[i + 1];
if (u2 < 0xDC00 || u2 > 0xDFFF)
{ msg = "surrogate UTF-16 low value out of range";
goto Lerr;
}
u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
i += 2;
}
else if (u >= 0xDC00 && u <= 0xDFFF)
{ msg = "unpaired surrogate UTF-16 value";
goto Lerr;
}
else if (u == 0xFFFE || u == 0xFFFF)
{ msg = "illegal UTF-16 value";
goto Lerr;
}
else
i++;
}
else
{
i++;
}
assert(utf_isValidDchar(u));
*pidx = i;
*presult = (dchar_t)u;
return NULL;
Lerr:
*presult = (dchar_t)s[i];
*pidx = i + 1;
return msg;
}

26
dmd/utf.h Normal file
View File

@@ -0,0 +1,26 @@
// Compiler implementation of the D programming language
// utf.h
// Copyright (c) 2003-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_UTF_H
#define DMD_UTF_H
typedef unsigned dchar_t;
int utf_isValidDchar(dchar_t c);
char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult);
char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult);
char *utf_validateString(unsigned char *s, size_t len);
extern int isUniAlpha(dchar_t);
#endif

181
dmd/version.c Normal file
View File

@@ -0,0 +1,181 @@
// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "identifier.h"
#include "dsymbol.h"
#include "cond.h"
#include "version.h"
#include "module.h"
/* ================================================== */
/* DebugSymbol's happen for statements like:
* debug = identifier;
* debug = integer;
*/
DebugSymbol::DebugSymbol(Loc loc, Identifier *ident)
: Dsymbol(ident)
{
this->loc = loc;
}
DebugSymbol::DebugSymbol(Loc loc, unsigned level)
: Dsymbol()
{
this->level = level;
this->loc = loc;
}
Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s)
{
assert(!s);
DebugSymbol *ds = new DebugSymbol(loc, ident);
ds->level = level;
return ds;
}
int DebugSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
//printf("DebugSymbol::addMember('%s') %s\n", sd->toChars(), toChars());
Module *m;
// Do not add the member to the symbol table,
// just make sure subsequent debug declarations work.
m = sd->isModule();
if (ident)
{
if (!m)
error("declaration must be at module level");
else
{
if (findCondition(m->debugidsNot, ident))
error("defined after use");
if (!m->debugids)
m->debugids = new Array();
m->debugids->push(ident->toChars());
}
}
else
{
if (!m)
error("level declaration must be at module level");
else
m->debuglevel = level;
}
return 0;
}
void DebugSymbol::semantic(Scope *sc)
{
//printf("DebugSymbol::semantic() %s\n", toChars());
}
void DebugSymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("debug = ");
if (ident)
buf->writestring(ident->toChars());
else
buf->printf("%u", level);
buf->writestring(";");
buf->writenl();
}
char *DebugSymbol::kind()
{
return "debug";
}
/* ================================================== */
/* VersionSymbol's happen for statements like:
* version = identifier;
* version = integer;
*/
VersionSymbol::VersionSymbol(Loc loc, Identifier *ident)
: Dsymbol(ident)
{
this->loc = loc;
}
VersionSymbol::VersionSymbol(Loc loc, unsigned level)
: Dsymbol()
{
this->level = level;
this->loc = loc;
}
Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s)
{
assert(!s);
VersionSymbol *ds = new VersionSymbol(loc, ident);
ds->level = level;
return ds;
}
int VersionSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
//printf("VersionSymbol::addMember('%s') %s\n", sd->toChars(), toChars());
Module *m;
// Do not add the member to the symbol table,
// just make sure subsequent debug declarations work.
m = sd->isModule();
if (ident)
{
VersionCondition::checkPredefined(loc, ident->toChars());
if (!m)
error("declaration must be at module level");
else
{
if (findCondition(m->versionidsNot, ident))
error("defined after use");
if (!m->versionids)
m->versionids = new Array();
m->versionids->push(ident->toChars());
}
}
else
{
if (!m)
error("level declaration must be at module level");
else
m->versionlevel = level;
}
return 0;
}
void VersionSymbol::semantic(Scope *sc)
{
}
void VersionSymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("version = ");
if (ident)
buf->writestring(ident->toChars());
else
buf->printf("%u", level);
buf->writestring(";");
buf->writenl();
}
char *VersionSymbol::kind()
{
return "version";
}

51
dmd/version.h Normal file
View File

@@ -0,0 +1,51 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_VERSION_H
#define DMD_VERSION_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct OutBuffer;
struct HdrGenState;
struct DebugSymbol : Dsymbol
{
unsigned level;
DebugSymbol(Loc loc, Identifier *ident);
DebugSymbol(Loc loc, unsigned level);
Dsymbol *syntaxCopy(Dsymbol *);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
};
struct VersionSymbol : Dsymbol
{
unsigned level;
VersionSymbol(Loc loc, Identifier *ident);
VersionSymbol(Loc loc, unsigned level);
Dsymbol *syntaxCopy(Dsymbol *);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *kind();
};
#endif /* DMD_VERSION_H */

65
gen/elem.c Normal file
View File

@@ -0,0 +1,65 @@
#include <iostream>
#include "llvm/Instructions.h"
#include "elem.h"
#include "irstate.h"
#include "logger.h"
//////////////////////////////////////////////////////////////////////////////////////////
elem::elem()
{
mem = 0;
val = 0;
arg = 0;
type = NONE;
inplace = false;
field = false;
vardecl = 0;
funcdecl = 0;
}
llvm::Value* elem::getValue()
{
assert(val || mem);
switch(type)
{
case NONE:
assert(0 && "type == NONE");
break;
case VAR:
case REF: {
if (val) {
return val;
}
else {
if (!llvm::isa<llvm::PointerType>(mem->getType()))
{
Logger::cout() << "unexpected type: " << *mem->getType() << '\n';
assert(0);
}
const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(mem->getType());
if (!pt->getElementType()->isFirstClassType()) {
return mem;
}
else {
return new llvm::LoadInst(mem, "tmp", gIR->scopebb());
}
}
}
case VAL:
case NUL:
case FUNC:
case CONST:
case SLICE:
return val ? val : mem;
}
assert(0 && "type == invalid value");
return 0;
}

44
gen/elem.h Normal file
View File

@@ -0,0 +1,44 @@
#ifndef LLVMDC_GEN_ELEM_H
#define LLVMDC_GEN_ELEM_H
#include "llvm/Value.h"
#include "root.h"
#include "declaration.h"
#include "aggregate.h"
// represents a value. be it a constant literal, a variable etc.
// maintains all the information for doing load/store appropriately
struct elem : Object
{
enum {
NONE,
VAR,
VAL,
FUNC,
CONST,
NUL,
REF,
SLICE
};
public:
elem();
llvm::Value* mem;
llvm::Value* val;
llvm::Value* arg;
int type;
bool inplace;
bool field;
VarDeclaration* vardecl;
FuncDeclaration* funcdecl;
llvm::Value* getValue();
//llvm::Value* getMemory();
bool isNull() {return !(mem || val);}
};
#endif // LLVMDC_GEN_ELEM_H

8
gen/enums.h Normal file
View File

@@ -0,0 +1,8 @@
enum
{
LLVMnone,
LLVMnull,
LLVMmangle,
LLVMintrinsic,
LLVMbind,
};

111
gen/irstate.c Normal file
View File

@@ -0,0 +1,111 @@
/* DMDFE backend stubs
* This file contains the implementations of the backend routines.
* For dmdfe these do nothing but print a message saying the module
* has been parsed. Substitute your own behaviors for these routimes.
*/
#include "irstate.h"
#include "mtype.h"
IRState* gIR = 0;
llvm::TargetData* gTargetData = 0;
//////////////////////////////////////////////////////////////////////////////////////////
IRScope::IRScope()
{
begin = end = 0;
returned = false;
}
IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
{
begin = b;
end = e;
returned = false;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRState::IRState()
{
dmodule = 0;
module = 0;
inLvalue = false;
emitMain = false;
mainFunc = 0;
}
llvm::Function* IRState::topfunc()
{
assert(!funcs.empty() && "Function stack is empty!");
return funcs.top();
}
TypeFunction* IRState::topfunctype()
{
assert(!functypes.empty() && "TypeFunction stack is empty!");
return functypes.top();
}
llvm::Instruction* IRState::topallocapoint()
{
assert(!functypes.empty() && "AllocaPoint stack is empty!");
return functypes.top()->llvmAllocaPoint;
}
IRStruct& IRState::topstruct()
{
assert(!structs.empty() && "Struct vector is empty!");
return structs.back();
}
llvm::Value* IRState::toplval()
{
assert(!lvals.empty() && "Lval vector is empty!");
return lvals.back();
}
IRScope& IRState::scope()
{
assert(!scopes.empty());
return scopes.back();
}
llvm::BasicBlock* IRState::scopebb()
{
return scopebegin();
}
llvm::BasicBlock* IRState::scopebegin()
{
IRScope& s = scope();
assert(s.begin);
return s.begin;
}
llvm::BasicBlock* IRState::scopeend()
{
IRScope& s = scope();
assert(s.end);
return s.end;
}
bool IRState::scopereturned()
{
return scope().returned;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRStruct::IRStruct()
: recty(llvm::OpaqueType::get())
{
type = 0;
}
IRStruct::IRStruct(TypeStruct* t)
: recty(llvm::OpaqueType::get())
{
type = t;
}
IRStruct::~IRStruct()
{
}

122
gen/irstate.h Normal file
View File

@@ -0,0 +1,122 @@
#ifndef LLVMDC_GEN_IRSTATE_H
#define LLVMDC_GEN_IRSTATE_H
#include <stack>
#include <vector>
#include <deque>
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/BasicBlock.h"
#include "llvm/Target/TargetData.h"
#include "root.h"
// global ir state for current module
struct IRState;
extern IRState* gIR;
extern llvm::TargetData* gTargetData;
struct TypeFunction;
struct TypeStruct;
struct ClassDeclaration;
struct FuncDeclaration;
struct Module;
struct TypeStruct;
// represents a scope
struct IRScope
{
llvm::BasicBlock* begin;
llvm::BasicBlock* end;
bool returned;
IRScope();
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
};
// represents a struct
struct IRStruct : Object
{
typedef std::vector<const llvm::Type*> TypeVector;
typedef std::vector<llvm::Constant*> ConstantVector;
typedef std::vector<llvm::PATypeHolder> PATypeHolderVector;
public:
IRStruct();
IRStruct(TypeStruct*);
virtual ~IRStruct();
TypeStruct* type;
TypeVector fields;
ConstantVector inits;
llvm::PATypeHolder recty;
};
// represents a clas
struct IRClass : Object
{
// TODO
};
// represents the module
struct IRState : Object
{
IRState();
// module
Module* dmodule;
llvm::Module* module;
// functions
std::stack<llvm::Function*> funcs;
llvm::Function* topfunc();
std::stack<TypeFunction*> functypes;
TypeFunction* topfunctype();
llvm::Instruction* topallocapoint();
// structs
typedef std::vector<IRStruct> StructVector;
StructVector structs;
IRStruct& topstruct();
// classes TODO move into IRClass
typedef std::vector<ClassDeclaration*> ClassDeclVec;
ClassDeclVec classes;
typedef std::vector<FuncDeclaration*> FuncDeclVec;
typedef std::vector<FuncDeclVec> ClassMethodVec;
ClassMethodVec classmethods;
typedef std::vector<bool> BoolVec;
BoolVec queueClassMethods;
// D main function
bool emitMain;
llvm::Function* mainFunc;
// L-values
bool inLvalue;
typedef std::vector<llvm::Value*> LvalVec;
LvalVec lvals;
llvm::Value* toplval();
// basic block scopes
std::vector<IRScope> scopes;
IRScope& scope();
llvm::BasicBlock* scopebegin();
llvm::BasicBlock* scopeend();
llvm::BasicBlock* scopebb();
bool scopereturned();
// loop blocks
typedef std::vector<IRScope> BBVec;
BBVec loopbbs;
// this holds the array being indexed or sliced so $ will work
// might be a better way but it works. problem is I only get a
// VarDeclaration for __dollar, but I can't see how to get the
// array pointer from this :(
LvalVec arrays;
};
#endif // LLVMDC_GEN_IRSTATE_H

47
gen/logger.c Normal file
View File

@@ -0,0 +1,47 @@
#ifndef LLVMD_NO_LOGGER
#include <cassert>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include "logger.h"
namespace Logger
{
static std::string indent_str;
void indent()
{
indent_str += " ";
}
void undent()
{
assert(!indent_str.empty());
indent_str.resize(indent_str.size()-2);
}
std::ostream& cout()
{
return std::cout << indent_str;
}
void println(const char* fmt,...)
{
printf(indent_str.c_str());
va_list va;
va_start(va,fmt);
vprintf(fmt,va);
va_end(va);
printf("\n");
}
void print(const char* fmt,...)
{
printf(indent_str.c_str());
va_list va;
va_start(va,fmt);
vprintf(fmt,va);
va_end(va);
}
}
#endif

48
gen/logger.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef _llvmd_gen_logger_h_
#define _llvmd_gen_logger_h_
#include <iostream>
namespace Logger
{
#ifndef LLVMD_NO_LOGGER
void indent();
void undent();
std::ostream& cout();
void println(const char* fmt,...);
void print(const char* fmt,...);
#else
inline void indent() {}
inline void undent() {}
inline std::ostream& cout() { return std::cout; }
inline void println(const char* fmt, ...) {}
inline void print(const char* fmt, ...) {}
#endif
struct LoggerScope
{
LoggerScope()
{
#ifndef LLVMD_NO_LOGGER
//std::cout << "-->indented\n";
Logger::indent();
#endif
}
~LoggerScope()
{
#ifndef LLVMD_NO_LOGGER
//std::cout << "<--undented\n";
Logger::undent();
#endif
}
};
}
#ifndef LLVMD_NO_LOGGER
#define LOG_SCOPE Logger::LoggerScope _logscope;
#else
#define LOG_SCOPE
#endif
#endif

74
gen/runtime.c Normal file
View File

@@ -0,0 +1,74 @@
#include <cassert>
#include "llvm/Module.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/MemoryBuffer.h"
#include "runtime.h"
#include "logger.h"
#include "root.h"
#include "mars.h"
static llvm::Module* M = NULL;
static bool runtime_failed = false;
bool LLVM_D_InitRuntime()
{
Logger::println("*** Loading D runtime ***");
LOG_SCOPE;
std::string filename(global.params.runtimeImppath);
filename.append("/llvmdcore.bc");
llvm::MemoryBuffer* buffer = llvm::MemoryBuffer::getFile(filename.c_str(), filename.length());
if (!buffer) {
Logger::println("Failed to load runtime library from disk");
runtime_failed = true;
return false;
}
std::string errstr;
bool retval = false;
M = llvm::ParseBitcodeFile(buffer, &errstr);
if (M) {
retval = true;
}
else {
Logger::println("Failed to load runtime: %s", errstr.c_str());
runtime_failed = true;
}
delete buffer;
return retval;
}
void LLVM_D_FreeRuntime()
{
if (M) {
Logger::println("*** Freeing D runtime ***");
delete M;
}
}
llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name)
{
// TODO maybe check the target module first, to allow overriding the runtime on a pre module basis?
// could be done and seems like it could be neat too :)
if (global.params.noruntime) {
error("No implicit runtime calls allowed with -noruntime option enabled");
fatal();
}
if (!M) {
assert(!runtime_failed);
LLVM_D_InitRuntime();
}
llvm::Function* fn = M->getFunction(name);
if (!fn)
return NULL;
const llvm::FunctionType* fnty = fn->getFunctionType();
return llvm::cast<llvm::Function>(target->getOrInsertFunction(name, fnty));
}

Some files were not shown because too many files have changed in this diff Show More