Skip to content

Commit

Permalink
allow opDollar to match any declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinNowak committed Oct 28, 2012
1 parent 091446b commit a38038e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 19 deletions.
41 changes: 22 additions & 19 deletions src/dsymbol.c
Expand Up @@ -1364,31 +1364,30 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
}
assert(ad);

Dsymbol *dsym = search_function(ad, Id::opDollar);
if (!dsym) // no dollar exists -- search in higher scope
Dsymbol *s = ad->search(loc, Id::opDollar, 0);
if (!s) // no dollar exists -- search in higher scope
return NULL;
s = s->toAlias();

// Check for multi-dimensional opDollar(dim)(). Only for ArrayExp.
Expression *e;
TemplateDeclaration *td;
if (exp->op == TOKarray && (td = dsym->isTemplateDeclaration()))
{ ArrayExp *ae = (ArrayExp *)exp;
// Check for multi-dimensional opDollar(dim)(). Only for ArrayExp.
if (exp->op == TOKarray && (td = s->isTemplateDeclaration()))
{
ArrayExp *ae = (ArrayExp *)exp;
// Instantiate opDollar!(dim) with the index as a template argument
Objects *tdargs = new Objects();
tdargs->setDim(1);

Expression *x = new IntegerExp(0, ae->currentDimension, Type::tsize_t);
x = x->semantic(sc);
tdargs->data[0] = x;
Expression *dim = new IntegerExp(0, ae->currentDimension, Type::tsize_t);
dim = dim->semantic(sc);
tdargs->push(dim);

//TemplateInstance *ti = new TemplateInstance(loc, td, tdargs);
//ti->semantic(sc);

DotTemplateInstanceExp *dte = new DotTemplateInstanceExp(loc, ae->e1, td->ident, tdargs);

v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(0, dte));
e = new DotTemplateInstanceExp(loc, ae->e1, td->ident, tdargs);
}
else
{ /* opDollar exists, but it's a function, not a template.
{ /* opDollar exists, but it's not a template.
* This is acceptable ONLY for single-dimension indexing.
* Note that it's impossible to have both template & function opDollar,
* because both take no arguments.
Expand All @@ -1398,12 +1397,16 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
exp->error("%s only defines opDollar for one dimension", ad->toChars());
return NULL;
}
FuncDeclaration *fd = dsym->isFuncDeclaration();
assert(fd);
Expression * x = new DotVarExp(loc, ce, fd);

v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(0, x));
Declaration *d = s->isDeclaration();
assert(d);
e = new DotVarExp(loc, ce, d);
}
e = e->semantic(sc);
if (!e->type)
exp->error("%s has no value", e->toChars());
if ((t = e->type->toBasetype()) && t->ty == Tfunction)
e = new CallExp(e->loc, e);
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(0, e));
}
else
{ /* For arrays, $ will either be a compile-time constant
Expand Down
18 changes: 18 additions & 0 deletions test/runnable/opover2.d
@@ -1,3 +1,4 @@
// PERMUTE_ARGS: -inline -O -property

// Test operator overloading

Expand Down Expand Up @@ -881,6 +882,23 @@ void test18()
assert((slice[0 .. $] += 2) == [2, 0, 8]);
assert((slice[0 .. $-1] += 2) == [2, 0, 7]);
assert((slice[$-3 .. $-1] += 2) == [2, 5, 7]);

// test different kinds of opDollar
auto dollar(string opDollar)()
{
static struct Dollar
{
size_t opIndex(size_t a) { return a; }
mixin(opDollar);
}
Dollar d;
return d[$];
}
assert(dollar!q{@property size_t opDollar() { return 8; }}() == 8);
assert(dollar!q{template opDollar(size_t dim) { enum opDollar = dim; }}() == 0);
assert(dollar!q{const size_t opDollar = 8;}() == 8);
assert(dollar!q{enum opDollar = 8;}() == 8);
assert(dollar!q{size_t length() { return 8; } alias length opDollar;}() == 8);
}

/**************************************/
Expand Down

0 comments on commit a38038e

Please sign in to comment.