# HG changeset patch # User Robert Clipsham # Date 1252400876 -3600 # Node ID e4f7b5d9c68a601ba926481ee9ca24b12a6c1dc8 # Parent 4551475bc6b6033339f9ddf546e406d8f38a68d9 DMD 2.032 Merge. diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/arrayop.c --- a/dmd2/arrayop.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/arrayop.c Tue Sep 08 10:07:56 2009 +0100 @@ -333,6 +333,17 @@ arguments->shift(this); } +void CastExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) +{ + Type *tb = type->toBasetype(); + if (tb->ty == Tarray || tb->ty == Tsarray) + { + e1->buildArrayIdent(buf, arguments); + } + else + Expression::buildArrayIdent(buf, arguments); +} + void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) { buf->writestring("Slice"); @@ -417,6 +428,17 @@ return e; } +Expression *CastExp::buildArrayLoop(Arguments *fparams) +{ + Type *tb = type->toBasetype(); + if (tb->ty == Tarray || tb->ty == Tsarray) + { + return e1->buildArrayLoop(fparams); + } + else + Expression::buildArrayLoop(fparams); +} + Expression *SliceExp::buildArrayLoop(Arguments *fparams) { Identifier *id = Identifier::generateId("p", fparams->dim); @@ -435,12 +457,14 @@ /* Evaluate assign expressions right to left */ Expression *ex2 = e2->buildArrayLoop(fparams); +#if DMDV2 /* Need the cast because: * b = c + p[i]; * where b is a byte fails because (c + p[i]) is an int * which cannot be implicitly cast to byte. */ ex2 = new CastExp(0, ex2, e1->type->nextOf()); +#endif Expression *ex1 = e1->buildArrayLoop(fparams); Argument *param = (Argument *)fparams->data[0]; param->storageClass = 0; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/attrib.c --- a/dmd2/attrib.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/attrib.c Tue Sep 08 10:07:56 2009 +0100 @@ -77,6 +77,41 @@ return m; } +void AttribDeclaration::setScopeNewSc(Scope *sc, + unsigned stc, enum LINK linkage, enum PROT protection, int explicitProtection, + unsigned structalign) +{ + if (decl) + { + Scope *newsc = sc; + if (stc != sc->stc || + linkage != sc->linkage || + protection != sc->protection || + explicitProtection != sc->explicitProtection || + structalign != sc->structalign) + { + // create new one for changes + newsc = new Scope(*sc); + newsc->flags &= ~SCOPEfree; + newsc->stc = stc; + newsc->linkage = linkage; + newsc->protection = protection; + newsc->explicitProtection = explicitProtection; + newsc->structalign = structalign; + } + for (unsigned i = 0; i < decl->dim; i++) + { Dsymbol *s = (Dsymbol *)decl->data[i]; + + s->setScope(newsc); // yes, the only difference from semanticNewSc() + } + if (newsc != sc) + { + sc->offset = newsc->offset; + newsc->pop(); + } + } +} + void AttribDeclaration::semanticNewSc(Scope *sc, unsigned stc, enum LINK linkage, enum PROT protection, int explicitProtection, unsigned structalign) @@ -340,11 +375,33 @@ return scd; } +void StorageClassDeclaration::setScope(Scope *sc) +{ + if (decl) + { + unsigned scstc = sc->stc; + + /* These sets of storage classes are mutually exclusive, + * so choose the innermost or most recent one. + */ + if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest)) + scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest); + if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared)) + scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared); + if (stc & (STCconst | STCimmutable | STCmanifest)) + scstc &= ~(STCconst | STCimmutable | STCmanifest); + if (stc & (STCgshared | STCshared | STCtls)) + scstc &= ~(STCgshared | STCshared | STCtls); + scstc |= stc; + + setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); + } +} + void StorageClassDeclaration::semantic(Scope *sc) { if (decl) { -#if 1 unsigned scstc = sc->stc; /* These sets of storage classes are mutually exclusive, @@ -361,29 +418,6 @@ scstc |= stc; semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); -#else - unsigned stc_save = sc->stc; - - /* These sets of storage classes are mutually exclusive, - * so choose the innermost or most recent one. - */ - if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest)) - sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest); - if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared)) - sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared); - if (stc & (STCconst | STCimmutable | STCmanifest)) - sc->stc &= ~(STCconst | STCimmutable | STCmanifest); - if (stc & (STCgshared | STCshared | STCtls)) - sc->stc &= ~(STCgshared | STCshared | STCtls); - sc->stc |= stc; - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - } - sc->stc = stc_save; -#endif } } @@ -402,22 +436,24 @@ { STCstatic, TOKstatic }, { STCextern, TOKextern }, { STCconst, TOKconst }, - { STCimmutable, TOKimmutable }, - { STCshared, TOKshared }, { STCfinal, TOKfinal }, { STCabstract, TOKabstract }, { STCsynchronized, TOKsynchronized }, { STCdeprecated, TOKdeprecated }, { STCoverride, TOKoverride }, + { STClazy, TOKlazy }, + { STCalias, TOKalias }, + { STCout, TOKout }, + { STCin, TOKin }, +#if DMDV2 + { STCimmutable, TOKimmutable }, + { STCshared, TOKshared }, { STCnothrow, TOKnothrow }, { STCpure, TOKpure }, { STCref, TOKref }, { STCtls, TOKtls }, { STCgshared, TOKgshared }, - { STClazy, TOKlazy }, - { STCalias, TOKalias }, - { STCout, TOKout }, - { STCin, TOKin }, +#endif }; for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++) @@ -454,25 +490,21 @@ return ld; } +void LinkDeclaration::setScope(Scope *sc) +{ + //printf("LinkDeclaration::setScope(linkage = %d, decl = %p)\n", linkage, decl); + if (decl) + { + setScopeNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign); + } +} + void LinkDeclaration::semantic(Scope *sc) { //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl); if (decl) { -#if 1 semanticNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign); -#else - enum LINK linkage_save = sc->linkage; - - sc->linkage = linkage; - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - } - sc->linkage = linkage_save; -#endif } } @@ -544,27 +576,19 @@ return pd; } +void ProtDeclaration::setScope(Scope *sc) +{ + if (decl) + { + setScopeNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign); + } +} + void ProtDeclaration::semantic(Scope *sc) { if (decl) { -#if 1 semanticNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign); -#else - enum PROT protection_save = sc->protection; - int explicitProtection_save = sc->explicitProtection; - - sc->protection = protection; - sc->explicitProtection = 1; - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - - s->semantic(sc); - } - sc->protection = protection_save; - sc->explicitProtection = explicitProtection_save; -#endif } } @@ -611,44 +635,21 @@ return ad; } +void AlignDeclaration::setScope(Scope *sc) +{ + //printf("\tAlignDeclaration::setScope '%s'\n",toChars()); + if (decl) + { + setScopeNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign); + } +} + void AlignDeclaration::semantic(Scope *sc) { -// LDC -// we only support packed structs, as from the spec: align(1) struct Packed { ... } -// other alignments are simply ignored. my tests show this is what llvm-gcc does too ... - //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); if (decl) { -#if 1 semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign); -#else - unsigned salign_save = sc->structalign; - -#if IN_DMD - sc->structalign = salign; -#endif - for (unsigned i = 0; i < decl->dim; i++) - { - Dsymbol *s = (Dsymbol *)decl->data[i]; - -#if IN_LLVM - if (s->isStructDeclaration() && salign == 1) - { - sc->structalign = salign; - s->semantic(sc); - sc->structalign = salign_save; - } - else - { -#endif - s->semantic(sc); -#if IN_LLVM - } -#endif - } - sc->structalign = salign_save; -#endif } else assert(0 && "what kind of align use triggers this?"); @@ -870,6 +871,39 @@ return pd; } +void PragmaDeclaration::setScope(Scope *sc) +{ +#if TARGET_NET + if (ident == Lexer::idPool("assembly")) + { + if (!args || args->dim != 1) + { + error("pragma has invalid number of arguments"); + } + else + { + Expression *e = (Expression *)args->data[0]; + e = e->semantic(sc); + e = e->optimize(WANTvalue | WANTinterpret); + args->data[0] = (void *)e; + if (e->op != TOKstring) + { + error("string expected, not '%s'", e->toChars()); + } + PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast(e)); + + assert(sc); + pragma->setScope(sc); + + //add to module members + assert(sc->module); + assert(sc->module->members); + sc->module->members->push(pragma); + } + } +#endif // TARGET_NET +} + void PragmaDeclaration::semantic(Scope *sc) { // Should be merged with PragmaStatement @@ -892,7 +926,7 @@ if (e->op == TOKstring) { StringExp *se = (StringExp *)e; - fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string); + fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); } else error("string expected for message, not '%s'", e->toChars()); @@ -981,22 +1015,6 @@ #if TARGET_NET else if (ident == Lexer::idPool("assembly")) { - if (!args || args->dim != 1) - error("pragma has invalid number of arguments"); - else - { - Expression *e = (Expression *)args->data[0]; - e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); - args->data[0] = (void *)e; - if (e->op != TOKstring) - { - error("string expected, not '%s'", e->toChars()); - } - PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast(e)); - decl = new Array; - decl->push(pragma); - } } #endif // TARGET_NET // LDC diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/attrib.h --- a/dmd2/attrib.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/attrib.h Tue Sep 08 10:07:56 2009 +0100 @@ -36,6 +36,9 @@ AttribDeclaration(Array *decl); virtual Array *include(Scope *sc, ScopeDsymbol *s); int addMember(Scope *sc, ScopeDsymbol *s, int memnum); + void setScopeNewSc(Scope *sc, + unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection, + unsigned structalign); void semanticNewSc(Scope *sc, unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection, unsigned structalign); @@ -69,6 +72,7 @@ StorageClassDeclaration(unsigned stc, Array *decl); Dsymbol *syntaxCopy(Dsymbol *s); + void setScope(Scope *sc); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -81,6 +85,7 @@ LinkDeclaration(enum LINK p, Array *decl); Dsymbol *syntaxCopy(Dsymbol *s); + void setScope(Scope *sc); void semantic(Scope *sc); void semantic3(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -93,6 +98,7 @@ ProtDeclaration(enum PROT p, Array *decl); Dsymbol *syntaxCopy(Dsymbol *s); + void setScope(Scope *sc); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -105,6 +111,7 @@ AlignDeclaration(Loc loc, unsigned sa, Array *decl); Dsymbol *syntaxCopy(Dsymbol *s); + void setScope(Scope *sc); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -128,6 +135,7 @@ PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); + void setScope(Scope *sc); int oneMember(Dsymbol **ps); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); const char *kind(); diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/cast.c --- a/dmd2/cast.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/cast.c Tue Sep 08 10:07:56 2009 +0100 @@ -1796,8 +1796,17 @@ if (op == TOKmin || op == TOKadd) { - if (t1 == t2 && (t1->ty == Tstruct || t1->ty == Tclass)) - goto Lerror; + if (t1->ty == Tstruct) + { + if (t2->ty == Tstruct && + ((TypeStruct *)t1)->sym == ((TypeStruct *)t2)->sym) + goto Lerror; + } + else if (t1->ty == Tclass) + { + if (t2->ty == Tclass) + goto Lerror; + } } if (!typeMerge(sc, this, &type, &e1, &e2)) @@ -1941,6 +1950,9 @@ IntRange ir1 = e1->getIntRange(); IntRange ir2 = e2->getIntRange(); + if (ir2.imax == 0 || ir2.imin == 0) + return Expression::getIntRange(); + ir.imin = ir1.imin / ir2.imax; ir.imax = ir1.imax / ir2.imin; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/class.c --- a/dmd2/class.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/class.c Tue Sep 08 10:07:56 2009 +0100 @@ -349,6 +349,8 @@ //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars()); scope = scx ? scx : new Scope(*sc); scope->setNoFree(); + if (tc->sym->scope) + tc->sym->scope->module->addDeferredSemantic(tc->sym); scope->module->addDeferredSemantic(this); return; } @@ -402,6 +404,12 @@ error("inherits from duplicate interface %s", b2->base->toChars()); } + if (!tc->sym->symtab) + { // Try to resolve forward reference + if (sc->mustsemantic && tc->sym->scope) + tc->sym->semantic(NULL); + } + b->base = tc->sym; if (!b->base->symtab || b->base->scope) { @@ -410,6 +418,8 @@ //printf("\ttry later, forward reference of base %s\n", baseClass->toChars()); scope = scx ? scx : new Scope(*sc); scope->setNoFree(); + if (tc->sym->scope) + tc->sym->scope->module->addDeferredSemantic(tc->sym); scope->module->addDeferredSemantic(this); return; } @@ -798,8 +808,8 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) { Dsymbol *s; + //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); - //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); if (scope) { Scope *sc = scope; sc->mustsemantic++; @@ -962,10 +972,12 @@ return 0; } +#if DMDV2 int ClassDeclaration::isCPPinterface() { return 0; } +#endif /**************************************** @@ -1142,6 +1154,11 @@ baseclasses.remove(i); continue; } + if (!b->base->symtab) + { // Try to resolve forward reference + if (sc->mustsemantic && b->base->scope) + b->base->semantic(NULL); + } if (!b->base->symtab || b->base->scope || b->base->inuse) { //error("forward reference of base class %s", baseClass->toChars()); @@ -1326,10 +1343,12 @@ return com; } +#if DMDV2 int InterfaceDeclaration::isCPPinterface() { return cpp; } +#endif /******************************************* */ diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/constfold.c --- a/dmd2/constfold.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/constfold.c Tue Sep 08 10:07:56 2009 +0100 @@ -65,6 +65,11 @@ return 1; } +int NullExp::isConst() +{ + return 0; +} + int SymOffExp::isConst() { return 2; @@ -1084,6 +1089,8 @@ Type *tb = to->toBasetype(); Type *typeb = type->toBasetype(); + /* Allow casting from one string type to another + */ if (e1->op == TOKstring) { if (tb->ty == Tarray && typeb->ty == Tarray && diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/cppmangle.c --- a/dmd2/cppmangle.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/cppmangle.c Tue Sep 08 10:07:56 2009 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -25,7 +25,7 @@ #include "import.h" #include "aggregate.h" -#if DMDV2 +#if CPP_MANGLE /* Do mangling for C++ linkage. * Follows Itanium C++ ABI 1.86 diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/declaration.c --- a/dmd2/declaration.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/declaration.c Tue Sep 08 10:07:56 2009 +0100 @@ -141,7 +141,7 @@ if (isConst()) p = "const"; else if (isInvariant()) - p = "mutable"; + p = "immutable"; else if (storage_class & STCmanifest) p = "enum"; else if (!t->isAssignable()) @@ -639,6 +639,7 @@ onstack = 0; canassign = 0; value = NULL; + rundtor = NULL; #if IN_LLVM aggrIndex = 0; @@ -956,9 +957,7 @@ Expression *e1; e1 = new VarExp(loc, this); e = new AssignExp(loc, e1, e); -#if DMDV2 e->op = TOKconstruct; -#endif e->type = e1->type; // don't type check this, it would fail init = new ExpInitializer(loc, e); return; @@ -979,10 +978,8 @@ { init = getExpInitializer(); } -#if DMDV2 // Default initializer is always a blit op = TOKblit; -#endif } if (init) @@ -1039,7 +1036,7 @@ Expression *e1 = new VarExp(loc, this); Type *t = type->toBasetype(); - if (t->ty == Tsarray) + if (t->ty == Tsarray && !(storage_class & (STCref | STCout))) { ei->exp = ei->exp->semantic(sc); if (!ei->exp->implicitConvTo(type)) @@ -1167,7 +1164,7 @@ e = e->optimize(WANTvalue | WANTinterpret); else e = e->optimize(WANTvalue); - if (e->op == TOKint64 || e->op == TOKstring) + if (e->op == TOKint64 || e->op == TOKstring || e->op == TOKfloat64) { ei->exp = e; // no errors, keep result } diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/declaration.h --- a/dmd2/declaration.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/declaration.h Tue Sep 08 10:07:56 2009 +0100 @@ -261,7 +261,11 @@ Initializer *init; unsigned offset; int noauto; // no auto semantics +#if DMDV2 FuncDeclarations nestedrefs; // referenced by these lexically nested functions +#else + int nestedref; // referenced by a lexically nested function +#endif 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 @@ -269,6 +273,11 @@ Dsymbol *aliassym; // if redone as alias to another symbol Expression *value; // when interpreting, this is the value // (NULL if value not determinable) +#if DMDV2 + VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see + // if the destructor should be run. Used to prevent + // dtor calls on postblitted vars +#endif VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); @@ -285,8 +294,10 @@ int isDataseg(); int isThreadlocal(); int hasPointers(); +#if DMDV2 int canTakeAddressOf(); int needsAutoDtor(); +#endif Expression *callAutoDtor(Scope *sc); ExpInitializer *getExpInitializer(); Expression *getConstInitializer(); @@ -625,6 +636,8 @@ Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments); +#else +enum BUILTIN { }; #endif struct FuncDeclaration : Declaration @@ -718,6 +731,7 @@ void appendExp(Expression *e); void appendState(Statement *s); char *mangle(); + const char *toPrettyChars(); int isMain(); int isWinMain(); int isDllMain(); @@ -734,7 +748,7 @@ virtual int isFinal(); virtual int addPreInvariant(); virtual int addPostInvariant(); - Expression *interpret(InterState *istate, Expressions *arguments); + Expression *interpret(InterState *istate, Expressions *arguments, Expression *thisexp = NULL); void inlineScan(); int canInline(int hasthis, int hdrscan = 0); Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments); @@ -788,12 +802,13 @@ #endif }; +#if DMDV2 FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s, Objects *tiargs, Expression *ethis, Expressions *arguments, int flags); - +#endif struct FuncAliasDeclaration : FuncDeclaration { diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/doc.c --- a/dmd2/doc.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/doc.c Tue Sep 08 10:07:56 2009 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -238,7 +238,7 @@ // Generate predefined macros // Set the title to be the name of the module - { char *p = toPrettyChars(); + { const char *p = toPrettyChars(); Macro::define(¯otable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p)); } diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/dsymbol.c --- a/dmd2/dsymbol.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/dsymbol.c Tue Sep 08 10:07:56 2009 +0100 @@ -169,7 +169,7 @@ return ident ? ident->toChars() : (char *)"__anonymous"; } -char *Dsymbol::toPrettyChars() +const char *Dsymbol::toPrettyChars() { Dsymbol *p; char *s; char *q; @@ -452,10 +452,12 @@ return FALSE; } +#if DMDV2 int Dsymbol::isOverloadable() { return 0; } +#endif LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? { @@ -695,6 +697,7 @@ /********************************* OverloadSet ****************************/ +#if DMDV2 OverloadSet::OverloadSet() : Dsymbol() { @@ -709,6 +712,7 @@ { return "overloadset"; } +#endif /********************************* ScopeDsymbol ****************************/ diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/dsymbol.h --- a/dmd2/dsymbol.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/dsymbol.h Tue Sep 08 10:07:56 2009 +0100 @@ -62,6 +62,7 @@ struct TypeTuple; struct WithStatement; struct LabelDsymbol; +struct ScopeDsymbol; struct TemplateDeclaration; struct TemplateInstance; struct TemplateMixin; @@ -130,7 +131,6 @@ Dsymbol(); Dsymbol(Identifier *); char *toChars(); - char *toPrettyChars(); char *locToChars(); int equals(Object *o); int isAnonymous(); @@ -148,6 +148,7 @@ static Array *arraySyntaxCopy(Array *a); + virtual const char *toPrettyChars(); virtual const char *kind(); virtual Dsymbol *toAlias(); // resolve real symbol virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum); @@ -173,7 +174,9 @@ virtual int isExport(); // is Dsymbol exported? virtual int isImportedSymbol(); // is Dsymbol imported? virtual int isDeprecated(); // is Dsymbol deprecated? +#if DMDV2 virtual int isOverloadable(); +#endif 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? @@ -322,6 +325,7 @@ // Overload Sets +#if DMDV2 struct OverloadSet : Dsymbol { Dsymbols a; // array of Dsymbols @@ -331,6 +335,7 @@ OverloadSet *isOverloadSet() { return this; } const char *kind(); }; +#endif // Table of Dsymbol's diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/expression.c --- a/dmd2/expression.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/expression.c Tue Sep 08 10:07:56 2009 +0100 @@ -3235,7 +3235,7 @@ e = resolveProperties(sc, e); if (i >= nfields) { error("more initializers than fields of %s", sd->toChars()); - break; + return new ErrorExp(); } Dsymbol *s = (Dsymbol *)sd->fields.data[i]; VarDeclaration *v = s->isVarDeclaration(); @@ -4429,7 +4429,9 @@ else { fd->semantic2(sc); - if (!global.errors) + if (!global.errors || + // need to infer return type + (fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())) { fd->semantic3(sc); @@ -4438,6 +4440,10 @@ } } + // need to infer return type + if (global.errors && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()) + ((TypeFunction *)fd->type)->next = Type::terror; + // Type is a "delegate to" or "pointer to" the function literal if (fd->isNested()) { @@ -4788,6 +4794,12 @@ goto Lno; tded = targ; break; + + case TOKshared: + if (!targ->isShared()) + goto Lno; + tded = targ; + break; #endif case TOKsuper: @@ -5293,7 +5305,7 @@ } if (global.params.verbose) - printf("file %s\t(%s)\n", (char*)se->string, name); + printf("file %s\t(%s)\n", (char *)se->string, name); { File f(name); if (f.read()) @@ -6219,7 +6231,7 @@ } } -#if DMDV2 +#if 1 /* This recognizes: * foo!(tiargs)(funcargs) */ @@ -6346,7 +6358,7 @@ if (t1->ty == Tstruct) { ad = ((TypeStruct *)t1)->sym; - +#if DMDV2 // First look for constructor if (ad->ctor && arguments && arguments->dim) { @@ -6374,7 +6386,7 @@ e = e->semantic(sc); return e; } - +#endif // No constructor, look for overload of opCall if (search_function(ad, Id::call)) goto L1; // overload of opCall, therefore it's a call @@ -6449,7 +6461,7 @@ f->addPostInvariant() ) { - error("cannot call public/export function %s from immutable", f->toChars()); + error("cannot call public/export function %s from invariant", f->toChars()); } checkDeprecated(sc, f); @@ -6484,19 +6496,27 @@ Type *tthis = ue->e1->type->toBasetype(); if (tthis->ty == Tpointer) tthis = tthis->nextOf()->toBasetype(); +#if 0 // this checking should have been already done if (f->type->isInvariant()) { if (tthis->mod != MODinvariant) - error("%s can only be called on an invariant object", e1->toChars()); + error("%s can only be called with an immutable object", e1->toChars()); + } + else if (f->type->isShared()) + { + if (tthis->mod != MODinvariant && + tthis->mod != MODshared && + tthis->mod != (MODshared | MODconst)) + error("shared %s can only be called with a shared or immutable object", e1->toChars()); } else { if (tthis->mod != 0) { //printf("mod = %x\n", tthis->mod); - error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars()); + error("%s can only be called with a mutable object, not %s", e1->toChars(), tthis->toChars()); } } - +#endif /* Cannot call mutable method on a final struct */ if (tthis->ty == Tstruct && @@ -7586,27 +7606,30 @@ else goto Lerror; + { + Scope *sc2 = sc; if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) { sym = new ArrayScopeSymbol(sc, this); sym->loc = loc; sym->parent = sc->scopesym; - sc = sc->push(sym); + sc2 = sc->push(sym); } if (lwr) - { lwr = lwr->semantic(sc); - lwr = resolveProperties(sc, lwr); - lwr = lwr->implicitCastTo(sc, Type::tsize_t); + { lwr = lwr->semantic(sc2); + lwr = resolveProperties(sc2, lwr); + lwr = lwr->implicitCastTo(sc2, Type::tsize_t); } if (upr) - { upr = upr->semantic(sc); - upr = resolveProperties(sc, upr); - upr = upr->implicitCastTo(sc, Type::tsize_t); - } - - if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) - sc->pop(); + { upr = upr->semantic(sc2); + upr = resolveProperties(sc2, upr); + upr = upr->implicitCastTo(sc2, Type::tsize_t); + } + + if (sc2 != sc) + sc2->pop(); + } if (t->ty == Ttuple) { @@ -8292,6 +8315,15 @@ } } + // Determine if this is an initialization of a reference + int refinit = 0; + if (op == TOKconstruct && e1->op == TOKvar) + { VarExp *ve = (VarExp *)e1; + VarDeclaration *v = ve->var->isVarDeclaration(); + if (v->storage_class & (STCout | STCref)) + refinit = 1; + } + Type *t1 = e1->type->toBasetype(); if (t1->ty == Tfunction) @@ -8313,22 +8345,14 @@ if (e) return e; } - else if (op == TOKconstruct) + else if (op == TOKconstruct && !refinit) { Type *t2 = e2->type->toBasetype(); if (t2->ty == Tstruct && sd == ((TypeStruct *)t2)->sym && sd->cpctor) { /* We have a copy constructor for this */ - if (e2->op == TOKvar || e2->op == TOKstar) - { /* Write as: - * e1.cpctor(e2); - */ - Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0); - e = new CallExp(loc, e, e2); - return e->semantic(sc); - } - else if (e2->op == TOKquestion) + if (e2->op == TOKquestion) { /* Write as: * a ? e1 = b : e1 = c; */ @@ -8340,6 +8364,17 @@ Expression *e = new CondExp(loc, ec->econd, ea1, ea2); return e->semantic(sc); } + else if (e2->op == TOKvar || + e2->op == TOKdotvar || + e2->op == TOKstar || + e2->op == TOKindex) + { /* Write as: + * e1.cpctor(e2); + */ + Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0); + e = new CallExp(loc, e, e2); + return e->semantic(sc); + } } } } @@ -8353,7 +8388,7 @@ } } - if (t1->ty == Tsarray) + if (t1->ty == Tsarray && !refinit) { // Convert e1 to e1[] Expression *e = new SliceExp(e1->loc, e1, NULL, NULL); e1 = e->semantic(sc); @@ -8398,7 +8433,7 @@ { /* Should have already converted e1 => e1[] */ - assert(0); + assert(op == TOKconstruct); //error("cannot assign to static array %s", e1->toChars()); } else if (e1->op == TOKslice) diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/expression.h --- a/dmd2/expression.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/expression.h Tue Sep 08 10:07:56 2009 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -323,6 +323,7 @@ ThisExp(Loc loc); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); int isBool(int result); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int isLvalue(); @@ -361,6 +362,7 @@ NullExp(Loc loc); Expression *semantic(Scope *sc); int isBool(int result); + int isConst(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); MATCH implicitConvTo(Type *t); @@ -620,6 +622,7 @@ Type *newtype, Expressions *arguments); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + Expression *optimize(int result); #if IN_DMD elem *toElem(IRState *irs); #endif @@ -1245,6 +1248,8 @@ int checkSideEffect(int flag); void checkEscape(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); #if IN_DMD elem *toElem(IRState *irs); #endif diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/func.c --- a/dmd2/func.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/func.c Tue Sep 08 10:07:56 2009 +0100 @@ -180,7 +180,7 @@ stc |= STCimmutable; if (type->isConst()) stc |= STCconst; - if (type->isShared()) + if (type->isShared() || storage_class & STCsynchronized) stc |= STCshared; switch (stc & STC_TYPECTOR) { @@ -1199,12 +1199,13 @@ error("expected to return a value of type %s", type->nextOf()->toChars()); else if (!inlineAsm) { +#if DMDV2 int blockexit = fbody ? fbody->blockExit() : BEfallthru; if (f->isnothrow && blockexit & BEthrow) error("'%s' is nothrow yet may throw", toChars()); int offend = blockexit & BEfallthru; - +#endif if (type->nextOf()->ty == Tvoid) { if (offend && isMain()) @@ -1217,10 +1218,11 @@ { if (offend) { Expression *e; - - //warning(loc, "no return exp; or assert(0); at end of function"); +#if DMDV1 + warning(loc, "no return exp; or assert(0); at end of function"); +#else error("no return exp; or assert(0); at end of function"); - +#endif if (global.params.useAssert && !global.params.useInline) { /* Add an assert(0, msg); where the missing return @@ -1412,7 +1414,7 @@ fbody = new CompoundStatement(0, a); -#if IN_LLVM +#if 0 // This seems to have been added in with dmd 2.032, see below // wrap body of synchronized functions in a synchronized statement if (isSynchronized()) { @@ -1450,7 +1452,7 @@ fbody = new CompoundStatement(0, a); } #endif - +#if DMDV2 /* Append destructor calls for parameters as finally blocks. */ if (parameters) @@ -1479,6 +1481,46 @@ } } } +#endif + +#if 1 + if (isSynchronized()) + { /* Wrap the entire function body in a synchronized statement + */ + ClassDeclaration *cd = parent->isClassDeclaration(); + if (cd) + { +#if TARGET_WINDOS + if (/*config.flags2 & CFG2seh &&*/ // always on for WINDOS + !isStatic() && !fbody->usesEH()) + { + /* The back end uses the "jmonitor" hack for syncing; + * no need to do the sync at this level. + */ + } + else +#endif + { + Expression *vsync; + if (isStatic()) + { // The monitor is in the ClassInfo + vsync = new DotIdExp(loc, new DsymbolExp(loc, cd), Id::classinfo); + } + else + { // 'this' is the monitor + vsync = new VarExp(loc, vthis); + } + fbody = new PeelStatement(fbody); // don't redo semantic() + fbody = new SynchronizedStatement(loc, vsync, fbody); + fbody = fbody->semantic(sc2); + } + } + else + { + error("synchronized function %s must be a member of a class", toChars()); + } + } +#endif } sc2->callSuper = 0; @@ -1914,12 +1956,18 @@ { OutBuffer buf; + buf.writeByte('('); if (arguments) { HdrGenState hgs; argExpTypesToCBuffer(&buf, arguments, &hgs); + buf.writeByte(')'); + if (ethis) + ethis->type->modToBuffer(&buf); } + else + buf.writeByte(')'); if (m.last == MATCHnomatch) { @@ -1928,9 +1976,13 @@ tf = (TypeFunction *)type; + OutBuffer buf2; + tf->modToBuffer(&buf2); + //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco); - error(loc, "%s does not match parameter types (%s)", + error(loc, "%s%s is not callable using argument types %s", Argument::argsTypesToChars(tf->parameters, tf->varargs), + buf2.toChars(), buf.toChars()); return m.anyf; // as long as it's not a FuncAliasDeclaration } @@ -2202,6 +2254,13 @@ } } +const char *FuncDeclaration::toPrettyChars() +{ + if (isMain()) + return "D main"; + else + return Dsymbol::toPrettyChars(); +} int FuncDeclaration::isMain() { diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/id.c --- a/dmd2/id.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/id.c Tue Sep 08 10:07:56 2009 +0100 @@ -103,6 +103,7 @@ Identifier *Id::reverse; Identifier *Id::dup; Identifier *Id::idup; +Identifier *Id::property; Identifier *Id::___out; Identifier *Id::___in; Identifier *Id::__int; @@ -180,6 +181,10 @@ Identifier *Id::aaKeys; Identifier *Id::aaValues; Identifier *Id::aaRehash; +Identifier *Id::monitorenter; +Identifier *Id::monitorexit; +Identifier *Id::criticalenter; +Identifier *Id::criticalexit; Identifier *Id::GNU_asm; Identifier *Id::lib; Identifier *Id::msg; @@ -333,6 +338,7 @@ reverse = Lexer::idPool("reverse"); dup = Lexer::idPool("dup"); idup = Lexer::idPool("idup"); + property = Lexer::idPool("property"); ___out = Lexer::idPool("out"); ___in = Lexer::idPool("in"); __int = Lexer::idPool("int"); @@ -410,6 +416,10 @@ aaKeys = Lexer::idPool("_aaKeys"); aaValues = Lexer::idPool("_aaValues"); aaRehash = Lexer::idPool("_aaRehash"); + monitorenter = Lexer::idPool("_d_monitorenter"); + monitorexit = Lexer::idPool("_d_monitorexit"); + criticalenter = Lexer::idPool("_d_criticalenter"); + criticalexit = Lexer::idPool("_d_criticalexit"); GNU_asm = Lexer::idPool("GNU_asm"); lib = Lexer::idPool("lib"); msg = Lexer::idPool("msg"); diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/id.h --- a/dmd2/id.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/id.h Tue Sep 08 10:07:56 2009 +0100 @@ -105,6 +105,7 @@ static Identifier *reverse; static Identifier *dup; static Identifier *idup; + static Identifier *property; static Identifier *___out; static Identifier *___in; static Identifier *__int; @@ -182,6 +183,10 @@ static Identifier *aaKeys; static Identifier *aaValues; static Identifier *aaRehash; + static Identifier *monitorenter; + static Identifier *monitorexit; + static Identifier *criticalenter; + static Identifier *criticalexit; static Identifier *GNU_asm; static Identifier *lib; static Identifier *msg; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/idgen.c --- a/dmd2/idgen.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/idgen.c Tue Sep 08 10:07:56 2009 +0100 @@ -137,6 +137,8 @@ { "dup" }, { "idup" }, + { "property" }, + // For inline assembler { "___out", "out" }, { "___in", "in" }, @@ -232,6 +234,10 @@ { "aaKeys", "_aaKeys" }, { "aaValues", "_aaValues" }, { "aaRehash", "_aaRehash" }, + { "monitorenter", "_d_monitorenter" }, + { "monitorexit", "_d_monitorexit" }, + { "criticalenter", "_d_criticalenter" }, + { "criticalexit", "_d_criticalexit" }, // For pragma's { "GNU_asm" }, diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/impcnvtab.c --- a/dmd2/impcnvtab.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/impcnvtab.c Tue Sep 08 10:07:56 2009 +0100 @@ -2,181 +2,185 @@ #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, -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,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,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,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,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,18,36,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,36,19,36,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,36,20,36,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,36,21,36,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,36,22,36,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,36,23,36,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,36,24,36,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,36,22,36,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,36,23,36,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,36,24,36,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,36,28,36,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,36,29,36,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,36,30,36,36,36,36,36,36,36,36,36, -36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,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,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,36,36,36,36,36,36,36,36,36, -36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,23,24,25,29,30,31,37,20,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,23,24,25,29,30,31,37,21,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,23,24,25,29,30,31,37,22,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,23,24,25,29,30,31,37,23,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,24,24,25,30,30,31,37,24,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,25,25,25,31,31,31,37,25,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,29,29,29,29,29,29,29,29,29,30,31,29,30,31,29,30,31,37,29,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,30,30,30,30,30,30,30,30,30,30,31,30,30,31,30,30,31,37,30,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,37,31,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,33,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, }; 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, -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,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,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,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,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,18,36,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,36,19,36,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,36,20,36,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,36,21,36,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,36,22,36,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,36,23,36,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,36,24,36,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,36,25,36,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,36,26,36,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,36,27,36,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,36,28,36,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,36,29,36,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,36,30,36,36,36,36,36,36,36,36,36, -36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,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,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,36,36,36,36,36,36,36,36,36, -36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,23,24,25,23,24,25,37,20,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,23,24,25,23,24,25,37,21,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,23,24,25,23,24,25,37,22,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,23,24,25,23,24,25,37,23,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,24,24,25,24,24,25,37,24,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,37,25,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,26,26,26,26,26,26,26,26,26,27,28,26,27,28,26,27,28,37,26,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,27,27,27,27,27,27,27,27,27,27,28,27,27,28,27,27,28,37,27,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,37,28,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,29,29,29,29,29,29,29,29,29,30,31,29,30,31,29,30,31,37,29,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,30,30,30,30,30,30,30,30,30,30,31,30,30,31,30,30,31,37,30,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,37,31,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,33,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, }; 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, -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,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,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,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,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,18,36,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,36,19,36,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,36,20,36,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,36,21,36,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,36,22,36,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,36,23,36,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,36,24,36,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,36,22,36,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,36,23,36,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,36,24,36,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,36,22,36,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,36,23,36,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,36,24,36,36,36,36,36,36,36,36,36, -36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,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,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,36,36,36,36,36,36,36,36,36, -36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,31,37,20,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,31,37,21,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,31,37,22,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,33,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, }; 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,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,1,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,0,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,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,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,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,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,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,0,0,1,1,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,0,0,1,1,1,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,0,0,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,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,0,0,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,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,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,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,0,0,1,1,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,0,0,1,1,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,0,0,1,1,1,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,0,0,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/init.c --- a/dmd2/init.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/init.c Tue Sep 08 10:07:56 2009 +0100 @@ -412,15 +412,24 @@ case Tpointer: case Tarray: - edim = dim; - break; + edim = dim; + break; default: assert(0); } } else + { edim = value.dim; + for (size_t i = 0, j = 0; i < value.dim; i++, j++) + { + if (index.data[i]) + j = ((Expression *)index.data[i])->toInteger(); + if (j >= edim) + edim = j + 1; + } + } elements = new Expressions(); elements->setDim(edim); @@ -464,7 +473,7 @@ Lno: delete elements; error(loc, "array initializers as expressions are not allowed"); - return NULL; + return new ErrorExp(); } diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/inline.c --- a/dmd2/inline.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/inline.c Tue Sep 08 10:07:56 2009 +0100 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -870,7 +870,8 @@ condition = condition->inlineScan(iss); if (increment) increment = increment->inlineScan(iss); - body = body->inlineScan(iss); + if (body) + body = body->inlineScan(iss); return this; } @@ -1072,6 +1073,31 @@ if (ie) { +#if DMDV2 + if (vd->type) + { Type *tb = vd->type->toBasetype(); + if (tb->ty == Tstruct) + { StructDeclaration *sd = ((TypeStruct *)tb)->sym; + if (sd->cpctor) + { /* The problem here is that if the initializer is a + * function call that returns a struct S with a cpctor: + * S s = foo(); + * the postblit is done by the return statement in foo() + * in s2ir.c, the intermediate code generator. + * But, if foo() is inlined and now the code looks like: + * S s = x; + * the postblit is not there, because such assignments + * are rewritten as s.cpctor(&x) by the front end. + * So, the inlining won't get the postblit called. + * Work around by not inlining these cases. + * A proper fix would be to move all the postblit + * additions to the front end. + */ + return; + } + } + } +#endif ie->exp = ie->exp->inlineScan(iss); } } @@ -1499,6 +1525,9 @@ inlineNest++; Expression *eb = fbody->doInline(&ids); inlineNest--; +//eb->type->print(); +//eb->print(); +//eb->dump(0); return Expression::combine(e, eb); } diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/interpret.c --- a/dmd2/interpret.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/interpret.c Tue Sep 08 10:07:56 2009 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -34,6 +34,7 @@ Dsymbols vars; // variables used in this function Statement *start; // if !=NULL, start execution at this statement Statement *gotoTarget; // target of EXP_GOTO_INTERPRET result + Expression *localThis; // value of 'this', or NULL if none InterState(); }; @@ -50,11 +51,14 @@ /************************************* * Attempt to interpret a function given the arguments. * Input: - * istate state for calling function (NULL if none) + * istate state for calling function (NULL if none) + * arguments function arguments + * thisarg 'this', if a needThis() function, NULL if not. + * * Return result expression if successful, NULL if not. */ -Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments) +Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) { #if LOG printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars()); @@ -72,7 +76,7 @@ if (cantInterpret || semanticRun == 3) return NULL; - if (needThis() || isNested() || !fbody) + if (!fbody) { cantInterpret = 1; return NULL; } @@ -90,11 +94,13 @@ assert(tb->ty == Tfunction); TypeFunction *tf = (TypeFunction *)tb; Type *tret = tf->next->toBasetype(); - if (tf->varargs /*|| tret->ty == Tvoid*/) + if (tf->varargs) { cantInterpret = 1; + error("Variadic functions are not yet implemented in CTFE"); return NULL; } - + + // Ensure there are no lazy parameters if (tf->parameters) { size_t dim = Argument::dim(tf->parameters); for (size_t i = 0; i < dim; i++) @@ -109,13 +115,20 @@ InterState istatex; istatex.caller = istate; istatex.fd = this; + istatex.localThis = thisarg; Expressions vsave; // place to save previous parameter values size_t dim = 0; + if (needThis() && !thisarg) + { cantInterpret = 1; + // error, no this. Prevent segfault. + error("need 'this' to access member %s", toChars()); + return NULL; + } if (arguments) { dim = arguments->dim; - assert(!dim || parameters->dim == dim); + assert(!dim || (parameters && (parameters->dim == dim))); vsave.setDim(dim); /* Evaluate all the arguments to the function, @@ -144,7 +157,9 @@ } earg = earg->interpret(istate ? istate : &istatex); if (earg == EXP_CANT_INTERPRET) + { cantInterpret = 1; return NULL; + } } eargs.data[i] = earg; } @@ -157,23 +172,36 @@ #if LOG printf("arg[%d] = %s\n", i, earg->toChars()); #endif - if (arg->storageClass & (STCout | STCref)) + if (arg->storageClass & (STCout | STCref) && earg->op==TOKvar) { /* Bind out or ref parameter to the corresponding * variable v2 */ - if (!istate || earg->op != TOKvar) + if (!istate) + { cantInterpret = 1; + error("%s cannot be by passed by reference at compile time", earg->toChars()); return NULL; // can't bind to non-interpreted vars - + } + // We need to chase down all of the the passed parameters until + // we find something that isn't a TOKvar, then create a variable + // containg that expression. VarDeclaration *v2; while (1) { VarExp *ve = (VarExp *)earg; v2 = ve->var->isVarDeclaration(); if (!v2) + { cantInterpret = 1; return NULL; + } if (!v2->value || v2->value->op != TOKvar) break; + if (((VarExp *)v2->value)->var->isStaticStructInitDeclaration()) + { // This can happen if v is a struct initialized to + // 0 using an __initZ StaticStructInitDeclaration from + // TypeStruct::defaultInit() + break; // eg default-initialized variable + } earg = v2->value; } @@ -191,8 +219,7 @@ } } else - { /* Value parameters - */ + { // Value parameters and non-trivial references v->value = earg; } #if LOG @@ -200,11 +227,22 @@ #endif } } + // Don't restore the value of 'this' upon function return + if (needThis() && thisarg->op==TOKvar) { + VarDeclaration *thisvar = ((VarExp *)(thisarg))->var->isVarDeclaration(); + for (size_t i = 0; i < istate->vars.dim; i++) + { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; + if (v == thisvar) + { istate->vars.data[i] = NULL; + break; + } + } + } /* Save the values of the local variables used */ Expressions valueSaves; - if (istate) + if (istate && !isNested()) { //printf("saving local variables...\n"); valueSaves.setDim(istate->vars.dim); @@ -220,7 +258,6 @@ } Expression *e = NULL; - while (1) { e = fbody->interpret(&istatex); @@ -246,7 +283,6 @@ else break; } - /* Restore the parameter values */ for (size_t i = 0; i < dim; i++) @@ -255,7 +291,7 @@ v->value = (Expression *)vsave.data[i]; } - if (istate) + if (istate && !isNested()) { /* Restore the variable values */ @@ -268,7 +304,6 @@ } } } - return e; } @@ -478,7 +513,7 @@ return e; if (e == EXP_BREAK_INTERPRET) return NULL; - if (e != EXP_CONTINUE_INTERPRET) + if (e && e != EXP_CONTINUE_INTERPRET) return e; } @@ -758,7 +793,7 @@ while (1) { - e = Cmp(TOKlt, key->value->type, key->value, upr); + e = Cmp(TOKlt, key->value->type, key->value, eupr); if (e == EXP_CANT_INTERPRET) break; if (e->isBool(TRUE) == FALSE) @@ -773,19 +808,23 @@ { e = NULL; break; } - e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); - if (e == EXP_CANT_INTERPRET) + if (e == NULL || e == EXP_CONTINUE_INTERPRET) + { e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); + if (e == EXP_CANT_INTERPRET) + break; + key->value = e; + } + else break; - key->value = e; } } else // TOKforeach_reverse { key->value = eupr; - while (1) + do { - e = Cmp(TOKgt, key->value->type, key->value, lwr); + e = Cmp(TOKgt, key->value->type, key->value, elwr); if (e == EXP_CANT_INTERPRET) break; if (e->isBool(TRUE) == FALSE) @@ -805,7 +844,7 @@ { e = NULL; break; } - } + } while (e == NULL || e == EXP_CONTINUE_INTERPRET); } key->value = keysave; return e; @@ -946,6 +985,14 @@ printf("type = %s\n", type->toChars()); dump(0); #endif + error("Cannot interpret %s at compile time", toChars()); + return EXP_CANT_INTERPRET; +} + +Expression *ThisExp::interpret(InterState *istate) +{ + if (istate->localThis) + return istate->localThis->interpret(istate); return EXP_CANT_INTERPRET; } @@ -995,7 +1042,7 @@ if (v) { #if DMDV2 - if ((v->isConst() || v->isInvariant()) && v->init && !v->value) + if ((v->isConst() || v->isInvariant() || v->storage_class & STCmanifest) && v->init && !v->value) #else if (v->isConst() && v->init) #endif @@ -1005,7 +1052,11 @@ } else { e = v->value; - if (!e) + if (v->isDataseg()) + { error(loc, "static variable %s cannot be read at compile time", v->toChars()); + e = EXP_CANT_INTERPRET; + } + else if (!e) error(loc, "variable %s is used before initialization", v->toChars()); else if (e != EXP_CANT_INTERPRET) e = e->interpret(istate); @@ -1064,6 +1115,8 @@ declaration->isTemplateMixin() || declaration->isTupleDeclaration()) { // These can be made to work, too lazy now + error("Declaration %s is not yet implemented in CTFE", toChars()); + e = EXP_CANT_INTERPRET; } else @@ -1071,7 +1124,7 @@ e = NULL; } #if LOG - printf("-DeclarationExp::interpret(): %p\n", e); + printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e); #endif return e; } @@ -1261,7 +1314,9 @@ /* We don't know how to deal with overlapping fields */ if (sd->hasUnions) - return EXP_CANT_INTERPRET; + { error("Unions with overlapping fields are not yet supported in CTFE"); + return EXP_CANT_INTERPRET; + } if (elements) { @@ -1433,6 +1488,98 @@ BIN_INTERPRET2(Identity) BIN_INTERPRET2(Cmp) +/* Helper functions for BinExp::interpretAssignCommon + */ + +/*************************************** + * Duplicate the elements array, then set field 'indexToChange' = newelem. + */ +Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, void *newelem) +{ + Expressions *expsx = new Expressions(); + expsx->setDim(oldelems->dim); + for (size_t j = 0; j < expsx->dim; j++) + { + if (j == indexToChange) + expsx->data[j] = newelem; + else + expsx->data[j] = oldelems->data[j]; + } + return expsx; +} + +/*************************************** + * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$] + */ +Expressions *spliceElements(Expressions *oldelems, + Expressions *newelems, size_t insertpoint) +{ + Expressions *expsx = new Expressions(); + expsx->setDim(oldelems->dim); + for (size_t j = 0; j < expsx->dim; j++) + { + if (j >= insertpoint && j < insertpoint + newelems->dim) + expsx->data[j] = newelems->data[j - insertpoint]; + else + expsx->data[j] = oldelems->data[j]; + } + return expsx; +} + +/****************************** + * Create an array literal consisting of 'elem' duplicated 'dim' times. + */ +ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, + Expression *elem, size_t dim) +{ + Expressions *elements = new Expressions(); + elements->setDim(dim); + for (size_t i = 0; i < dim; i++) + elements->data[i] = elem; + ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); + ae->type = type; + return ae; +} + + +/******************************** + * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp. + */ +StructLiteralExp *createDefaultInitStructLiteral(Loc loc, StructDeclaration *sym) +{ + Expressions *structelems = new Expressions(); + structelems->setDim(sym->fields.dim); + for (size_t j = 0; j < structelems->dim; j++) + { + structelems->data[j] = ((VarDeclaration *)(sym->fields.data[j]))->type->defaultInit(); + } + StructLiteralExp *structinit = new StructLiteralExp(loc, sym, structelems); + // Why doesn't the StructLiteralExp constructor do this, when + // sym->type != NULL ? + structinit->type = sym->type; + return structinit; +} + +/******************************** + * Add v to the istate list, unless it already exists there. + */ +void addVarToInterstate(InterState *istate, VarDeclaration *v) +{ + if (!v->isParameter()) + { + for (size_t i = 0; 1; i++) + { + if (i == istate->vars.dim) + { istate->vars.push(v); + //printf("\tadding %s to istate\n", v->toChars()); + break; + } + if (v == (VarDeclaration *)istate->vars.data[i]) + break; + } + } +} + Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) { #if LOG @@ -1453,7 +1600,40 @@ Expression *e2 = this->e2->interpret(istate); if (e2 == EXP_CANT_INTERPRET) return e2; + + // Chase down rebinding of out and ref. + if (e1->op == TOKvar) + { + VarExp *ve = (VarExp *)e1; + VarDeclaration *v = ve->var->isVarDeclaration(); + if (v && v->value && v->value->op == TOKvar) + { + VarExp *ve2 = (VarExp *)v->value; + if (ve2->var->isStaticStructInitDeclaration()) + { // This can happen if v is a struct initialized to + // 0 using an __initZ StaticStructInitDeclaration from + // TypeStruct::defaultInit() + } + else + e1 = v->value; + } + else if (v && v->value && (v->value->op==TOKindex || v->value->op == TOKdotvar)) + { + // It is no longer be a TOKvar, eg when a[4] is passed by ref. + e1 = v->value; + } + } + // To reduce code complexity of handling dotvar expressions, + // extract the aggregate now. + Expression *aggregate; + if (e1->op == TOKdotvar) { + aggregate = ((DotVarExp *)e1)->e1; + // Get rid of 'this'. + if (aggregate->op == TOKthis && istate->localThis) + aggregate = istate->localThis; + } + /* Assignment to variable of the form: * v = e2 */ @@ -1461,25 +1641,14 @@ { VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); + assert(v); + if (v && v->isDataseg()) + { // Can't modify global or static data + error("%s cannot be modified at compile time", v->toChars()); + return EXP_CANT_INTERPRET; + } if (v && !v->isDataseg()) { - /* Chase down rebinding of out and ref - */ - if (v->value && v->value->op == TOKvar) - { - VarExp *ve2 = (VarExp *)v->value; - if (ve2->var->isStaticStructInitDeclaration()) - { - /* This can happen if v is a struct initialized to - * 0 using an StaticStructInitDeclaration from - * TypeStruct::defaultInit() - */ - } - else - v = ve2->var->isVarDeclaration(); - assert(v); - } - Expression *ev = v->value; if (fp && !ev) { error("variable %s is used before initialization", v->toChars()); @@ -1496,35 +1665,43 @@ } e2 = Cast(v->type, v->type, e2); } - if (e2 != EXP_CANT_INTERPRET) - { - if (!v->isParameter()) - { - for (size_t i = 0; 1; i++) - { - if (i == istate->vars.dim) - { istate->vars.push(v); - //printf("\tadding %s to istate\n", v->toChars()); - break; - } - if (v == (VarDeclaration *)istate->vars.data[i]) - break; - } - } - v->value = e2; - e = Cast(type, type, post ? ev : e2); - } + if (e2 == EXP_CANT_INTERPRET) + return e2; + + addVarToInterstate(istate, v); + v->value = e2; + e = Cast(type, type, post ? ev : e2); } } + else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) + { // eg v.u.var = e2, v[3].u.var = e2, etc. + error("Nested struct assignment %s is not yet supported in CTFE", toChars()); + } /* Assignment to struct member of the form: * v.var = e2 */ - else if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKvar) - { VarExp *ve = (VarExp *)((DotVarExp *)e1)->e1; - VarDeclaration *v = ve->var->isVarDeclaration(); + else if (e1->op == TOKdotvar && aggregate->op == TOKvar) + { VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration(); if (v->isDataseg()) + { // Can't modify global or static data + error("%s cannot be modified at compile time", v->toChars()); return EXP_CANT_INTERPRET; + } else { + // Chase down rebinding of out and ref + if (v->value && v->value->op == TOKvar) + { + VarExp *ve2 = (VarExp *)v->value; + if (ve2->var->isStaticStructInitDeclaration()) + { // This can happen if v is a struct initialized to + // 0 using an __initZ StaticStructInitDeclaration from + // TypeStruct::defaultInit() + } + else + v = ve2->var->isVarDeclaration(); + assert(v); + } + } if (fp && !v->value) { error("variable %s is used before initialization", v->toChars()); return e; @@ -1561,30 +1738,11 @@ if (e2 == EXP_CANT_INTERPRET) return e2; - if (!v->isParameter()) - { - for (size_t i = 0; 1; i++) - { - if (i == istate->vars.dim) - { istate->vars.push(v); - break; - } - if (v == (VarDeclaration *)istate->vars.data[i]) - break; - } - } + addVarToInterstate(istate, v); /* Create new struct literal reflecting updated fieldi */ - Expressions *expsx = new Expressions(); - expsx->setDim(se->elements->dim); - for (size_t j = 0; j < expsx->dim; j++) - { - if (j == fieldi) - expsx->data[j] = (void *)e2; - else - expsx->data[j] = se->elements->data[j]; - } + Expressions *expsx = changeOneElement(se->elements, fieldi, e2); v->value = new StructLiteralExp(se->loc, se->sd, expsx); v->value->type = se->type; @@ -1598,7 +1756,10 @@ VarDeclaration *v = soe->var->isVarDeclaration(); if (v->isDataseg()) + { + error("%s cannot be modified at compile time", v->toChars()); return EXP_CANT_INTERPRET; + } if (fp && !v->value) { error("variable %s is used before initialization", v->toChars()); return e; @@ -1623,30 +1784,11 @@ if (e2 == EXP_CANT_INTERPRET) return e2; - if (!v->isParameter()) - { - for (size_t i = 0; 1; i++) - { - if (i == istate->vars.dim) - { istate->vars.push(v); - break; - } - if (v == (VarDeclaration *)istate->vars.data[i]) - break; - } - } + addVarToInterstate(istate, v); /* Create new struct literal reflecting updated fieldi */ - Expressions *expsx = new Expressions(); - expsx->setDim(se->elements->dim); - for (size_t j = 0; j < expsx->dim; j++) - { - if (j == fieldi) - expsx->data[j] = (void *)e2; - else - expsx->data[j] = se->elements->data[j]; - } + Expressions *expsx = changeOneElement(se->elements, fieldi, e2); v->value = new StructLiteralExp(se->loc, se->sd, expsx); v->value->type = se->type; @@ -1659,9 +1801,23 @@ { IndexExp *ie = (IndexExp *)e1; VarExp *ve = (VarExp *)ie->e1; VarDeclaration *v = ve->var->isVarDeclaration(); - if (!v || v->isDataseg()) + { + error("%s cannot be modified at compile time", v ? v->toChars(): "void"); return EXP_CANT_INTERPRET; + } + if (v->value && v->value->op == TOKvar) + { + VarExp *ve2 = (VarExp *)v->value; + if (ve2->var->isStaticStructInitDeclaration()) + { // This can happen if v is a struct initialized to + // 0 using an __initZ StaticStructInitDeclaration from + // TypeStruct::defaultInit() + } + else + v = ve2->var->isVarDeclaration(); + assert(v); + } if (!v->value) { if (fp) @@ -1679,15 +1835,10 @@ * But we're too lazy at the moment to do it, as that * involves redoing Index() and whoever calls it. */ - Expression *ev = v->type->defaultInit(); + size_t dim = ((TypeSArray *)t)->dim->toInteger(); - Expressions *elements = new Expressions(); - elements->setDim(dim); - for (size_t i = 0; i < dim; i++) - elements->data[i] = (void *)ev; - ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); - ae->type = v->type; - v->value = ae; + v->value = createBlockDuplicatedArrayLiteral(v->type, + v->type->defaultInit(), dim); } else return EXP_CANT_INTERPRET; @@ -1702,9 +1853,20 @@ aae = (AssocArrayLiteralExp *)v->value; else if (v->value->op == TOKstring) se = (StringExp *)v->value; + else if (v->value->op == TOKnull) + { + // This would be a runtime segfault + error("Cannot index null array %s", v->toChars()); + return EXP_CANT_INTERPRET; + } else return EXP_CANT_INTERPRET; + /* Set the $ variable + */ + Expression *ee = ArrayLength(Type::tsize_t, v->value); + if (ee != EXP_CANT_INTERPRET && ie->lengthVar) + ie->lengthVar->value = ee; Expression *index = ie->e2->interpret(istate); if (index == EXP_CANT_INTERPRET) return EXP_CANT_INTERPRET; @@ -1722,34 +1884,14 @@ e2 = Cast(type, type, e2); if (e2 == EXP_CANT_INTERPRET) return e2; - - if (!v->isParameter()) - { - for (size_t i = 0; 1; i++) - { - if (i == istate->vars.dim) - { istate->vars.push(v); - break; - } - if (v == (VarDeclaration *)istate->vars.data[i]) - break; - } - } - + + addVarToInterstate(istate, v); if (ae) { /* Create new array literal reflecting updated elem */ int elemi = index->toInteger(); - Expressions *expsx = new Expressions(); - expsx->setDim(ae->elements->dim); - for (size_t j = 0; j < expsx->dim; j++) - { - if (j == elemi) - expsx->data[j] = (void *)e2; - else - expsx->data[j] = ae->elements->data[j]; - } + Expressions *expsx = changeOneElement(ae->elements, elemi, e2); v->value = new ArrayLiteralExp(ae->loc, expsx); v->value->type = ae->type; } @@ -1812,8 +1954,245 @@ e = Cast(type, type, post ? ev : e2); } + + /* Assignment to struct element in array, of the form: + * a[i].var = e2 + */ + else if (e1->op == TOKdotvar && aggregate->op == TOKindex && + ((IndexExp *)aggregate)->e1->op == TOKvar) + { + IndexExp * ie = (IndexExp *)aggregate; + VarExp *ve = (VarExp *)(ie->e1); + VarDeclaration *v = ve->var->isVarDeclaration(); + if (!v || v->isDataseg()) + { + error("%s cannot be modified at compile time", v ? v->toChars(): "void"); + return EXP_CANT_INTERPRET; + } + Type *t = ve->type->toBasetype(); + ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value; + if (!ae) + { + // assignment to one element in an uninitialized (static) array. + // This is quite difficult, because defaultInit() for a struct is a VarExp, + // not a StructLiteralExp. + Type *t = v->type->toBasetype(); + if (t->ty != Tsarray) + { + error("Cannot index an uninitialized variable"); + return EXP_CANT_INTERPRET; + } + + Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype(); + if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; } + + // Create a default struct literal... + StructDeclaration *sym = ((TypeStruct *)telem)->sym; + StructLiteralExp *structinit = createDefaultInitStructLiteral(v->loc, sym); + + // ... and use to create a blank array literal + size_t dim = ((TypeSArray *)t)->dim->toInteger(); + ae = createBlockDuplicatedArrayLiteral(v->type, structinit, dim); + v->value = ae; + } + if ((Expression *)(ae->elements) == EXP_CANT_INTERPRET) + { + // Note that this would be a runtime segfault + error("Cannot index null array %s", v->toChars()); + return EXP_CANT_INTERPRET; + } + // Set the $ variable + Expression *ee = ArrayLength(Type::tsize_t, v->value); + if (ee != EXP_CANT_INTERPRET && ie->lengthVar) + ie->lengthVar->value = ee; + // Determine the index, and check that it's OK. + Expression *index = ie->e2->interpret(istate); + if (index == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + + int elemi = index->toInteger(); + if (elemi >= ae->elements->dim) + { + error("array index %d is out of bounds %s[0..%d]", elemi, + v->toChars(), ae->elements->dim); + return EXP_CANT_INTERPRET; + } + // Get old element + Expression *vie = (Expression *)(ae->elements->data[elemi]); + if (vie->op != TOKstructliteral) + return EXP_CANT_INTERPRET; + + // Work out which field needs to be changed + StructLiteralExp *se = (StructLiteralExp *)vie; + VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration(); + if (!vf) + return EXP_CANT_INTERPRET; + + int fieldi = se->getFieldIndex(type, vf->offset); + if (fieldi == -1) + return EXP_CANT_INTERPRET; + + Expression *ev = se->getField(type, vf->offset); + if (fp) + e2 = (*fp)(type, ev, e2); + else + e2 = Cast(type, type, e2); + if (e2 == EXP_CANT_INTERPRET) + return e2; + + // Create new struct literal reflecting updated field + Expressions *expsx = changeOneElement(se->elements, fieldi, e2); + Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx); + + // Create new array literal reflecting updated struct elem + ae->elements = changeOneElement(ae->elements, elemi, newstruct); + return ae; + } + /* Slice assignment, initialization of static arrays + * a[] = e + */ + else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar) + { + SliceExp * sexp = (SliceExp *)e1; + VarExp *ve = (VarExp *)(sexp->e1); + VarDeclaration *v = ve->var->isVarDeclaration(); + if (!v || v->isDataseg()) + { + error("%s cannot be modified at compile time", v->toChars()); + return EXP_CANT_INTERPRET; + } + // Chase down rebinding of out and ref + if (v->value && v->value->op == TOKvar) + { + VarExp *ve2 = (VarExp *)v->value; + if (ve2->var->isStaticStructInitDeclaration()) + { // This can happen if v is a struct initialized to + // 0 using an __initZ StaticStructInitDeclaration from + // TypeStruct::defaultInit() + } + else + v = ve2->var->isVarDeclaration(); + assert(v); + } + /* Set the $ variable + */ + Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) + : EXP_CANT_INTERPRET; + if (ee != EXP_CANT_INTERPRET && sexp->lengthVar) + sexp->lengthVar->value = ee; + Expression *upper = NULL; + Expression *lower = NULL; + if (sexp->upr) + { + upper = sexp->upr->interpret(istate); + if (upper == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + } + if (sexp->lwr) + { + lower = sexp->lwr->interpret(istate); + if (lower == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + } + Type *t = v->type->toBasetype(); + size_t dim; + if (t->ty == Tsarray) + dim = ((TypeSArray *)t)->dim->toInteger(); + else if (t->ty == Tarray) + { + if (!v->value || v->value->op == TOKnull) + { + error("cannot assign to null array %s", v->toChars()); + return EXP_CANT_INTERPRET; + } + if (v->value->op == TOKarrayliteral) + dim = ((ArrayLiteralExp *)v->value)->elements->dim; + else if (v->value->op ==TOKstring) + { + error("String slice assignment is not yet supported in CTFE"); + return EXP_CANT_INTERPRET; + } + } + else + { + error("%s cannot be evaluated at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + int upperbound = upper ? upper->toInteger() : dim; + int lowerbound = lower ? lower->toInteger() : 0; + + ArrayLiteralExp *existing; + if (((int)lowerbound < 0) || (upperbound > dim)) + { + error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); + return EXP_CANT_INTERPRET; + } + if (upperbound-lowerbound != dim) + { + // Only modifying part of the array. Must create a new array literal. + // If the existing array is uninitialized (this can only happen + // with static arrays), create it. + if (v->value && v->value->op == TOKarrayliteral) + existing = (ArrayLiteralExp *)v->value; + else + { + // this can only happen with static arrays + existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); + } + } + + if (e2->op == TOKarrayliteral) + { + // Static array assignment from literal + ArrayLiteralExp *ae = (ArrayLiteralExp *)e2; + if (ae->elements->dim != (upperbound - lowerbound)) + { + error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound); + return e; + } + if (upperbound - lowerbound == dim) + v->value = ae; + else + { + // value[] = value[0..lower] ~ ae ~ value[upper..$] + existing->elements = spliceElements(existing->elements, ae->elements, lowerbound); + v->value = existing; + } + return e2; + } + else if (t->nextOf()->ty == e2->type->ty) + { + // Static array block assignment + if (upperbound-lowerbound ==dim) + v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim); + else + { + // value[] = value[0..lower] ~ ae ~ value[upper..$] + existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound); + v->value = existing; + } + return e2; + } + else if (e2->op == TOKstring) + { + StringExp *se = (StringExp *)e2; + // This is problematic. char[8] should be storing + // values as a string literal, not + // as an array literal. Then, for static arrays, we + // could do modifications + // in-place, with a dramatic memory and speed improvement. + error("String slice assignment is not yet supported in CTFE"); + return e2; + } + else + { + error("Slice operation %s cannot be evaluated at compile time", toChars()); + return e; + } + } else { + error("%s cannot be evaluated at compile time", toChars()); #ifdef DEBUG dump(0); #endif @@ -1927,6 +2306,27 @@ #if LOG printf("CallExp::interpret() %s\n", toChars()); #endif + if (e1->op == TOKdotvar) + { + Expression * pthis = ((DotVarExp*)e1)->e1; + FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); + TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; + if (tf) + { // Member function call + if(pthis->op == TOKthis) + pthis = istate->localThis; + Expression *eresult = fd->interpret(istate, arguments, pthis); + if (eresult) + e = eresult; + else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) + e = EXP_VOID_INTERPRET; + else + error("cannot evaluate %s at compile time", toChars()); + return e; + } + error("cannot evaluate %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + } if (e1->op == TOKvar) { FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); @@ -2159,6 +2559,17 @@ #if LOG printf("AssertExp::interpret() %s\n", toChars()); #endif + if( this->e1->op == TOKaddress) + { // Special case: deal with compiler-inserted assert(&this, "null this") + AddrExp *ade = (AddrExp *)this->e1; + if(ade->e1->op == TOKthis && istate->localThis) + return istate->localThis->interpret(istate); + } +if (this->e1->op == TOKthis) +{ + if(istate->localThis) + return istate->localThis->interpret(istate); +} e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; @@ -2227,6 +2638,14 @@ } } } +#if DMDV2 +#else // this is required for D1, where structs return *this instead of 'this'. + else if (e1->op == TOKthis) + { + if(istate->localThis) + return istate->localThis->interpret(istate); + } +#endif #if LOG if (e == EXP_CANT_INTERPRET) printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); @@ -2253,7 +2672,7 @@ e = EXP_CANT_INTERPRET; return e; } - } + } else error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars()); } #if LOG @@ -2282,7 +2701,9 @@ Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) { - //printf("interpret_aaKeys()\n"); +#if LOG + printf("interpret_aaKeys()\n"); +#endif if (!arguments || arguments->dim != 2) return NULL; Expression *earg = (Expression *)arguments->data[0]; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/lexer.c --- a/dmd2/lexer.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/lexer.c Tue Sep 08 10:07:56 2009 +0100 @@ -1160,6 +1160,7 @@ SINGLE(';', TOKsemicolon) SINGLE(':', TOKcolon) SINGLE('$', TOKdollar) + SINGLE('@', TOKat) #undef SINGLE @@ -3088,6 +3089,7 @@ Token::tochars[TOKorass] = "|="; Token::tochars[TOKidentifier] = "identifier"; + Token::tochars[TOKat] = "@"; // For debugging Token::tochars[TOKdotexp] = "dotexp"; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/lexer.h --- a/dmd2/lexer.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/lexer.h Tue Sep 08 10:07:56 2009 +0100 @@ -31,7 +31,7 @@ + - += -= * / % *= /= %= & | ^ &= |= ^= - = ! ~ + = ! ~ @ ++ -- . -> : , ? && || @@ -159,7 +159,8 @@ TOKgshared, TOKline, TOKfile, - TOKshared, + TOKshared, + TOKat, #endif // LDC specific diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/mangle.c --- a/dmd2/mangle.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/mangle.c Tue Sep 08 10:07:56 2009 +0100 @@ -122,7 +122,7 @@ return ident->toChars(); case LINKcpp: -#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS) +#if CPP_MANGLE return cpp_mangle(this); #else // Windows C++ mangling is done by C++ back end diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/mars.c --- a/dmd2/mars.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/mars.c Tue Sep 08 10:07:56 2009 +0100 @@ -98,7 +98,7 @@ "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates."; #endif ; - version = "v2.031"; + version = "v2.032"; #if IN_LLVM ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/mars.h --- a/dmd2/mars.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/mars.h Tue Sep 08 10:07:56 2009 +0100 @@ -95,6 +95,9 @@ #define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer #define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN +// Set if C++ mangling is done by the front end +#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)) + /* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD and * TARGET_SOLARIS, which are * set on the command line via the compiler makefile. diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/mtype.c --- a/dmd2/mtype.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/mtype.c Tue Sep 08 10:07:56 2009 +0100 @@ -198,6 +198,7 @@ sizeTy[i] = sizeof(TypeBasic); sizeTy[Tsarray] = sizeof(TypeSArray); sizeTy[Tarray] = sizeof(TypeDArray); + //sizeTy[Tnarray] = sizeof(TypeNArray); sizeTy[Taarray] = sizeof(TypeAArray); sizeTy[Tpointer] = sizeof(TypePointer); sizeTy[Treference] = sizeof(TypeReference); @@ -216,6 +217,7 @@ mangleChar[Tarray] = 'A'; mangleChar[Tsarray] = 'G'; + mangleChar[Tnarray] = '@'; mangleChar[Taarray] = 'H'; mangleChar[Tpointer] = 'P'; mangleChar[Treference] = 'R'; @@ -1151,6 +1153,16 @@ } } +void Type::modToBuffer(OutBuffer *buf) +{ + if (mod & MODshared) + buf->writestring(" shared"); + if (mod & MODconst) + buf->writestring(" const"); + if (mod & MODinvariant) + buf->writestring(" immutable"); +} + /************************************ */ @@ -1651,6 +1663,12 @@ return next->reliesOnTident(); } +/******************************* + * For TypeFunction, nextOf() can return NULL if the function return + * type is meant to be inferred, and semantic() hasn't yet ben run + * on the function. After semantic(), it must no longer be NULL. + */ + Type *TypeNext::nextOf() { return next; @@ -3251,6 +3269,88 @@ return TRUE; } + +/***************************** TypeNewArray *****************************/ + +#if 0 + +TypeNewArray::TypeNewArray(Type *telement) + : TypeArray(Tnewarray, telement) +{ + sym = NULL; +} + +Type *TypeNewArray::syntaxCopy() +{ + Type *t = next->syntaxCopy(); + if (t == next) + t = this; + else + { t = new TypeNewArray(t); + t->mod = mod; + } + return t; +} + +d_uns64 TypeNewArray::size(Loc loc) +{ + //printf("TypeNewArray::size()\n"); + return PTRSIZE; +} + +unsigned TypeNewArray::alignsize() +{ + return PTRSIZE; +} + +Type *TypeNewArray::semantic(Loc loc, Scope *sc) +{ Type *tn = next; + + tn = next->semantic(loc,sc); + Type *tbn = tn->toBasetype(); + switch (tbn->ty) + { + case Tfunction: + case Tnone: + case Ttuple: + error(loc, "can't have array of %s", tbn->toChars()); + tn = next = tint32; + break; + case Tstruct: + { TypeStruct *ts = (TypeStruct *)tbn; + if (ts->sym->isnested) + error(loc, "cannot have array of inner structs %s", ts->toChars()); + break; + } + } + if (tn->isauto()) + error(loc, "cannot have array of auto %s", tn->toChars()); + + next = tn; + transitive(); + return merge(); +} + +void TypeNewArray::toDecoBuffer(OutBuffer *buf, int flag) +{ + Type::toDecoBuffer(buf, flag); + buf->writeByte('e'); + if (next) + next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod); +} + +void TypeNewArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) +{ + if (mod != this->mod) + { toCBuffer3(buf, hgs, mod); + return; + } + next->toCBuffer2(buf, hgs, this->mod); + buf->writestring("[new]"); +} + +#endif + /***************************** TypeAArray *****************************/ TypeAArray::TypeAArray(Type *t, Type *index) @@ -3774,6 +3874,7 @@ this->inuse = 0; this->isnothrow = false; this->ispure = false; + this->isproperty = false; this->isref = false; #if IN_LLVM @@ -3789,6 +3890,7 @@ t->mod = mod; t->isnothrow = isnothrow; t->ispure = ispure; + t->isproperty = isproperty; t->isref = isref; return t; } @@ -3958,8 +4060,7 @@ assert(0); } buf->writeByte(mc); - - if (ispure || isnothrow || isref) + if (ispure || isnothrow || isproperty || isref) { if (ispure) buf->writestring("Na"); @@ -3967,6 +4068,8 @@ buf->writestring("Nb"); if (isref) buf->writestring("Nc"); + if (isproperty) + buf->writestring("Nd"); } // LDC: if we're not producing a mangle string, add the this @@ -4026,6 +4129,8 @@ buf->writestring("pure "); if (isnothrow) buf->writestring("nothrow "); + if (isproperty) + buf->writestring("@property "); if (isref) buf->writestring("ref "); @@ -4098,17 +4203,14 @@ */ if (mod != this->mod) { - if (mod & MODconst) - buf->writestring(" const"); - if (mod & MODinvariant) - buf->writestring(" immutable"); - if (mod & MODshared) - buf->writestring(" shared"); + modToBuffer(buf); } if (ispure) buf->writestring(" pure"); if (isnothrow) buf->writestring(" nothrow"); + if (isproperty) + buf->writestring(" @property"); if (isref) buf->writestring(" ref"); @@ -6170,7 +6272,7 @@ { if (mod) return Type::toChars(); - return sym->toPrettyChars(); + return (char *)sym->toPrettyChars(); } Type *TypeClass::syntaxCopy() diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/mtype.h --- a/dmd2/mtype.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/mtype.h Tue Sep 08 10:07:56 2009 +0100 @@ -60,9 +60,10 @@ enum ENUMTY { - Tarray, // dynamic array - Tsarray, // static array - Taarray, // associative array + Tarray, // slice array, aka T[] + Tsarray, // static array, aka T[dimension] + Tnarray, // resizable array, aka T[new] + Taarray, // associative array, aka T[type] Tpointer, Treference, Tfunction, @@ -128,7 +129,10 @@ #define MODshared 2 // type is shared char *deco; - /* Note that there is no "shared immutable", because that is just immutable + /* These are cached values that are lazily evaluated by constOf(), invariantOf(), etc. + * They should not be referenced by anybody but mtype.c. + * They can be NULL if not lazily evaluated yet. + * Note that there is no "shared immutable", because that is just immutable */ Type *cto; // MODconst ? mutable version of this type : const version @@ -242,7 +246,8 @@ virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod); -#if POSIX + void modToBuffer(OutBuffer *buf); +#if CPP_MANGLE virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif virtual int isintegral(); @@ -359,7 +364,7 @@ Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); char *toChars(); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif int isintegral(); @@ -413,7 +418,7 @@ TypeInfoDeclaration *getTypeInfoDeclaration(); Expression *toExpression(); int hasPointers(); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -443,7 +448,7 @@ MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -472,7 +477,7 @@ int hasPointers(); MATCH implicitConvTo(Type *to); MATCH constConv(Type *to); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -500,7 +505,7 @@ TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -519,7 +524,7 @@ Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *defaultInit(Loc loc); int isZeroInit(Loc loc); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif }; @@ -539,6 +544,7 @@ // 2: T t ...) style for variable number of arguments bool isnothrow; // true: nothrow bool ispure; // true: pure + bool isproperty; // can be called without parentheses bool isref; // true: returns a reference enum LINK linkage; // calling convention @@ -553,7 +559,7 @@ MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); Type *reliesOnTident(); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif bool parameterEscapes(Argument *p); @@ -591,7 +597,7 @@ TypeInfoDeclaration *getTypeInfoDeclaration(); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); int hasPointers(); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -697,7 +703,7 @@ MATCH implicitConvTo(Type *to); MATCH constConv(Type *to); Type *toHeadMutable(); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -738,7 +744,7 @@ MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -784,7 +790,7 @@ TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); Type *toHeadMutable(); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -821,7 +827,7 @@ #if DMDV2 Type *toHeadMutable(); MATCH constConv(Type *to); -#if POSIX +#if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif #endif diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/optimize.c --- a/dmd2/optimize.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/optimize.c Tue Sep 08 10:07:56 2009 +0100 @@ -86,6 +86,8 @@ e = ei->syntaxCopy(); e = e->semantic(v->scope); e = e->implicitCastTo(v->scope, v->type); + // enabling this line causes test22 in test suite to fail + //ei->type = e->type; v->scope = NULL; v->inuse--; } @@ -426,11 +428,50 @@ return this; } +Expression *NewExp::optimize(int result) +{ + if (thisexp) + thisexp = thisexp->optimize(WANTvalue); + + // Optimize parameters + if (newargs) + { + for (size_t i = 0; i < newargs->dim; i++) + { Expression *e = (Expression *)newargs->data[i]; + + e = e->optimize(WANTvalue); + newargs->data[i] = (void *)e; + } + } + + if (arguments) + { + for (size_t i = 0; i < arguments->dim; i++) + { Expression *e = (Expression *)arguments->data[i]; + + e = e->optimize(WANTvalue); + arguments->data[i] = (void *)e; + } + } + return this; +} + Expression *CallExp::optimize(int result) { //printf("CallExp::optimize(result = %d) %s\n", result, toChars()); Expression *e = this; + // Optimize parameters + if (arguments) + { + for (size_t i = 0; i < arguments->dim; i++) + { Expression *e = (Expression *)arguments->data[i]; + + e = e->optimize(WANTvalue); + arguments->data[i] = (void *)e; + } + } + e1 = e1->optimize(result); if (e1->op == TOKvar) { @@ -792,7 +833,8 @@ e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = this; - if (this->e1->isConst() && this->e2->isConst()) + if ((this->e1->isConst() && this->e2->isConst()) || + (this->e1->op == TOKnull && this->e2->op == TOKnull)) { e = Identity(op, type, this->e1, this->e2); } diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/parse.c --- a/dmd2/parse.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/parse.c Tue Sep 08 10:07:56 2009 +0100 @@ -2266,7 +2266,7 @@ nextToken(); arguments = parseParameters(&varargs); while (1) - { // Postfixes of 'pure' or 'nothrow' + { // Postfixes if (token.value == TOKpure) ispure = true; else if (token.value == TOKnothrow) @@ -2433,6 +2433,22 @@ ((TypeFunction *)tf)->ispure = 1; nextToken(); continue; + + case TOKat: + nextToken(); + if (token.value != TOKidentifier) + { error("attribute identifier expected"); + nextToken(); + continue; + } + Identifier *id = token.ident; + if (id == Id::property) + ((TypeFunction *)tf)->ispure = 1; + else + error("valid attribute identifiers are property, not %s", id->toChars()); + nextToken(); + continue; + } break; } @@ -4361,6 +4377,10 @@ case TOKnothrow: t = peek(t); continue; + case TOKat: + t = peek(t); // skip '@' + t = peek(t); // skip identifier + continue; default: break; } diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/root/response.c --- a/dmd2/root/response.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/root/response.c Tue Sep 08 10:07:56 2009 +0100 @@ -14,16 +14,13 @@ #include #include -#if !__DMC__ -#include -#endif - #if _WIN32 #include #include #endif #if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 +#include #include #include #include diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/root/root.c --- a/dmd2/root/root.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/root/root.c Tue Sep 08 10:07:56 2009 +0100 @@ -409,10 +409,12 @@ continue; #endif +#if 0 case ' ': case '\t': // tabs in filenames? if (!instring) // if not in string break; // treat as end of path +#endif default: buf.writeByte(c); continue; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/statement.c --- a/dmd2/statement.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/statement.c Tue Sep 08 10:07:56 2009 +0100 @@ -29,6 +29,12 @@ #include "template.h" #include "attrib.h" +#if IN_LLVM +#include "gen/tollvm.h" +#elif IN_DMD +extern int os_critsecsize(); +#endif + /******************************** Statement ***************************/ Statement::Statement(Loc loc) @@ -182,6 +188,22 @@ } +/******************************** PeelStatement ***************************/ + +PeelStatement::PeelStatement(Statement *s) + : Statement(s->loc) +{ + this->s = s; +} + +Statement *PeelStatement::semantic(Scope *sc) +{ + /* "peel" off this wrapper, and don't run semantic() + * on the result. + */ + return s; +} + /******************************** ExpStatement ***************************/ ExpStatement::ExpStatement(Loc loc, Expression *exp) @@ -344,6 +366,25 @@ if (e) { //printf("dtor is: "); e->print(); +#if 0 + if (v->type->toBasetype()->ty == Tstruct) + { /* Need a 'gate' to turn on/off destruction, + * in case v gets moved elsewhere. + */ + Identifier *id = Lexer::uniqueId("__runDtor"); + ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1)); + VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie); + *sentry = new DeclarationStatement(loc, rd); + v->rundtor = rd; + + /* Rewrite e as: + * rundtor && e + */ + Expression *ve = new VarExp(loc, v->rundtor); + e = new AndAndExp(loc, ve, e); + e->type = Type::tbool; + } +#endif *sfinally = new ExpStatement(loc, e); } } @@ -418,7 +459,12 @@ if (sentry) { sentry = sentry->semantic(sc); - statements->data[i] = sentry; + if (s->isDeclarationStatement()) + { statements->insert(i, sentry); + i++; + } + else + statements->data[i] = sentry; } if (sexception) { @@ -562,7 +608,8 @@ //printf("%s\n", s->toChars()); if (!(result & BEfallthru) && !s->comeFrom()) { - s->warning("statement is not reachable"); + if (s->blockExit() != BEhalt) + s->warning("statement is not reachable"); } result &= ~BEfallthru; @@ -909,46 +956,12 @@ Statement *WhileStatement::semantic(Scope *sc) { -#if 0 - if (condition->op == TOKmatch) - { - /* Rewrite while (condition) body as: - * if (condition) - * do - * body - * while ((_match = _match.opNext), _match); - */ - - Expression *ew = new IdentifierExp(0, Id::_match); - ew = new DotIdExp(0, ew, Id::next); - ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew); - ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0)); - Expression *ev = new IdentifierExp(0, Id::_match); - //ev = new CastExp(0, ev, Type::tvoidptr); - ew = new CommaExp(0, ew, ev); - Statement *sw = new DoStatement(loc, body, ew); - Statement *si = new IfStatement(loc, condition, sw, NULL); - return si->semantic(sc); - } -#endif - - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - condition = condition->optimize(WANTvalue); - condition = condition->checkToBoolean(); - - sc->noctor++; - - Scope *scd = sc->push(); - scd->sbreak = this; - scd->scontinue = this; - if (body) - body = body->semantic(scd); - scd->pop(); - - sc->noctor--; - - return this; + /* Rewrite as a for(;condition;) loop + */ + + Statement *s = new ForStatement(loc, NULL, condition, NULL, body); + s = s->semantic(sc); + return s; } int WhileStatement::hasBreak() @@ -963,11 +976,13 @@ int WhileStatement::usesEH() { + assert(0); return body ? body->usesEH() : 0; } int WhileStatement::blockExit() { + assert(0); //printf("WhileStatement::blockExit(%p)\n", this); int result = BEnone; @@ -998,6 +1013,7 @@ int WhileStatement::comeFrom() { + assert(0); if (body) return body->comeFrom(); return FALSE; @@ -1193,6 +1209,10 @@ if (condition) { if (condition->canThrow()) result |= BEthrow; + if (condition->isBool(TRUE)) + result &= ~BEfallthru; + else if (condition->isBool(FALSE)) + return result; } else result &= ~BEfallthru; // the body must do the exiting @@ -1452,11 +1472,14 @@ for (size_t i = 0; i < dim; i++) { // Declare args Argument *arg = (Argument *)arguments->data[i]; + Type *argtype = arg->type->semantic(loc, sc); VarDeclaration *var; - var = new VarDeclaration(loc, arg->type, arg->ident, NULL); + var = new VarDeclaration(loc, argtype, arg->ident, NULL); var->storage_class |= STCforeach; var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); + if (var->storage_class & (STCref | STCout)) + var->storage_class |= STCnodtor; if (dim == 2 && i == 0) { key = var; //var->storage_class |= STCfinal; @@ -1471,20 +1494,68 @@ var->storage_class |= STCconst; } } -#if 1 +#if 0 DeclarationExp *de = new DeclarationExp(loc, var); de->semantic(sc); -#else - var->semantic(sc); - if (!sc->insert(var)) - error("%s already defined", var->ident->toChars()); #endif } - sc->sbreak = this; - sc->scontinue = this; - body = body->semantic(sc); - +#if 1 + { + /* Convert to a ForStatement + * foreach (key, value; a) body => + * for (T[] tmp = a[], size_t key; key < tmp.length; ++key) + * { T value = tmp[k]; body } + * + * foreach_reverse (key, value; a) body => + * for (T[] tmp = a[], size_t key = tmp.length; key--; ) + * { T value = tmp[k]; body } + */ + Identifier *id = Lexer::uniqueId("__aggr"); + ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL)); + VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie); + + Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length); + + if (!key) + { + Identifier *id = Lexer::uniqueId("__key"); + key = new VarDeclaration(loc, Type::tsize_t, id, NULL); + } + if (op == TOKforeach_reverse) + key->init = new ExpInitializer(loc, tmp_length); + else + key->init = new ExpInitializer(loc, new IntegerExp(0)); + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + Statement *forinit = new CompoundDeclarationStatement(loc, cs); + + Expression *cond; + if (op == TOKforeach_reverse) + // key-- + cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); + else + // key < tmp.length + cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length); + + Expression *increment = NULL; + if (op == TOKforeach) + // key += 1 + increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); + + // T value = tmp[key]; + value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); + Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value)); + + body = new CompoundStatement(loc, ds, body); + + ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); + s = fs->semantic(sc); + break; + } +#else if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst) { if (aggr->op == TOKstring) @@ -1494,20 +1565,23 @@ tab->toChars(), value->type->toChars()); } - if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) + if (key) { if (global.params.is64bit) { if (key->type->ty != Tint64 && key->type->ty != Tuns64) error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); } - else - error("foreach: key type must be int or uint, not %s", key->type->toChars()); + + if (key->storage_class & (STCout | STCref)) + error("foreach: key cannot be out or ref"); } - if (key && key->storage_class & (STCout | STCref)) - error("foreach: key cannot be out or ref"); + sc->sbreak = this; + sc->scontinue = this; + body = body->semantic(sc); break; +#endif case Taarray: if (!checkForArgTypes()) @@ -1745,12 +1819,14 @@ keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); exps->push(new IntegerExp(0, keysize, Type::tsize_t)); +#if IN_LLVM // LDC paint delegate argument to the type runtime expects if (!fldeTy->equals(flde->type)) { flde = new CastExp(loc, flde, flde->type); flde->type = fldeTy; } +#endif exps->push(flde); e = new CallExp(loc, ec, exps); e->type = Type::tindex; // don't run semantic() on e @@ -2055,6 +2131,55 @@ lwr = ea.e1; upr = ea.e2; } +#if 1 + /* Convert to a for loop: + * foreach (key; lwr .. upr) => + * for (auto key = lwr, auto tmp = upr; key < tmp; ++key) + * + * foreach_reverse (key; lwr .. upr) => + * for (auto tmp = lwr, auto key = upr; key-- > tmp;) + */ + + ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); + key = new VarDeclaration(loc, arg->type, arg->ident, ie); + + Identifier *id = Lexer::uniqueId("__limit"); + ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); + VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie); + + Statements *cs = new Statements(); + // Keep order of evaluation as lwr, then upr + if (op == TOKforeach) + { + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + } + else + { + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + } + Statement *forinit = new CompoundDeclarationStatement(loc, cs); + + Expression *cond; + if (op == TOKforeach_reverse) + { // key-- > tmp + cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); + cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp)); + } + else + // key < tmp + cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp)); + + Expression *increment = NULL; + if (op == TOKforeach) + // key += 1 + increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); + + ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); + s = fs->semantic(sc); + return s; +#else if (!arg->type->isscalar()) error("%s is not a scalar type", arg->type->toChars()); @@ -2078,6 +2203,7 @@ sc->noctor--; sc->pop(); return s; +#endif } int ForeachRangeStatement::hasBreak() @@ -2092,11 +2218,14 @@ int ForeachRangeStatement::usesEH() { + assert(0); return body->usesEH(); } int ForeachRangeStatement::blockExit() -{ int result = BEfallthru; +{ + assert(0); + int result = BEfallthru; if (lwr && lwr->canThrow()) result |= BEthrow; @@ -2113,6 +2242,7 @@ int ForeachRangeStatement::comeFrom() { + assert(0); if (body) return body->comeFrom(); return FALSE; @@ -2462,7 +2592,7 @@ { sc->func->allowInlining = true; } - +#if DMDV2 else if (ident == Id::startaddress) { if (!args || args->dim != 1) @@ -2483,6 +2613,7 @@ return this; } } +#endif else error("unrecognized pragma(%s)", ident->toChars()); @@ -2657,7 +2788,7 @@ ; } - if (!sc->sw->sdefault) + if (!sc->sw->sdefault && !isFinal) { hasNoDefault = 1; warning("switch statement has no default"); @@ -3693,21 +3824,145 @@ Statement *SynchronizedStatement::semantic(Scope *sc) { if (exp) - { ClassDeclaration *cd; - + { exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - cd = exp->type->isClassHandle(); + ClassDeclaration *cd = exp->type->isClassHandle(); if (!cd) error("can only synchronize on class objects, not '%s'", exp->type->toChars()); else if (cd->isInterfaceDeclaration()) - { Type *t = new TypeIdentifier(0, Id::Object); + { /* Cast the interface to an object, as the object has the monitor, + * not the interface. + */ + Type *t = new TypeIdentifier(0, Id::Object); t = t->semantic(0, sc); exp = new CastExp(loc, exp, t); exp = exp->semantic(sc); } + +#if 1 + /* Rewrite as: + * auto tmp = exp; + * _d_monitorenter(tmp); + * try { body } finally { _d_monitorexit(tmp); } + */ + Identifier *id = Lexer::uniqueId("__sync"); + ExpInitializer *ie = new ExpInitializer(loc, exp); + VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie); + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + +#if IN_LLVM + // LDC: Build args + Arguments* args = new Arguments; + args->push(new Argument(STCin, ClassDeclaration::object->type, NULL, NULL)); + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorenter); +#else + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter); +#endif + Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp)); + e->type = Type::tvoid; // do not run semantic on e + cs->push(new ExpStatement(loc, e)); + +#if IN_LLVM + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit); +#else + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit); +#endif + e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp)); + e->type = Type::tvoid; // do not run semantic on e + Statement *s = new ExpStatement(loc, e); + s = new TryFinallyStatement(loc, body, s); + cs->push(s); + + s = new CompoundStatement(loc, cs); + return s->semantic(sc); +#endif } +#if 1 + else + { /* Generate our own critical section, then rewrite as: + * __gshared byte[CriticalSection.sizeof] critsec; + * _d_criticalenter(critsec.ptr); + * try { body } finally { _d_criticalexit(critsec.ptr); } + */ + Identifier *id = Lexer::uniqueId("__critsec"); +#if IN_LLVM + Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + getTypePaddedSize(DtoMutexType()))); +#elif IN_DMD + Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize())); +#endif + VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); + tmp->storage_class |= STCgshared | STCstatic; + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + +#if IN_LLVM + // LDC: Build args (based on the code from gen/tollvm.cpp:DtoMutexType() + Arguments* args = new Arguments; + StructDeclaration* dcs = new StructDeclaration(loc, id); + if (global.params.os == OSWindows) + { + dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + } + else if (global.params.os == OSFreeBSD) + { + dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL)); + } + else + { + // pthread_fastlock + StructDeclaration* pfl = new StructDeclaration(loc, id); + pfl->scope->linkage = LINKc; + pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL)); + pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + + // pthread_mutex + StructDeclaration* pm = new StructDeclaration(loc, id); + pm->scope->linkage = LINKc; + pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + pm->addField(pm->scope, new VarDeclaration(loc, Type::tvoidptr, id, NULL)); + pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + pm->addField(pm->scope, new VarDeclaration(loc, pfl->type, id, NULL)); + + // D_CRITICAL_SECTION + dcs->scope->linkage = LINKc; + dcs->addField(dcs->scope, new VarDeclaration(loc, dcs->type->pointerTo(), id, NULL)); + dcs->addField(dcs->scope, new VarDeclaration(loc, pm->type, id, NULL)); + } + args->push(new Argument(STCin, dcs->type->pointerTo(), NULL, NULL)); + + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter); +#else + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter); +#endif + Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); + e = e->semantic(sc); + e = new CallExp(loc, new VarExp(loc, fdenter), e); + e->type = Type::tvoid; // do not run semantic on e + cs->push(new ExpStatement(loc, e)); + +#if IN_LLVM + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit); +#else + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit); +#endif + e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); + e = e->semantic(sc); + e = new CallExp(loc, new VarExp(loc, fdexit), e); + e->type = Type::tvoid; // do not run semantic on e + Statement *s = new ExpStatement(loc, e); + s = new TryFinallyStatement(loc, body, s); + cs->push(s); + + s = new CompoundStatement(loc, cs); + return s->semantic(sc); + } +#endif if (body) { Statement* oldScopeExit = sc->enclosingScopeExit; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/statement.h --- a/dmd2/statement.h Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/statement.h Tue Sep 08 10:07:56 2009 +0100 @@ -153,6 +153,14 @@ #endif }; +struct PeelStatement : Statement +{ + Statement *s; + + PeelStatement(Statement *s); + Statement *semantic(Scope *sc); +}; + struct ExpStatement : Statement { Expression *exp; diff -r 4551475bc6b6 -r e4f7b5d9c68a dmd2/template.c --- a/dmd2/template.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/template.c Tue Sep 08 10:07:56 2009 +0100 @@ -1972,14 +1972,21 @@ L2: - for (int i = 0; i < tempinst->tiargs->dim; i++) + for (int i = 0; 1; i++) { //printf("\ttest: tempinst->tiargs[%d]\n", i); + Object *o1; + if (i < tempinst->tiargs->dim) + o1 = (Object *)tempinst->tiargs->data[i]; + else if (i < tempinst->tdtypes.dim && i < tp->tempinst->tiargs->dim) + // Pick up default arg + o1 = (Object *)tempinst->tdtypes.data[i]; + else + break; + if (i >= tp->tempinst->tiargs->dim) goto Lnomatch; - int j; - Object *o1 = (Object *)tempinst->tiargs->data[i]; Object *o2 = (Object *)tp->tempinst->tiargs->data[i]; Type *t1 = isType(o1); @@ -2005,6 +2012,7 @@ #endif TemplateTupleParameter *ttp; + int j; if (t2 && t2->ty == Tident && i == tp->tempinst->tiargs->dim - 1 && @@ -2119,6 +2127,7 @@ return Type::deduceType(sc, tparam, parameters, dedtypes); Lnomatch: + //printf("no match\n"); return MATCHnomatch; } @@ -4143,7 +4152,7 @@ Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); Tuple *va = isTuple(o); - //printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va); + //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va); if (ta) { buf.writeByte('T'); diff -r 4551475bc6b6 -r e4f7b5d9c68a gen/classes.cpp --- a/gen/classes.cpp Tue Aug 25 21:35:43 2009 +0200 +++ b/gen/classes.cpp Tue Sep 08 10:07:56 2009 +0100 @@ -732,7 +732,11 @@ // class name // code from dmd +#if DMDV2 + const char *name = cd->ident->toChars(); +#else char *name = cd->ident->toChars(); +#endif size_t namelen = strlen(name); if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0)) { diff -r 4551475bc6b6 -r e4f7b5d9c68a gen/tollvm.cpp --- a/gen/tollvm.cpp Tue Aug 25 21:35:43 2009 +0200 +++ b/gen/tollvm.cpp Tue Sep 08 10:07:56 2009 +0100 @@ -874,8 +874,11 @@ opaque->refineAbstractTypeTo(pa.get()); pmutex = isaStruct(pa.get()); - gIR->mutexType = pmutex; - gIR->module->addTypeName("D_CRITICAL_SECTION", pmutex); + if (gIR->module != NULL) + { + gIR->mutexType = pmutex; + gIR->module->addTypeName("D_CRITICAL_SECTION", pmutex); + } return pmutex; }