diff --git a/dmd/cast.c b/dmd/cast.c index 6b187326..b7650c76 100644 --- a/dmd/cast.c +++ b/dmd/cast.c @@ -100,7 +100,12 @@ fflush(stdout); error("cannot implicitly convert expression (%s) of type %s to %s", toChars(), type->toChars(), t->toChars()); - return castTo(sc, t); + return new ErrorExp(); +} + +Expression *ErrorExp::implicitCastTo(Scope *sc, Type *t) +{ + return this; } /******************************************* @@ -746,6 +751,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t) if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid) { error("cannot convert string literal to void*"); + return new ErrorExp(); } se = this; @@ -1115,11 +1121,11 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t) } else if (f->needThis()) { error("no 'this' to create delegate for %s", f->toChars()); - e = new ErrorExp(); + return new ErrorExp(); } else { error("cannot cast from function pointer to delegate"); - e = new ErrorExp(); + return new ErrorExp(); } } else @@ -1577,7 +1583,7 @@ Expression *Expression::integralPromotions(Scope *sc) { case Tvoid: error("void has no value"); - break; + return new ErrorExp(); case Tint8: case Tuns8: diff --git a/dmd/class.c b/dmd/class.c index 3b71a743..55f2fbb8 100644 --- a/dmd/class.c +++ b/dmd/class.c @@ -65,7 +65,7 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla if (id) { // Look for special class names - if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof) + if (id == Id::__sizeof || id == Id::__xalignof || id == Id::mangleof) error("illegal class name"); // BUG: What if this is the wrong TypeInfo, i.e. it is nested? diff --git a/dmd/declaration.c b/dmd/declaration.c index 46874823..6f200c64 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -891,6 +891,9 @@ void VarDeclaration::semantic(Scope *sc) else if (storage_class & STCtemplateparameter) { } + else if (storage_class & STCctfe) + { + } else { AggregateDeclaration *aad = sc->anonAgg; diff --git a/dmd/declaration.h b/dmd/declaration.h index 43ad8e94..c91ac035 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -974,6 +974,7 @@ struct UnitTestDeclaration : FuncDeclaration int addPreInvariant(); int addPostInvariant(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + void toJsonBuffer(OutBuffer *buf); UnitTestDeclaration *isUnitTestDeclaration() { return this; } }; diff --git a/dmd/dsymbol.c b/dmd/dsymbol.c index 9b813112..ac921fdb 100644 --- a/dmd/dsymbol.c +++ b/dmd/dsymbol.c @@ -525,7 +525,7 @@ int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) } if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) { - if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof) + if (ident == Id::__sizeof || ident == Id::__xalignof || ident == Id::mangleof) error(".%s property cannot be redefined", ident->toChars()); } return 1; diff --git a/dmd/expression.c b/dmd/expression.c index 58a1c1b6..112faebe 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -284,6 +284,7 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, */ e1->error("this for %s needs to be type %s not type %s", var->toChars(), ad->toChars(), t->toChars()); + e1 = new ErrorExp(); } } return e1; @@ -371,6 +372,7 @@ Expression *resolveProperties(Scope *sc, Expression *e) else if (e->op == TOKdotexp) { e->error("expression has no value"); + return new ErrorExp(); } } @@ -386,17 +388,19 @@ Expression *resolveProperties(Scope *sc, Expression *e) * Perform semantic() on an array of Expressions. */ -void arrayExpressionSemantic(Expressions *exps, Scope *sc) +Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc) { if (exps) { for (size_t i = 0; i < exps->dim; i++) { Expression *e = (Expression *)exps->data[i]; - - e = e->semantic(sc); - exps->data[i] = (void *)e; + if (e) + { e = e->semantic(sc); + exps->data[i] = (void *)e; + } } } + return exps; } @@ -497,6 +501,12 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt #if DMDV2 /* The type is determined by applying ?: to each pair. */ + /* Still have a problem with: + * ubyte[][] = [ cast(ubyte[])"hello", [1]]; + * which works if the array literal is initialized top down with the ubyte[][] + * type, but fails with this function doing bottom up typing. + */ + //printf("arrayExpressionToCommonType()\n"); IntegerExp integerexp(0); CondExp condexp(0, &integerexp, NULL, NULL); @@ -524,7 +534,9 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt condexp.semantic(sc); exps->data[j0] = (void *)condexp.e1; e = condexp.e2; - t0 = e->type; + j0 = i; + e0 = e; + t0 = e0->type; } } else @@ -573,7 +585,7 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps) printf("1: \n"); #endif arg->error("%s is not an expression", arg->toChars()); - arg = new IntegerExp(arg->loc, 0, Type::tint32); + arg = new ErrorExp(); } arg = resolveProperties(sc, arg); @@ -611,6 +623,7 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e) */ Identifier *idtmp = Lexer::uniqueId("__tmp"); VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e)); + tmp->storage_class |= STCctfe; Expression *ae = new DeclarationExp(loc, tmp); e = new CommaExp(loc, ae, new VarExp(loc, tmp)); e = e->semantic(sc); @@ -630,8 +643,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e) void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments) { - unsigned n; - //printf("functionParameters()\n"); assert(arguments); size_t nargs = arguments ? arguments->dim : 0; @@ -640,7 +651,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum if (nargs > nparams && tf->varargs == 0) error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf->toChars()); - n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) + unsigned n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) int done = 0; for (size_t i = 0; i < n; i++) @@ -667,14 +678,10 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum return; } arg = p->defaultArg; + arg = arg->inlineCopy(sc); #if DMDV2 - if (arg->op == TOKdefault) - { DefaultInitExp *de = (DefaultInitExp *)arg; - arg = de->resolve(loc, sc); - } - else + arg = arg->resolveLoc(loc, sc); // __FILE__ and __LINE__ #endif - arg = arg->copy(); arguments->push(arg); nargs++; } @@ -2130,8 +2137,7 @@ Expression *IdentifierExp::semantic(Scope *sc) error("undefined identifier %s, did you mean %s %s?", ident->toChars(), s->kind(), s->toChars()); else error("undefined identifier %s", ident->toChars()); - type = Type::terror; - return this; + return new ErrorExp(); } char *IdentifierExp::toChars() @@ -5694,12 +5700,11 @@ Expression *DotIdExp::semantic(Scope *sc) return e; } error("undefined identifier %s", toChars()); - type = Type::tvoid; - return this; + return new ErrorExp(); } else if (e1->type->ty == Tpointer && ident != Id::init && ident != Id::__sizeof && - ident != Id::alignof && ident != Id::offsetof && + ident != Id::__xalignof && ident != Id::offsetof && ident != Id::mangleof && ident != Id::stringof) { /* Rewrite: * p.ident diff --git a/dmd/expression.h b/dmd/expression.h index eda63855..939c35af 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -120,7 +120,7 @@ struct Expression : Object virtual void toMangleBuffer(OutBuffer *buf); virtual Expression *toLvalue(Scope *sc, Expression *e); virtual Expression *modifiableLvalue(Scope *sc, Expression *e); - Expression *implicitCastTo(Scope *sc, Type *t); + virtual Expression *implicitCastTo(Scope *sc, Type *t); virtual MATCH implicitConvTo(Type *t); virtual Expression *castTo(Scope *sc, Type *t); virtual void checkEscape(); @@ -155,6 +155,7 @@ struct Expression : Object virtual int inlineCost(InlineCostState *ics); virtual Expression *doInline(InlineDoState *ids); virtual Expression *inlineScan(InlineScanState *iss); + Expression *inlineCopy(Scope *sc); // For operator overloading virtual int isCommutative(); @@ -217,6 +218,7 @@ struct ErrorExp : IntegerExp { ErrorExp(); + Expression *implicitCastTo(Scope *sc, Type *t); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -638,6 +640,18 @@ struct NewAnonClassExp : Expression void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; +#if DMDV2 +struct SymbolExp : Expression +{ + Declaration *var; + int hasOverloads; + + SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads); + + elem *toElem(IRState *irs); +}; +#endif + // Offset from symbol struct SymOffExp : Expression diff --git a/dmd/idgen.c b/dmd/idgen.c index 80469a91..5ef958f0 100644 --- a/dmd/idgen.c +++ b/dmd/idgen.c @@ -43,7 +43,7 @@ Msgtable msgtable[] = { "init" }, { "size" }, { "__sizeof", "sizeof" }, - { "alignof" }, + { "__xalignof", "alignof" }, { "mangleof" }, { "stringof" }, { "tupleof" }, diff --git a/dmd/init.c b/dmd/init.c index 21aed083..da01ee59 100644 --- a/dmd/init.c +++ b/dmd/init.c @@ -341,6 +341,7 @@ void ArrayInitializer::addInit(Expression *index, Initializer *value) Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) { unsigned i; unsigned length; + const unsigned long amax = 0x80000000; //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); if (sem) // if semantic() already run @@ -357,15 +358,13 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) default: error(loc, "cannot use array to initialize %s", type->toChars()); - return this; + goto Lerr; } length = 0; for (i = 0; i < index.dim; i++) - { Expression *idx; - Initializer *val; - - idx = (Expression *)index.data[i]; + { + Expression *idx = (Expression *)index.data[i]; if (idx) { idx = idx->semantic(sc); idx = idx->optimize(WANTvalue | WANTinterpret); @@ -373,19 +372,35 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) length = idx->toInteger(); } - val = (Initializer *)value.data[i]; - val = val->semantic(sc, t->next); + Initializer *val = (Initializer *)value.data[i]; + val = val->semantic(sc, t->nextOf()); value.data[i] = (void *)val; length++; if (length == 0) - error(loc, "array dimension overflow"); + { error(loc, "array dimension overflow"); + goto Lerr; + } if (length > dim) dim = length; } - unsigned long amax = 0x80000000; - if ((unsigned long) dim * t->next->size() >= amax) - error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->next->size()); + if (t->ty == Tsarray) + { + dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); + if (dim > edim) + { + error(loc, "array initializer has %u elements, but array length is %jd", dim, edim); + goto Lerr; + } + } + + if ((unsigned long) dim * t->nextOf()->size() >= amax) + { error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->nextOf()->size()); + goto Lerr; + } return this; + +Lerr: + return new ExpInitializer(loc, new ErrorExp()); } /******************************** @@ -618,11 +633,11 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t) // Look for the case of statically initializing an array // with a single member. if (tb->ty == Tsarray && - !tb->next->equals(exp->type->toBasetype()->next) && - exp->implicitConvTo(tb->next) + !tb->nextOf()->equals(exp->type->toBasetype()->nextOf()) && + exp->implicitConvTo(tb->nextOf()) ) { - t = tb->next; + t = tb->nextOf(); } exp = exp->implicitCastTo(sc, t); diff --git a/dmd/inline.c b/dmd/inline.c index de8dca47..2fb7fc50 100644 --- a/dmd/inline.c +++ b/dmd/inline.c @@ -22,6 +22,7 @@ #include "expression.h" #include "statement.h" #include "mtype.h" +#include "scope.h" /* ========== Compute cost of inlining =============== */ @@ -164,7 +165,10 @@ int VarExp::inlineCost(InlineCostState *ics) int ThisExp::inlineCost(InlineCostState *ics) { #if !IN_LLVM + //printf("ThisExp::inlineCost() %s\n", toChars()); FuncDeclaration *fd = ics->fd; + if (!fd) + return COST_MAX; if (!ics->hdrscan) if (fd->isNested() || !ics->hasthis) return COST_MAX; @@ -176,6 +180,8 @@ int SuperExp::inlineCost(InlineCostState *ics) { #if !IN_LLVM FuncDeclaration *fd = ics->fd; + if (!fd) + return COST_MAX; if (!ics->hdrscan) if (fd->isNested() || !ics->hasthis) return COST_MAX; @@ -205,6 +211,7 @@ int StructLiteralExp::inlineCost(InlineCostState *ics) int FuncExp::inlineCost(InlineCostState *ics) { + //printf("FuncExp::inlineCost()\n"); // This breaks on LDC too, since nested functions have internal linkage // and thus can't be referenced from other objects. // Right now, this makes the function be output to the .obj file twice. @@ -470,10 +477,8 @@ Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids) { Expression *e = (Expression *)a->data[i]; if (e) - { e = e->doInline(ids); - newa->data[i] = (void *)e; - } + newa->data[i] = (void *)e; } } return newa; @@ -1537,4 +1542,31 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A } +/**************************************************** + * Perform the "inline copying" of a default argument for a function parameter. + */ + +Expression *Expression::inlineCopy(Scope *sc) +{ +#if 0 + /* See Bugzilla 2935 for explanation of why just a copy() is broken + */ + return copy(); +#else + InlineCostState ics; + + memset(&ics, 0, sizeof(ics)); + ics.hdrscan = 1; // so DeclarationExp:: will work on 'statics' which are not + int cost = inlineCost(&ics); + if (cost >= COST_MAX) + { error("cannot inline default argument %s", toChars()); + return new ErrorExp(); + } + InlineDoState ids; + memset(&ids, 0, sizeof(ids)); + ids.parent = sc->parent; + Expression *e = doInline(&ids); + return e; +#endif +} diff --git a/dmd/interpret.c b/dmd/interpret.c index 47d7b0d3..9491904d 100644 --- a/dmd/interpret.c +++ b/dmd/interpret.c @@ -323,6 +323,7 @@ Expression *Statement::interpret(InterState *istate) printf("Statement::interpret()\n"); #endif START() + error("Statement %s cannot be interpreted at compile time", this->toChars()); return EXP_CANT_INTERPRET; } @@ -1032,6 +1033,68 @@ Expression *LabelStatement::interpret(InterState *istate) return statement ? statement->interpret(istate) : NULL; } + +Expression *TryCatchStatement::interpret(InterState *istate) +{ +#if LOG + printf("TryCatchStatement::interpret()\n"); +#endif + START() + error("try-catch statements are not yet supported in CTFE"); + return EXP_CANT_INTERPRET; +} + + +Expression *TryFinallyStatement::interpret(InterState *istate) +{ +#if LOG + printf("TryFinallyStatement::interpret()\n"); +#endif + START() + error("try-finally statements are not yet supported in CTFE"); + return EXP_CANT_INTERPRET; +} + +Expression *ThrowStatement::interpret(InterState *istate) +{ +#if LOG + printf("ThrowStatement::interpret()\n"); +#endif + START() + error("throw statements are not yet supported in CTFE"); + return EXP_CANT_INTERPRET; +} + +Expression *OnScopeStatement::interpret(InterState *istate) +{ +#if LOG + printf("OnScopeStatement::interpret()\n"); +#endif + START() + error("scope guard statements are not yet supported in CTFE"); + return EXP_CANT_INTERPRET; +} + +Expression *WithStatement::interpret(InterState *istate) +{ +#if LOG + printf("WithStatement::interpret()\n"); +#endif + START() + error("with statements are not yet supported in CTFE"); + return EXP_CANT_INTERPRET; +} + +Expression *AsmStatement::interpret(InterState *istate) +{ +#if LOG + printf("AsmStatement::interpret()\n"); +#endif + START() + error("asm statements cannot be interpreted at compile time"); + return EXP_CANT_INTERPRET; +} + /******************************** Expression ***************************/ Expression *Expression::interpret(InterState *istate) @@ -1200,8 +1263,8 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) e = v->init->toExpression(); e = e->interpret(istate); } - else // This should never happen - e = v->type->defaultInitLiteral(); + else + e = v->type->defaultInitLiteral(loc); } else { e = v->value; @@ -2059,7 +2122,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) */ if (type->toBasetype()->ty == Tstruct && newval->op == TOKint64) { - newval = type->defaultInitLiteral(); + newval = type->defaultInitLiteral(loc); } newval = Cast(type, type, newval); e = newval; diff --git a/dmd/json.c b/dmd/json.c index d445d862..7db921b0 100644 --- a/dmd/json.c +++ b/dmd/json.c @@ -214,11 +214,17 @@ void AttribDeclaration::toJsonBuffer(OutBuffer *buf) if (d) { + size_t offset = buf->offset; for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = (Dsymbol *)d->data[i]; //printf("AttribDeclaration::toJsonBuffer %s\n", s->toChars()); + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } s->toJsonBuffer(buf); } + JsonRemoveComma(buf); } } @@ -240,6 +246,7 @@ void StaticDtorDeclaration::toJsonBuffer(OutBuffer *buf) { } void ClassInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } void ModuleInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } void TypeInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } +void UnitTestDeclaration::toJsonBuffer(OutBuffer *buf) { } #if DMDV2 void PostBlitDeclaration::toJsonBuffer(OutBuffer *buf) { } #endif @@ -307,19 +314,23 @@ void AggregateDeclaration::toJsonBuffer(OutBuffer *buf) } } - JsonString(buf, Pmembers); - buf->writestring(" : [\n"); - size_t offset = buf->offset; - for (int i = 0; i < members->dim; i++) - { Dsymbol *s = (Dsymbol *)members->data[i]; - if (offset != buf->offset) - { buf->writestring(",\n"); - offset = buf->offset; + if (members) + { + JsonString(buf, Pmembers); + buf->writestring(" : [\n"); + size_t offset = buf->offset; + for (int i = 0; i < members->dim; i++) + { Dsymbol *s = (Dsymbol *)members->data[i]; + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } + s->toJsonBuffer(buf); } - s->toJsonBuffer(buf); + JsonRemoveComma(buf); + buf->writestring("]\n"); } JsonRemoveComma(buf); - buf->writestring("]\n"); buf->writestring("}\n"); } @@ -386,19 +397,23 @@ void EnumDeclaration::toJsonBuffer(OutBuffer *buf) if (memtype) JsonProperty(buf, "base", memtype->toChars()); - JsonString(buf, Pmembers); - buf->writestring(" : [\n"); - size_t offset = buf->offset; - for (int i = 0; i < members->dim; i++) - { Dsymbol *s = (Dsymbol *)members->data[i]; - if (offset != buf->offset) - { buf->writestring(",\n"); - offset = buf->offset; + if (members) + { + JsonString(buf, Pmembers); + buf->writestring(" : [\n"); + size_t offset = buf->offset; + for (int i = 0; i < members->dim; i++) + { Dsymbol *s = (Dsymbol *)members->data[i]; + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } + s->toJsonBuffer(buf); } - s->toJsonBuffer(buf); + JsonRemoveComma(buf); + buf->writestring("]\n"); } JsonRemoveComma(buf); - buf->writestring("]\n"); buf->writestring("}\n"); } diff --git a/dmd/mars.c b/dmd/mars.c index 0fee5e66..2fd589bf 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -63,7 +63,7 @@ Global::Global() copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.058"; + version = "v1.060"; ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; global.structalign = 8; diff --git a/dmd/mtype.c b/dmd/mtype.c index 2ad9ce8e..b5fb873f 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -647,7 +647,7 @@ Expression *Type::getProperty(Loc loc, Identifier *ident) error(loc, ".size property should be replaced with .sizeof"); e = new ErrorExp(); } - else if (ident == Id::alignof) + else if (ident == Id::__xalignof) { e = new IntegerExp(loc, alignsize(), Type::tsize_t); } diff --git a/dmd/parse.c b/dmd/parse.c index c0525f74..3958bb8a 100644 --- a/dmd/parse.c +++ b/dmd/parse.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -122,9 +122,7 @@ Array *Parser::parseModule() md = new ModuleDeclaration(a, id); - if (token.value != TOKsemicolon) - error("';' expected following module declaration instead of %s", token.toChars()); - nextToken(); + check(TOKsemicolon, "module declaration"); addComment(mod, comment); } } @@ -288,6 +286,7 @@ Array *Parser::parseDeclDefs(int once) case TOKtls: stc = STCtls; goto Lstc; case TOKgshared: stc = STCgshared; goto Lstc; //case TOKmanifest: stc = STCmanifest; goto Lstc; + case TOKat: stc = parseAttribute(); goto Lstc; #endif Lstc: @@ -453,9 +452,7 @@ Array *Parser::parseDeclDefs(int once) s = NULL; } nextToken(); - if (token.value != TOKsemicolon) - error("semicolon expected"); - nextToken(); + check(TOKsemicolon, "debug declaration"); break; } @@ -476,9 +473,7 @@ Array *Parser::parseDeclDefs(int once) s = NULL; } nextToken(); - if (token.value != TOKsemicolon) - error("semicolon expected"); - nextToken(); + check(TOKsemicolon, "version declaration"); break; } condition = parseVersionCondition(); @@ -600,7 +595,7 @@ StaticAssert *Parser::parseStaticAssert() msg = parseAssignExp(); } check(TOKrparen); - check(TOKsemicolon); + check(TOKsemicolon, "static assert"); return new StaticAssert(loc, exp, msg); } @@ -781,20 +776,18 @@ Condition *Parser::parseStaticIfCondition() /***************************************** * Parse a constructor definition: - * this(arguments) { body } + * this(parameters) { body } * Current token is 'this'. */ Dsymbol *Parser::parseCtor() { - CtorDeclaration *f; - Parameters *arguments; - int varargs; Loc loc = this->loc; nextToken(); - arguments = parseParameters(&varargs); - f = new CtorDeclaration(loc, 0, arguments, varargs); + int varargs; + Parameters *parameters = parseParameters(&varargs); + CtorDeclaration *f = new CtorDeclaration(loc, 0, parameters, varargs); parseContracts(f); return f; } @@ -811,8 +804,8 @@ DtorDeclaration *Parser::parseDtor() Loc loc = this->loc; nextToken(); - check(TOKthis); - check(TOKlparen); + check(TOKthis, "~"); + check(TOKlparen, "~this"); check(TOKrparen); f = new DtorDeclaration(loc, 0); @@ -828,18 +821,39 @@ DtorDeclaration *Parser::parseDtor() StaticCtorDeclaration *Parser::parseStaticCtor() { - StaticCtorDeclaration *f; Loc loc = this->loc; nextToken(); - check(TOKlparen); + check(TOKlparen, "static this"); check(TOKrparen); - f = new StaticCtorDeclaration(loc, 0); + StaticCtorDeclaration *f = new StaticCtorDeclaration(loc, 0); parseContracts(f); return f; } +/***************************************** + * Parse a shared static constructor definition: + * shared static this() { body } + * Current token is 'shared'. + */ +#if DMDV2 +SharedStaticCtorDeclaration *Parser::parseSharedStaticCtor() +{ + Loc loc = this->loc; + + nextToken(); + nextToken(); + nextToken(); + check(TOKlparen, "shared static this"); + check(TOKrparen); + + SharedStaticCtorDeclaration *f = new SharedStaticCtorDeclaration(loc, 0); + parseContracts(f); + return f; +} +#endif + /***************************************** * Parse a static destructor definition: * static ~this() { body } @@ -848,19 +862,41 @@ StaticCtorDeclaration *Parser::parseStaticCtor() StaticDtorDeclaration *Parser::parseStaticDtor() { - StaticDtorDeclaration *f; Loc loc = this->loc; nextToken(); - check(TOKthis); - check(TOKlparen); + check(TOKthis, "~"); + check(TOKlparen, "~this"); check(TOKrparen); - f = new StaticDtorDeclaration(loc, 0); + StaticDtorDeclaration *f = new StaticDtorDeclaration(loc, 0); parseContracts(f); return f; } +/***************************************** + * Parse a shared static destructor definition: + * shared static ~this() { body } + * Current token is 'shared'. + */ +#if DMDV2 +SharedStaticDtorDeclaration *Parser::parseSharedStaticDtor() +{ + Loc loc = this->loc; + + nextToken(); + nextToken(); + nextToken(); + check(TOKthis, "shared static ~"); + check(TOKlparen, "shared static ~this"); + check(TOKrparen); + + SharedStaticDtorDeclaration *f = new SharedStaticDtorDeclaration(loc, 0); + parseContracts(f); + return f; +} +#endif + /***************************************** * Parse an invariant definition: * invariant() { body } @@ -957,7 +993,7 @@ Parameters *Parser::parseParameters(int *pvarargs) int varargs = 0; int hasdefault = 0; - check(TOKlparen); + check(TOKlparen, "start of parameter list"); while (1) { Type *tb; Identifier *ai = NULL; @@ -1080,7 +1116,7 @@ EnumDeclaration *Parser::parseEnum() while (token.value != TOKrcurly) { if (token.value == TOKidentifier) - { EnumMember *em; + { Expression *value; Identifier *ident; @@ -1093,14 +1129,15 @@ EnumDeclaration *Parser::parseEnum() nextToken(); value = parseAssignExp(); } - em = new EnumMember(loc, ident, value); + EnumMember *em = new EnumMember(loc, ident, value); e->members->push(em); + if (token.value == TOKrcurly) ; else { addComment(em, comment); comment = NULL; - check(TOKcomma); + check(TOKcomma, "enum member"); } addComment(em, comment); comment = token.blockComment; @@ -1129,6 +1166,7 @@ Dsymbol *Parser::parseAggregate() enum TOK tok; Identifier *id; TemplateParameters *tpl = NULL; + Expression *constraint = NULL; //printf("Parser::parseAggregate()\n"); tok = token.value; @@ -1219,13 +1257,12 @@ Dsymbol *Parser::parseAggregate() } if (tpl) - { Array *decldefs; - TemplateDeclaration *tempdecl; + { // Wrap a template around the aggregate declaration - // Wrap a template around the aggregate declaration - decldefs = new Array(); + Array *decldefs = new Array(); decldefs->push(a); - tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs); + TemplateDeclaration *tempdecl = + new TemplateDeclaration(loc, id, tpl, constraint, decldefs); return tempdecl; } @@ -1284,7 +1321,7 @@ Expression *Parser::parseConstraint() if (token.value == TOKif) { nextToken(); // skip over 'if' - check(TOKlparen); + check(TOKlparen, "if"); e = parseExpression(); check(TOKrparen); } @@ -1339,6 +1376,9 @@ Lerr: /****************************************** * Parse template parameter list. + * Input: + * flag 0: parsing "( list )" + * 1: parsing non-empty "list )" */ TemplateParameters *Parser::parseTemplateParameterList(int flag) @@ -1396,7 +1436,7 @@ TemplateParameters *Parser::parseTemplateParameterList(int flag) t->value == TOKcomma || t->value == TOKrparen) { // TypeParameter if (token.value != TOKidentifier) - { error("Identifier expected for template parameter"); + { error("identifier expected for template type parameter"); goto Lerr; } tp_ident = token.ident; @@ -1514,7 +1554,7 @@ Dsymbol *Parser::parseMixin() exp = parseExpression(); check(TOKrparen); tqual = new TypeTypeof(loc, exp); - check(TOKdot); + check(TOKdot, "typeof (expression)"); } if (token.value != TOKidentifier) { @@ -1566,10 +1606,7 @@ Dsymbol *Parser::parseMixin() id = NULL; tm = new TemplateMixin(loc, id, tqual, idents, tiargs); - if (token.value != TOKsemicolon) - error("';' expected after mixin"); - nextToken(); - + check(TOKsemicolon, "template mixin"); return tm; } @@ -1599,18 +1636,14 @@ Objects *Parser::parseTemplateArgumentList() // See if it is an Expression or a Type if (isDeclaration(&token, 0, TOKreserved, NULL)) { // Type - Type *ta; - // Get TemplateArgument - ta = parseBasicType(); + Type *ta = parseBasicType(); ta = parseDeclarator(ta, NULL); tiargs->push(ta); } else - { // Expression - Expression *ea; - - ea = parseAssignExp(); + { // Template argument is an expression + Expression *ea = parseAssignExp(); tiargs->push(ea); } if (token.value != TOKcomma) @@ -1655,7 +1688,7 @@ Import *Parser::parseImport(Array *decldefs, int isstatic) a->push(id); nextToken(); if (token.value != TOKidentifier) - { error("Identifier expected following package"); + { error("identifier expected following package"); break; } id = token.ident; @@ -1673,14 +1706,13 @@ Import *Parser::parseImport(Array *decldefs, int isstatic) { do { Identifier *name; - Identifier *alias; nextToken(); if (token.value != TOKidentifier) { error("Identifier expected following :"); break; } - alias = token.ident; + Identifier *alias = token.ident; nextToken(); if (token.value == TOKassign) { @@ -1708,8 +1740,7 @@ Import *Parser::parseImport(Array *decldefs, int isstatic) nextToken(); else { - error("';' expected"); - nextToken(); + check(TOKsemicolon, "import declaration"); } return NULL; @@ -1734,6 +1765,17 @@ Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl) t = t->makeSharedConst(); return t; } + else if (token.value == TOKwild && peekNext() == TOKshared && peekNext2() != TOKlparen || + token.value == TOKshared && peekNext() == TOKwild && peekNext2() != TOKlparen) + { + nextToken(); + nextToken(); + /* shared wild type + */ + t = parseType(pident, tpl); + t = t->makeSharedWild(); + return t; + } else if (token.value == TOKconst && peekNext() != TOKlparen) { nextToken(); @@ -1762,6 +1804,15 @@ Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl) t = t->makeShared(); return t; } + else if (token.value == TOKwild && peekNext() != TOKlparen) + { + nextToken(); + /* wild type + */ + t = parseType(pident, tpl); + t = t->makeWild(); + return t; + } else t = parseBasicType(); t = parseDeclarator(t, pident, tpl); @@ -1773,7 +1824,6 @@ Type *Parser::parseBasicType() { Type *t; Identifier *id; TypeQualified *tid; - TemplateInstance *tempinst; //printf("parseBasicType()\n"); switch (token.value) @@ -1786,9 +1836,9 @@ Type *Parser::parseBasicType() id = token.ident; nextToken(); if (token.value == TOKnot) - { + { // ident!(template_arguments) + TemplateInstance *tempinst = new TemplateInstance(loc, id); nextToken(); - tempinst = new TemplateInstance(loc, id); tempinst->tiargs = parseTemplateArgumentList(); tid = new TypeInstance(loc, tempinst); goto Lident2; @@ -1807,7 +1857,7 @@ Type *Parser::parseBasicType() if (token.value == TOKnot) { nextToken(); - tempinst = new TemplateInstance(loc, id); + TemplateInstance *tempinst = new TemplateInstance(loc, id); tempinst->tiargs = parseTemplateArgumentList(); tid->addIdent((Identifier *)tempinst); } @@ -1823,11 +1873,10 @@ Type *Parser::parseBasicType() goto Lident; case TOKtypeof: - { Expression *exp; - + { nextToken(); check(TOKlparen); - exp = parseExpression(); + Expression *exp = parseExpression(); check(TOKrparen); tid = new TypeTypeof(loc, exp); goto Lident2; @@ -1880,10 +1929,9 @@ Type *Parser::parseBasicType2(Type *t) } else if (isDeclaration(&token, 0, TOKrbracket, NULL)) { // It's an associative array declaration - Type *index; //printf("it's an associative array\n"); - index = parseBasicType(); + Type *index = parseBasicType(); index = parseDeclarator(index, NULL); // [ type ] t = new TypeAArray(t, index); check(TOKrbracket); @@ -1894,10 +1942,9 @@ Type *Parser::parseBasicType2(Type *t) inBrackets++; Expression *e = parseExpression(); // [ expression ] if (token.value == TOKslice) - { Expression *e2; - + { nextToken(); - e2 = parseExpression(); // [ exp .. exp ] + Expression *e2 = parseExpression(); // [ exp .. exp ] t = new TypeSlice(t, e, e2); } else @@ -1925,7 +1972,7 @@ Type *Parser::parseBasicType2(Type *t) //printf("it's an associative array\n"); index = parseBasicType(); - index = parseDeclarator(index, NULL); // [ type ] + index = parseDeclarator(index, NULL); // [ type ] check(TOKrbracket); ta = new TypeAArray(t, index); } @@ -2029,10 +2076,9 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters * } else if (isDeclaration(&token, 0, TOKrbracket, NULL)) { // It's an associative array declaration - Type *index; //printf("it's an associative array\n"); - index = parseBasicType(); + Type *index = parseBasicType(); index = parseDeclarator(index, NULL); // [ type ] check(TOKrbracket); ta = new TypeAArray(t, index); @@ -2058,16 +2104,14 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters * } #endif case TOKlparen: - { Parameters *arguments; - int varargs; - + { if (tpl) { /* Look ahead to see if this is (...)(...), * i.e. a function template declaration */ if (peekPastParen(&token)->value == TOKlparen) - { // It's a function template declaration + { //printf("function template declaration\n"); // Gather template parameter list @@ -2075,7 +2119,8 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters * } } - arguments = parseParameters(&varargs); + int varargs; + Parameters *arguments = parseParameters(&varargs); Type *ta = new TypeFunction(arguments, t, varargs, linkage); Type **pt; for (pt = &ts; *pt != t; pt = &(*pt)->next) @@ -2294,13 +2339,12 @@ Array *Parser::parseDeclarations() s = new LinkDeclaration(link, ax); } if (tpl) // it's a function template - { Array *decldefs; - TemplateDeclaration *tempdecl; - + { // Wrap a template around the aggregate declaration - decldefs = new Array(); + Array *decldefs = new Array(); decldefs->push(s); - tempdecl = new TemplateDeclaration(loc, s->ident, tpl, NULL, decldefs); + TemplateDeclaration *tempdecl = + new TemplateDeclaration(loc, s->ident, tpl, NULL, decldefs); s = tempdecl; } addComment(s, comment); @@ -2338,7 +2382,7 @@ Array *Parser::parseDeclarations() continue; default: - error("semicolon expected, not '%s'", token.toChars()); + error("semicolon expected to close declaration, not '%s'", token.toChars()); break; } } @@ -2356,9 +2400,9 @@ Array *Parser::parseDeclarations() */ #if DMDV2 -Array *Parser::parseAutoDeclarations(StorageClass storageClass, unsigned char *comment) +Dsymbols *Parser::parseAutoDeclarations(StorageClass storageClass, unsigned char *comment) { - Array *a = new Array; + Dsymbols *a = new Dsymbols; while (1) { @@ -2401,7 +2445,6 @@ Array *Parser::parseAutoDeclarations(StorageClass storageClass, unsigned char *c void Parser::parseContracts(FuncDeclaration *f) { - Type *tb; enum LINK linksave = linkage; // The following is irrelevant, as it is overridden by sc->linkage in @@ -2444,7 +2487,7 @@ L1: check(TOKlparen); while (1) { - tb = parseBasicType(); + Type *tb = parseBasicType(); f->fthrows->push(tb); if (token.value == TOKcomma) { nextToken(); @@ -2468,7 +2511,7 @@ L1: nextToken(); if (token.value != TOKlcurly) { - check(TOKlparen); + check(TOKlparen, "out"); if (token.value != TOKidentifier) error("(identifier) following 'out' expected, not %s", token.toChars()); f->outId = token.ident; @@ -2804,14 +2847,15 @@ Statement *Parser::parseStatement(int flags) case TOKis: case TOKlbracket: #if DMDV2 + case TOKtilde: + case TOKnot: case TOKtraits: case TOKfile: case TOKline: #endif Lexp: - { Expression *exp; - - exp = parseExpression(); + { + Expression *exp = parseExpression(); check(TOKsemicolon, "statement"); s = new ExpStatement(loc, exp); break; @@ -2848,6 +2892,12 @@ Statement *Parser::parseStatement(int flags) #if DMDV2 case TOKimmutable: case TOKshared: + case TOKwild: + case TOKnothrow: + case TOKpure: + case TOKtls: + case TOKgshared: + case TOKat: #endif // case TOKtypeof: Ldeclaration: @@ -2905,7 +2955,7 @@ Statement *Parser::parseStatement(int flags) check(TOKlparen, "mixin"); Expression *e = parseAssignExp(); check(TOKrparen); - check(TOKsemicolon); + check(TOKsemicolon, "mixin (string)"); s = new CompileStatement(loc, e); break; } @@ -2935,7 +2985,7 @@ Statement *Parser::parseStatement(int flags) Statement *body; nextToken(); - check(TOKlparen); + check(TOKlparen, "while"); condition = parseExpression(); check(TOKrparen); body = parseStatement(PSscope); @@ -2956,8 +3006,8 @@ Statement *Parser::parseStatement(int flags) nextToken(); body = parseStatement(PSscope); - check(TOKwhile); - check(TOKlparen); + check(TOKwhile, "statement"); + check(TOKlparen, "while"); condition = parseExpression(); check(TOKrparen); s = new DoStatement(loc, body, condition); @@ -2972,7 +3022,7 @@ Statement *Parser::parseStatement(int flags) Statement *body; nextToken(); - check(TOKlparen); + check(TOKlparen, "for"); if (token.value == TOKsemicolon) { init = NULL; nextToken(); @@ -3009,16 +3059,15 @@ Statement *Parser::parseStatement(int flags) case TOKforeach_reverse: { enum TOK op = token.value; - Parameters *arguments; Statement *d; Statement *body; Expression *aggr; nextToken(); - check(TOKlparen); + check(TOKlparen, "foreach"); - arguments = new Parameters(); + Parameters *arguments = new Parameters(); while (1) { @@ -3026,7 +3075,6 @@ Statement *Parser::parseStatement(int flags) Identifier *ai = NULL; Type *at; unsigned storageClass; - Parameter *a; storageClass = STCin; if (token.value == TOKinout || token.value == TOKref) @@ -3048,7 +3096,7 @@ Statement *Parser::parseStatement(int flags) if (!ai) error("no identifier for declarator %s", at->toChars()); Larg: - a = new Parameter(storageClass, at, ai, NULL); + Parameter *a = new Parameter(storageClass, at, ai, NULL); arguments->push(a); if (token.value == TOKcomma) { nextToken(); @@ -3056,7 +3104,7 @@ Statement *Parser::parseStatement(int flags) } break; } - check(TOKsemicolon); + check(TOKsemicolon, "foreach statement"); aggr = parseExpression(); check(TOKrparen); @@ -3072,7 +3120,7 @@ Statement *Parser::parseStatement(int flags) Statement *elsebody; nextToken(); - check(TOKlparen); + check(TOKlparen, "if"); if (token.value == TOKauto) { @@ -3140,9 +3188,9 @@ Statement *Parser::parseStatement(int flags) if (peek(&token)->value != TOKlparen) goto Ldeclaration; // scope used as storage class nextToken(); - check(TOKlparen); + check(TOKlparen, "scope"); if (token.value != TOKidentifier) - { error("scope identifier expected"); + { error("scope (identifier) expected"); goto Lerror; } else @@ -3213,14 +3261,12 @@ Statement *Parser::parseStatement(int flags) } case TOKswitch: - { Expression *condition; - Statement *body; - + { nextToken(); - check(TOKlparen); - condition = parseExpression(); + check(TOKlparen, "switch"); + Expression *condition = parseExpression(); check(TOKrparen); - body = parseStatement(PSscope); + Statement *body = parseStatement(PSscope); s = new SwitchStatement(loc, condition, body); break; } @@ -3238,7 +3284,21 @@ Statement *Parser::parseStatement(int flags) if (token.value != TOKcomma) break; } - check(TOKcolon); + check(TOKcolon, "case expression"); + +#if DMDV2 + /* case exp: .. case last: + */ + if (token.value == TOKslice) + { + if (cases.dim > 1) + error("only one case allowed for start of case range"); + nextToken(); + check(TOKcase, ".."); + last = parseAssignExp(); + check(TOKcolon, "case expression"); + } +#endif statements = new Statements(); while (token.value != TOKcase && @@ -3265,7 +3325,7 @@ Statement *Parser::parseStatement(int flags) Statements *statements; nextToken(); - check(TOKcolon); + check(TOKcolon, "default"); statements = new Statements(); while (token.value != TOKcase && @@ -3289,7 +3349,7 @@ Statement *Parser::parseStatement(int flags) exp = NULL; else exp = parseExpression(); - check(TOKsemicolon, "return statement"); + check(TOKsemicolon, "return expression"); s = new ReturnStatement(loc, exp); break; } @@ -3381,7 +3441,7 @@ Statement *Parser::parseStatement(int flags) Statement *body; nextToken(); - check(TOKlparen); + check(TOKlparen, "with"); exp = parseExpression(); check(TOKrparen); body = parseStatement(PSscope); @@ -3412,7 +3472,7 @@ Statement *Parser::parseStatement(int flags) } else { - check(TOKlparen); + check(TOKlparen, "catch"); t = parseBasicType(); id = NULL; t = parseDeclarator(t, &id); @@ -3475,7 +3535,7 @@ Statement *Parser::parseStatement(int flags) // Defer parsing of AsmStatements until semantic processing. nextToken(); - check(TOKlcurly); + check(TOKlcurly, "asm"); toklist = NULL; ptoklist = &toklist; label = NULL; @@ -3589,6 +3649,8 @@ void Parser::check(enum TOK value, const char *string) * needId 0 no identifier * 1 identifier optional * 2 must have identifier + * Output: + * if *pt is not NULL, it is set to the ending token, which would be endtok */ int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) @@ -3597,28 +3659,44 @@ int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) int haveId = 0; #if DMDV2 - if ((t->value == TOKconst || t->value == TOKinvariant) && + if ((t->value == TOKconst || + t->value == TOKinvariant || + t->value == TOKimmutable || + t->value == TOKwild || + t->value == TOKshared) && peek(t)->value != TOKlparen) { /* const type - * invariant type + * immutable type + * shared type + * wild type */ t = peek(t); } #endif if (!isBasicType(&t)) - return FALSE; + { + goto Lisnot; + } if (!isDeclarator(&t, &haveId, endtok)) - return FALSE; + goto Lisnot; if ( needId == 1 || (needId == 0 && !haveId) || (needId == 2 && haveId)) { if (pt) *pt = t; - return TRUE; + goto Lis; } else - return FALSE; + goto Lisnot; + +Lis: + //printf("\tis declaration, t = %s\n", t->toChars()); + return TRUE; + +Lisnot: + //printf("\tis not declaration\n"); + return FALSE; } int Parser::isBasicType(Token **pt) @@ -3822,10 +3900,15 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) case TOKinvariant: case TOKimmutable: case TOKshared: + case TOKwild: case TOKpure: case TOKnothrow: t = peek(t); continue; + case TOKat: + t = peek(t); // skip '@' + t = peek(t); // skip identifier + continue; default: break; } @@ -4195,8 +4278,8 @@ Expression *Parser::parsePrimaryExp() #if DMDV2 case TOKfile: - { char *s = loc.filename ? loc.filename : mod->ident->toChars(); - e = new StringExp(loc, s, strlen(s), 0); + { const char *s = loc.filename ? loc.filename : mod->ident->toChars(); + e = new StringExp(loc, (char *)s, strlen(s), 0); nextToken(); break; } @@ -4314,7 +4397,7 @@ Expression *Parser::parsePrimaryExp() Objects *args = NULL; nextToken(); - check(TOKlparen); + check(TOKlparen, "__traits"); if (token.value != TOKidentifier) { error("__traits(identifier, args...) expected"); goto Lerr; @@ -4462,7 +4545,7 @@ Expression *Parser::parsePrimaryExp() values->push(e); if (token.value == TOKrbracket) break; - check(TOKcomma); + check(TOKcomma, "literal element"); } } check(TOKrbracket); @@ -4615,7 +4698,7 @@ Expression *Parser::parsePostExp(Expression *e) arguments->push(arg); if (token.value == TOKrbracket) break; - check(TOKcomma); + check(TOKcomma, "array literal element"); } } e = new ArrayExp(loc, e, arguments); @@ -4820,8 +4903,8 @@ Expression *Parser::parseMulExp() switch (token.value) { case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue; - case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; - case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; + case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; + case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; default: break; @@ -4904,6 +4987,20 @@ Expression *Parser::parseRelExp() e = new CmpExp(op, loc, e, e2); continue; +#if DMDV2 + case TOKnot: // could be !in + if (peekNext() == TOKin) + { + nextToken(); + nextToken(); + e2 = parseShiftExp(); + e = new InExp(loc, e, e2); + e = new NotExp(loc, e); + continue; + } + break; +#endif + case TOKin: nextToken(); e2 = parseShiftExp(); @@ -4997,6 +5094,17 @@ Expression *Parser::parseCmpExp() case TOKnot: // Attempt to identify '!is' t = peek(&token); +#if DMDV2 + if (t->value == TOKin) + { + nextToken(); + nextToken(); + e2 = parseShiftExp(); + e = new InExp(loc, e, e2); + e = new NotExp(loc, e); + break; + } +#endif if (t->value != TOKis) break; nextToken(); @@ -5139,7 +5247,7 @@ Expression *Parser::parseCondExp() { nextToken(); e1 = parseExpression(); - check(TOKcolon); + check(TOKcolon, "condition ? expression"); e2 = parseCondExp(); e = new CondExp(loc, e, e1, e2); } @@ -5228,10 +5336,10 @@ Expressions *Parser::parseArguments() arguments->push(arg); if (token.value == endtok) break; - check(TOKcomma); + check(TOKcomma, "argument"); } } - check(endtok); + check(endtok, "argument list"); } return arguments; } diff --git a/dmd/speller.c b/dmd/speller.c index e6d578ee..bf3f72a4 100644 --- a/dmd/speller.c +++ b/dmd/speller.c @@ -21,7 +21,7 @@ const char idchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123 *void*value returned by fp() for first possible correct spelling */ -void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset) +void *spellerX(const char *seed, fp_speller_t fp, void *fparg, const char *charset, int flag) { size_t seedlen = strlen(seed); if (!seedlen) @@ -36,7 +36,11 @@ void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charse for (int i = 0; i < seedlen; i++) { //printf("del buf = '%s'\n", buf); - void *p = (*fp)(fparg, buf); + void *p; + if (flag) + p = spellerX(buf, fp, fparg, charset, flag - 1); + else + p = (*fp)(fparg, buf); if (p) return p; @@ -52,7 +56,11 @@ void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charse buf[i + 1] = seed[i]; //printf("tra buf = '%s'\n", buf); - void *p = (*fp)(fparg, buf); + void *p; + if (flag) + p = spellerX(buf, fp, fparg, charset, flag - 1); + else + p = (*fp)(fparg, buf); if (p) return p; @@ -70,7 +78,11 @@ void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charse buf[i] = *s; //printf("sub buf = '%s'\n", buf); - void *p = (*fp)(fparg, buf); + void *p; + if (flag) + p = spellerX(buf, fp, fparg, charset, flag - 1); + else + p = (*fp)(fparg, buf); if (p) return p; } @@ -86,7 +98,11 @@ void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charse buf[i] = *s; //printf("ins buf = '%s'\n", buf); - void *p = (*fp)(fparg, buf); + void *p; + if (flag) + p = spellerX(buf, fp, fparg, charset, flag - 1); + else + p = (*fp)(fparg, buf); if (p) return p; } @@ -96,3 +112,54 @@ void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charse return NULL;// didn't find any corrections } +void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset) +{ + for (int distance = 0; distance < 2; distance++) + { void *p = spellerX(seed, fp, fparg, charset, distance); + if (p) + return p; + } + return NULL; // didn't find it +} + + +#if UNITTEST + +#include +#include +#include + +void *speller_test(void *fparg, const char *s) +{ + if (strcmp((char *)fparg, s) == 0) + return fparg; + return NULL; +} + +void unittest_speller() +{ + static const char *cases[][3] = + { + { "hello", "hell", "y" }, + { "hello", "abcd", "n" }, + { "hello", "hel", "y" }, + { "ehllo", "helol", "y" }, + { "hello", "helxxlo", "y" }, + { "hello", "ehlxxlo", "n" }, + { "hello", "heaao", "y" }, + }; + //printf("unittest_speller()\n"); + void *p = speller("hello", &speller_test, (void *)"hell", idchars); + assert(p != NULL); + for (int i = 0; i < sizeof(cases)/sizeof(cases[0]); i++) + { + void *p = speller(cases[i][0], &speller_test, (void *)cases[i][1], idchars); + if (p) + assert(cases[i][2][0] == 'y'); + else + assert(cases[i][2][0] == 'n'); + } + //printf("unittest_speller() success\n"); +} + +#endif diff --git a/dmd/statement.h b/dmd/statement.h index 1ed3f503..ddd3c0dd 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -373,6 +373,7 @@ struct ForeachStatement : Statement ForeachStatement(Loc loc, enum TOK op, Parameters *arguments, Expression *aggr, Statement *body); Statement *syntaxCopy(); Statement *semantic(Scope *sc); + bool checkForArgTypes(); int hasBreak(); int hasContinue(); int usesEH(); @@ -714,6 +715,7 @@ struct WithStatement : Statement void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int usesEH(); int blockExit(); + Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -731,6 +733,7 @@ struct TryCatchStatement : Statement int hasBreak(); int usesEH(); int blockExit(); + Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -767,6 +770,7 @@ struct TryFinallyStatement : Statement int hasContinue(); int usesEH(); int blockExit(); + Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -785,6 +789,7 @@ struct OnScopeStatement : Statement Statement *semantic(Scope *sc); int usesEH(); void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); + Expression *interpret(InterState *istate); void toIR(IRState *irs); }; @@ -798,6 +803,7 @@ struct ThrowStatement : Statement Statement *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int blockExit(); + Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -889,6 +895,7 @@ struct AsmStatement : Statement Statement *semantic(Scope *sc); int blockExit(); int comeFrom(); + Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); virtual AsmStatement *isAsmStatement() { return this; }