fixes #427 :: Upgrade to DMDFE 1.059+1.060 patch; thanks to SiegeLord

This commit is contained in:
Moritz Warning
2010-09-05 19:12:55 +02:00
parent ac5180b65b
commit ba275942cf
17 changed files with 542 additions and 206 deletions

View File

@@ -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:

View File

@@ -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?

View File

@@ -891,6 +891,9 @@ void VarDeclaration::semantic(Scope *sc)
else if (storage_class & STCtemplateparameter)
{
}
else if (storage_class & STCctfe)
{
}
else
{
AggregateDeclaration *aad = sc->anonAgg;

View File

@@ -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; }
};

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -43,7 +43,7 @@ Msgtable msgtable[] =
{ "init" },
{ "size" },
{ "__sizeof", "sizeof" },
{ "alignof" },
{ "__xalignof", "alignof" },
{ "mangleof" },
{ "stringof" },
{ "tupleof" },

View File

@@ -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);

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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");
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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 <stdio.h>
#include <string.h>
#include <assert.h>
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

View File

@@ -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; }