Skip to content

Commit

Permalink
Merge pull request #2029 from 9rnsr/fix9628
Browse files Browse the repository at this point in the history
Issue 9628 - Lambda in foreach loop Vs. lambda in static foreach loop
  • Loading branch information
WalterBright committed Jun 8, 2013
2 parents 3c5eb89 + 0ba974c commit a8f842e
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 19 deletions.
3 changes: 2 additions & 1 deletion src/declaration.h
Expand Up @@ -766,9 +766,10 @@ class FuncLiteralDeclaration : public FuncDeclaration
Type *treq; // target of return type inference

FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, TOK tok,
ForeachStatement *fes);
ForeachStatement *fes, Identifier *id = NULL);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Dsymbol *syntaxCopy(Dsymbol *);
Dsymbol *syntaxCopy(Dsymbol *s, bool keepId);
bool isNested();
bool isVirtual();

Expand Down
18 changes: 16 additions & 2 deletions src/expression.c
Expand Up @@ -5803,10 +5803,24 @@ FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td)
tok = fd->tok; // save original kind of function/delegate/(infer)
}

FuncLiteralDeclaration *getFuncLit(Dsymbols *members);

Expression *FuncExp::syntaxCopy()
{
TemplateDeclaration *td2 = td ? (TemplateDeclaration *)td->syntaxCopy(NULL) : NULL;
return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL), td2);
FuncExp *fe;
TemplateDeclaration *td2;
FuncLiteralDeclaration *fd2;
if (td)
{
td2 = (TemplateDeclaration *)td->syntaxCopy(NULL);
fd2 = getFuncLit(td2->members);
}
else
{
td2 = NULL;
fd2 = (FuncLiteralDeclaration *)fd->syntaxCopy(NULL);
}
return new FuncExp(loc, fd2, td2);
}

Expression *FuncExp::semantic(Scope *sc)
Expand Down
35 changes: 20 additions & 15 deletions src/func.c
Expand Up @@ -3810,38 +3810,43 @@ FuncDeclaration *FuncAliasDeclaration::toAliasFunc()
/****************************** FuncLiteralDeclaration ************************/

FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
TOK tok, ForeachStatement *fes)
TOK tok, ForeachStatement *fes, Identifier *id)
: FuncDeclaration(loc, endloc, NULL, STCundefined, type)
{
const char *id;

if (fes)
id = "__foreachbody";
else if (tok == TOKreserved)
id = "__lambda";
else if (tok == TOKdelegate)
id = "__dgliteral";
else
id = "__funcliteral";
this->ident = Lexer::uniqueId(id);
if (!id)
{
const char *s;
if (fes) s = "__foreachbody";
else if (tok == TOKreserved) s = "__lambda";
else if (tok == TOKdelegate) s = "__dgliteral";
else s = "__funcliteral";
id = Lexer::uniqueId(s);
}
this->ident = id;
this->tok = tok;
this->fes = fes;
this->treq = NULL;
//printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
}

Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
{
return syntaxCopy(s, false);
}

Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s, bool keepId)
{
FuncLiteralDeclaration *f;

//printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
if (s)
f = (FuncLiteralDeclaration *)s;
else
{ f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
f->ident = ident; // keep old identifier
f->treq = treq; // don't need to copy
{
Identifier *id = keepId ? ident : NULL;
f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes, id);
}
f->treq = treq; // don't need to copy
FuncDeclaration::syntaxCopy(f);
return f;
}
Expand Down
16 changes: 15 additions & 1 deletion src/template.c
Expand Up @@ -399,6 +399,13 @@ Object *objectSyntaxCopy(Object *o)
}
#endif

FuncLiteralDeclaration *getFuncLit(Dsymbols *members)
{
assert(members->dim == 1);
assert((*members)[0]->isFuncLiteralDeclaration());
return (FuncLiteralDeclaration *)(*members)[0];
}


/* ======================== TemplateDeclaration ============================= */

Expand Down Expand Up @@ -468,7 +475,8 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
if (constraint)
e = constraint->syntaxCopy();
Dsymbols *d = Dsymbol::arraySyntaxCopy(members);
td = new TemplateDeclaration(loc, ident, p, e, d, ismixin);
Identifier *id = literal ? getFuncLit(d)->ident : ident;
td = new TemplateDeclaration(loc, id, p, e, d, ismixin);
td->literal = literal;
return td;
}
Expand Down Expand Up @@ -5172,6 +5180,12 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
// Copy the syntax trees from the TemplateDeclaration
if (members && speculative)
{} // Don't copy again so they were previously created.
else if (tempdecl->literal)
{
FuncLiteralDeclaration *fld = getFuncLit(tempdecl->members);
members = new Dsymbols();
members->push(fld->syntaxCopy(NULL, true));
}
else
members = Dsymbol::arraySyntaxCopy(tempdecl->members);

Expand Down
35 changes: 35 additions & 0 deletions test/runnable/funclit.d
Expand Up @@ -750,6 +750,40 @@ void test9415()
dg = (int a){return z;};
}

/***************************************************/
// 9628

template TypeTuple9628(TL...) { alias TypeTuple9628 = TL; }
void map9628(alias func)() { func(0); }

void test9628()
{
auto items = [[10, 20], [30]];
size_t[] res;

res = null;
foreach (_; 0 .. 2)
{
foreach (sub; items)
{
map9628!(( i){ res ~= sub.length; });
map9628!((size_t i){ res ~= sub.length; });
}
}
assert(res == [2,2,1,1, 2,2,1,1]);

res = null;
foreach (_; TypeTuple9628!(0, 1))
{
foreach (sub; items)
{
map9628!(( i){ res ~= sub.length; });
map9628!((size_t i){ res ~= sub.length; });
}
}
assert(res == [2,2,1,1, 2,2,1,1]);
}

/***************************************************/
// 9928

Expand Down Expand Up @@ -802,6 +836,7 @@ int main()
test9153();
test9393();
test9415();
test9628();
test9928();

printf("Success\n");
Expand Down

0 comments on commit a8f842e

Please sign in to comment.