Skip to content

Commit

Permalink
Allow template property getter/setter like opDispatch.
Browse files Browse the repository at this point in the history
  • Loading branch information
9rnsr committed Jan 26, 2012
1 parent c49e060 commit 0e7942a
Show file tree
Hide file tree
Showing 3 changed files with 364 additions and 43 deletions.
129 changes: 86 additions & 43 deletions src/expression.c
Expand Up @@ -211,6 +211,50 @@ FuncDeclaration *hasThis(Scope *sc)
Expression *resolveProperties(Scope *sc, Expression *e)
{
//printf("resolveProperties(%s)\n", e->toChars());

TemplateDeclaration *td;
Objects *targsi;
Expression *ethis;
if (e->op == TOKdotti)
{
DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e;
td = dti->getTempdecl(sc);
dti->ti->semanticTiargs(sc);
targsi = dti->ti->tiargs;
ethis = dti->e1;
goto L1;
}
else if (e->op == TOKdottd)
{
DotTemplateExp *dte = (DotTemplateExp *)e;
td = dte->td;
targsi = NULL;
ethis = dte->e1;
goto L1;
}
else if (e->op == TOKtemplate)
{
td = ((TemplateExp *)e)->td;
targsi = NULL;
ethis = NULL;
L1:
assert(td);
unsigned errors = global.startGagging();
FuncDeclaration *fd = td->deduceFunctionTemplate(sc, e->loc, targsi, ethis, NULL, 1);
if (global.endGagging(errors))
fd = NULL; // eat "is not a function template" error
if (fd && fd->type)
{ assert(fd->type->ty == Tfunction);
TypeFunction *tf = (TypeFunction *)fd->type;
if (!tf->isproperty && global.params.enforcePropertySyntax)
error(e->loc, "not a property %s", e->toChars());

e = new CallExp(e->loc, e);
e = e->semantic(sc);
}
return e;
}

if (e->type)
{
Type *t = e->type->toBasetype();
Expand Down Expand Up @@ -247,11 +291,6 @@ Expression *resolveProperties(Scope *sc, Expression *e)
}

}
else if (e->op == TOKdottd)
{
e = new CallExp(e->loc, e);
e = e->semantic(sc);
}
return e;
}

Expand Down Expand Up @@ -544,16 +583,6 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps)
for (size_t i = 0; i < exps->dim; i++)
{ Expression *arg = (*exps)[i];

if (!arg->type)
{
#ifdef DEBUG
if (!global.gag)
printf("1: \n");
#endif
arg->error("%s is not an expression", arg->toChars());
arg = new ErrorExp();
}

arg = resolveProperties(sc, arg);
(*exps)[i] = arg;

Expand Down Expand Up @@ -3705,10 +3734,6 @@ Expression *StructLiteralExp::semantic(Scope *sc)
if (!e)
continue;

if (!e->type)
{ error("%s has no value", e->toChars());
return new ErrorExp();
}
e = resolveProperties(sc, e);
if (i >= nfields)
{ error("more initializers than fields of %s", sd->toChars());
Expand Down Expand Up @@ -5788,18 +5813,7 @@ Expression *BinExp::semantic(Scope *sc)
printf("BinExp::semantic('%s')\n", toChars());
#endif
e1 = e1->semantic(sc);
if (!e1->type &&
!(op == TOKassign && e1->op == TOKdottd)) // a.template = e2
{
error("%s has no value", e1->toChars());
return new ErrorExp();
}
e2 = e2->semantic(sc);
if (!e2->type)
{
error("%s has no value", e2->toChars());
return new ErrorExp();
}
if (e1->op == TOKerror || e2->op == TOKerror)
return new ErrorExp();
return this;
Expand Down Expand Up @@ -6837,8 +6851,8 @@ Expression *DotTemplateInstanceExp::semantic(Scope *sc)
ti->tempdecl = td;
if (ti->needsTypeInference(sc))
{
e = new CallExp(loc, this);
return e->semantic(sc);
e1 = eleft; // save result of semantic()
return this;
}
else
ti->semantic(sc);
Expand Down Expand Up @@ -9226,16 +9240,11 @@ Expression *IndexExp::semantic(Scope *sc)
}

e2 = e2->semantic(sc);
if (!e2->type)
{
error("%s has no value", e2->toChars());
goto Lerr;
}
if (e2->type->ty == Ttuple && ((TupleExp *)e2)->exps->dim == 1) // bug 4444 fix
e2 = ((TupleExp *)e2)->exps->tdata()[0];
e2 = resolveProperties(sc, e2);
if (e2->type == Type::terror)
goto Lerr;
if (e2->type->ty == Ttuple && ((TupleExp *)e2)->exps->dim == 1) // bug 4444 fix
e2 = ((TupleExp *)e2)->exps->tdata()[0];

if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
sc = sc->pop();
Expand Down Expand Up @@ -9694,13 +9703,47 @@ Expression *AssignExp::semantic(Scope *sc)
* or:
* f() = value
*/
TemplateDeclaration *td;
Objects *targsi;
FuncDeclaration *fd;
Expression *ethis;
if (e1->op == TOKdottd)
if (e1->op == TOKdotti)
{
Expression *e = new CallExp(loc, e1, e2);
e = e->semantic(sc);
return e;
DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
td = dti->getTempdecl(sc);
dti->ti->semanticTiargs(sc);
targsi = dti->ti->tiargs;
ethis = dti->e1;
goto L3;
}
else if (e1->op == TOKdottd)
{
DotTemplateExp *dte = (DotTemplateExp *)e1;
td = dte->td;
targsi = NULL;
ethis = dte->e1;
goto L3;
}
else if (e1->op == TOKtemplate)
{
td = ((TemplateExp *)e1)->td;
targsi = NULL;
ethis = NULL;
L3:
{
assert(td);
Expressions a;
a.push(e2);

fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, &a, 1);
if (fd && fd->type)
goto Lsetter;

fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, NULL, 1);
if (fd && fd->type)
goto Lgetter;
}
goto Leprop;
}
else if (e1->op == TOKdotvar && e1->type->toBasetype()->ty == Tfunction)
{
Expand Down
1 change: 1 addition & 0 deletions src/opover.c
Expand Up @@ -385,6 +385,7 @@ Expression *ArrayExp::op_overload(Scope *sc)
currentDimension = i; // Dimension for $, if required

x = x->semantic(sc);
x = resolveProperties(sc, x);
if (!x->type)
error("%s has no value", x->toChars());
if (lengthVar)
Expand Down

0 comments on commit 0e7942a

Please sign in to comment.