Skip to content

Commit

Permalink
refactor lambda inference process
Browse files Browse the repository at this point in the history
  • Loading branch information
9rnsr committed Mar 5, 2012
1 parent d531901 commit 4118727
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 155 deletions.
44 changes: 29 additions & 15 deletions src/cast.c
Expand Up @@ -131,6 +131,12 @@ Expression *ErrorExp::implicitCastTo(Scope *sc, Type *t)
return this;
}

Expression *FuncExp::implicitCastTo(Scope *sc, Type *t)
{
//printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
return inferType(t);
}

/*******************************************
* Return !=0 if we can implicitly convert this to type t.
* Don't do the actual cast.
Expand Down Expand Up @@ -719,12 +725,24 @@ MATCH DelegateExp::implicitConvTo(Type *t)

MATCH FuncExp::implicitConvTo(Type *t)
{
//printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
if (type && type != Type::tvoid && tok == TOKreserved && type->ty == Tpointer
&& (t->ty == Tpointer || t->ty == Tdelegate))
{ // Allow implicit function to delegate conversion
if (type->nextOf()->covariant(t->nextOf()) == 1)
return t->ty == Tpointer ? MATCHconst : MATCHconvert;
//printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
Expression *e = inferType(t, 1);
if (e)
{
if (e != this)
return e->implicitConvTo(t);

/* MATCHconst: Conversion from implicit to explicit function pointer
* MATCHconvert: Conversion from impliict funciton pointer to delegate
*/
if (tok == TOKreserved && type->ty == Tpointer &&
(t->ty == Tpointer || t->ty == Tdelegate))
{
if (type == t)
return MATCHexact;
if (type->nextOf()->covariant(t->nextOf()) == 1)
return t->ty == Tpointer ? MATCHconst : MATCHconvert;
}
}
return Expression::implicitConvTo(t);
}
Expand Down Expand Up @@ -1491,15 +1509,11 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t)
Expression *FuncExp::castTo(Scope *sc, Type *t)
{
//printf("FuncExp::castTo type = %s, t = %s\n", type->toChars(), t->toChars());
if (tok == TOKreserved)
{ assert(type && type != Type::tvoid);
if (type->ty == Tpointer && t->ty == Tdelegate)
{
Expression *e = copy();
e->type = new TypeDelegate(fd->type);
e->type = e->type->semantic(loc, sc);
return e;
}
Expression *e = inferType(t, 1);
if (e)
{ if (e != this)
e = e->castTo(sc, t);
return e;
}
return Expression::castTo(sc, t);
}
Expand Down
160 changes: 56 additions & 104 deletions src/expression.c
Expand Up @@ -756,13 +756,12 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
nargs++;
}
else if (arg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)arg;
{
Type *pt = p->type;
if (tf->varargs == 2 && i + 1 == nparams && pt->nextOf())
pt = pt->nextOf();
fe->setType(pt);
arg = fe->semantic(sc);
arguments->tdata()[i] = arg;
arg = ((FuncExp *)arg)->inferType(pt);
arguments->tdata()[i] = arg;
}

if (tf->varargs == 2 && i + 1 == nparams)
Expand Down Expand Up @@ -3783,14 +3782,6 @@ Expression *StructLiteralExp::semantic(Scope *sc)
telem = telem->toBasetype()->nextOf();
}

if (e->op == TOKfunction)
{ e = ((FuncExp *)e)->inferType(sc, telem);
if (!e)
{ error("cannot infer function literal type from %s", telem->toChars());
e = new ErrorExp();
}
}

e = e->implicitCastTo(sc, telem);

elements->tdata()[i] = e;
Expand Down Expand Up @@ -4951,7 +4942,6 @@ FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td)
this->td = td;
tok = fd->tok; // save original kind of function/delegate/(infer)
tded = NULL;
scope = NULL;
}

Expression *FuncExp::syntaxCopy()
Expand All @@ -4967,9 +4957,6 @@ Expression *FuncExp::semantic(Scope *sc)
#endif
if (!type || type == Type::tvoid)
{
// save for later use
scope = sc;

// Set target of return type inference
if (tded && !fd->type->nextOf())
{ TypeFunction *tfv = NULL;
Expand All @@ -4993,19 +4980,7 @@ Expression *FuncExp::semantic(Scope *sc)
type = Type::tvoid; // temporary type
return this;
}
else
{
Expression *e = inferType(sc, tded);
if (e)
{ e = e->castTo(sc, tded);
e = e->semantic(sc);
}
if (!e)
{ error("cannot infer function literal type");
e = new ErrorExp();
}
return e;
}
return inferType(tded);
}

unsigned olderrors = global.errors;
Expand Down Expand Up @@ -5051,9 +5026,6 @@ Expression *FuncExp::semantic(Scope *sc)
// used from CallExp::semantic()
Expression *FuncExp::semantic(Scope *sc, Expressions *arguments)
{
assert(!tded);
assert(!scope);

if ((!type || type == Type::tvoid) && td && arguments && arguments->dim)
{
for (size_t k = 0; k < arguments->dim; k++)
Expand Down Expand Up @@ -5097,24 +5069,27 @@ Expression *FuncExp::semantic(Scope *sc, Expressions *arguments)
return semantic(sc);
}

Expression *FuncExp::inferType(Scope *sc, Type *to)
Expression *FuncExp::inferType(Type *to, int flag)
{
//printf("inferType sc = %p, to = %s\n", sc, to->toChars());
if (!sc)
{ // used from TypeFunction::callMatch()
assert(scope);
sc = scope;
Expression *e = NULL;

Type *t = to;
if (t->ty == Tdelegate)
{ if (tok == TOKfunction)
goto L1;
t = t->nextOf();
}
else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction)
{ if (tok == TOKdelegate)
goto L1;
t = t->nextOf();
}
else
goto L1;

Expression *e = NULL;
if (td)
{ /// Parameter types inference from
assert(!type || type == Type::tvoid);
Type *t = to;
if (t->ty == Tdelegate ||
t->ty == Tpointer && t->nextOf()->ty == Tfunction)
{ t = t->nextOf();
}
assert(td->scope);
if (t->ty == Tfunction)
{
TypeFunction *tfv = (TypeFunction *)t;
Expand All @@ -5137,30 +5112,44 @@ Expression *FuncExp::inferType(Scope *sc, Type *to)
{ p = Parameter::getNth(tfv->parameters, u);
if (p->type->ty == Tident)
return NULL;
Type *tprm = p->type->semantic(loc, sc);
Type *tprm = p->type->semantic(loc, td->scope);
tiargs->push(tprm);
u = dim; // break inner loop
}
}
}

TemplateInstance *ti = new TemplateInstance(loc, td, tiargs);
e = (new ScopeExp(loc, ti))->semantic(sc);
e = (new ScopeExp(loc, ti))->semantic(td->scope);
}
}
}
else
else if (type)
{
assert(type && type != Type::tvoid); // semantic is already done
e = this;
}
assert(type != Type::tvoid); // semantic is already done

if (e)
{ // Check implicit function to delegate conversion
if (e->implicitConvTo(to))
e = e->castTo(sc, to);
// Allow conversion from implicit function pointer to delegate
if (tok == TOKreserved && type->ty == Tpointer &&
to->ty == Tdelegate)
{
Type *typen = type->nextOf();
assert(typen->deco);
if (typen->covariant(to->nextOf()) == 1)
{
FuncExp *fe = (FuncExp *)copy();
fe->tok = TOKdelegate;
fe->type = (new TypeDelegate(typen))->merge();
e = fe;
//e = fe->Expression::implicitCastTo(sc, to);
}
}
else
e = NULL;
e = this;
}
L1:
if (!flag && !e)
{ error("cannot infer function literal type from %s", to->toChars());
e = new ErrorExp();
}
return e;
}
Expand Down Expand Up @@ -7234,12 +7223,13 @@ Expression *CallExp::resolveUFCS(Scope *sc)
Expression *key = arguments->tdata()[0];
key = key->semantic(sc);
key = resolveProperties(sc, key);
if (!key->rvalue())
return new ErrorExp();

TypeAArray *taa = (TypeAArray *)tthis;
key = key->implicitCastTo(sc, taa->index);

if (!key->rvalue())
return new ErrorExp();

return new RemoveExp(loc, ethis, key);
}
else if (ident == Id::apply || ident == Id::applyReverse)
Expand Down Expand Up @@ -8655,26 +8645,6 @@ Expression *CastExp::semantic(Scope *sc)
Type *t1b = e1->type->toBasetype();
Type *tob = to->toBasetype();

if (e1->op == TOKfunction &&
(tob->ty == Tdelegate || tob->ty == Tpointer && tob->nextOf()->ty == Tfunction))
{
FuncExp *fe = (FuncExp *)e1;
Expression *e = NULL;
if (e1->type == Type::tvoid)
{
e = fe->inferType(sc, tob);
}
else if (e1->type->ty == Tpointer && e1->type->nextOf()->ty == Tfunction &&
fe->tok == TOKreserved &&
tob->ty == Tdelegate)
{
if (fe->implicitConvTo(tob))
e = fe->castTo(sc, tob);
}
if (e)
e1 = e->semantic(sc);
}

if (tob->ty == Tstruct &&
!tob->equals(t1b)
)
Expand Down Expand Up @@ -10080,27 +10050,6 @@ Expression *AssignExp::semantic(Scope *sc)

Type *t1 = e1->type->toBasetype();

if (t1->ty == Tdelegate || (t1->ty == Tpointer && t1->nextOf()->ty == Tfunction)
&& e2->op == TOKfunction)
{
FuncExp *fe = (FuncExp *)e2;
if (e2->type == Type::tvoid)
{
e2 = fe->inferType(sc, t1);
}
else if (e2->type->ty == Tpointer && e2->type->nextOf()->ty == Tfunction &&
fe->tok == TOKreserved &&
t1->ty == Tdelegate)
{
if (fe->implicitConvTo(t1))
e2 = fe->castTo(sc, t1);
}
if (!e2)
{ error("cannot infer function literal type from %s", t1->toChars());
e2 = new ErrorExp();
}
}

/* If it is an assignment from a 'foreign' type,
* check for operator overloading.
*/
Expand Down Expand Up @@ -10242,6 +10191,8 @@ Expression *AssignExp::semantic(Scope *sc)
}
}

if (e2->op == TOKfunction)
e2 = ((FuncExp *)e2)->inferType(t1);
if (!e2->rvalue())
return new ErrorExp();

Expand Down Expand Up @@ -10379,10 +10330,9 @@ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
}

Expression *CatAssignExp::semantic(Scope *sc)
{ Expression *e;

{
//printf("CatAssignExp::semantic() %s\n", toChars());
e = op_overload(sc);
Expression *e = op_overload(sc);
if (e)
return e;

Expand All @@ -10398,12 +10348,14 @@ Expression *CatAssignExp::semantic(Scope *sc)
e1 = e1->modifiableLvalue(sc, e1);

Type *tb1 = e1->type->toBasetype();
Type *tb2 = e2->type->toBasetype();
Type *tb1next = tb1->nextOf();

if (e2->op == TOKfunction)
e2 = ((FuncExp *)e2)->inferType(tb1next);
if (!e2->rvalue())
return new ErrorExp();

Type *tb1next = tb1->nextOf();
Type *tb2 = e2->type->toBasetype();

if ((tb1->ty == Tarray) &&
(tb2->ty == Tarray || tb2->ty == Tsarray) &&
Expand Down
4 changes: 2 additions & 2 deletions src/expression.h
Expand Up @@ -656,16 +656,16 @@ struct FuncExp : Expression
TemplateDeclaration *td;
enum TOK tok;
Type *tded;
Scope *scope;

FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *semantic(Scope *sc, Expressions *arguments);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *implicitCastTo(Scope *sc, Type *t);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0);
void setType(Type *t);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expand Down
6 changes: 0 additions & 6 deletions src/init.c
Expand Up @@ -854,12 +854,6 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
Type *ExpInitializer::inferType(Scope *sc)
{
//printf("ExpInitializer::inferType() %s\n", toChars());
if (exp->op == TOKfunction && ((FuncExp *)exp)->td)
{
exp->error("cannot infer type from ambiguous function literal %s", exp->toChars());
return Type::terror;
}

exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);

Expand Down

0 comments on commit 4118727

Please sign in to comment.