Skip to content

Commit

Permalink
Merge pull request #582 from 9rnsr/fix3382_ufcs
Browse files Browse the repository at this point in the history
Issue 3382 - [tdpl] Implement uniform function call syntax
  • Loading branch information
WalterBright committed Mar 8, 2012
2 parents ca1eadb + 41229fb commit b7742f7
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 24 deletions.
94 changes: 70 additions & 24 deletions src/expression.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -6562,6 +6562,25 @@ Expression *DotIdExp::semantic(Scope *sc, int flag)
e = e->semantic(sc); e = e->semantic(sc);
return e; return e;
} }
else if ((t1b->isTypeBasic() && t1b->ty != Tvoid) ||
t1b->ty == Tenum || t1b->ty == Tnull)
{ /* If ident is not a valid property, rewrite:
* e1.ident
* as:
* .ident(e1)
*/
unsigned errors = global.startGagging();
Type *t1 = e1->type;
e = e1->type->dotExp(sc, e1, ident);
if (global.endGagging(errors)) // if failed to find the property
{
e1->type = t1; // kludge to restore type
e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident);
e = new CallExp(loc, e, e1);
}
e = e->semantic(sc);
return e;
}
#endif #endif
else else
{ {
Expand Down Expand Up @@ -7069,7 +7088,7 @@ Expression *CallExp::syntaxCopy()


Expression *CallExp::resolveUFCS(Scope *sc) Expression *CallExp::resolveUFCS(Scope *sc)
{ {
Expression *ethis = NULL; Expression *e = NULL;
DotIdExp *dotid; DotIdExp *dotid;
DotTemplateInstanceExp *dotti; DotTemplateInstanceExp *dotti;
Identifier *ident; Identifier *ident;
Expand All @@ -7078,46 +7097,73 @@ Expression *CallExp::resolveUFCS(Scope *sc)
{ {
dotid = (DotIdExp *)e1; dotid = (DotIdExp *)e1;
ident = dotid->ident; ident = dotid->ident;
ethis = dotid->e1 = dotid->e1->semantic(sc); e = dotid->e1 = dotid->e1->semantic(sc);
if (ethis->op == TOKdotexp) if (e->op == TOKdotexp)
return NULL; return NULL;
ethis = resolveProperties(sc, ethis); e = resolveProperties(sc, e);
} }
else if (e1->op == TOKdotti) else if (e1->op == TOKdotti)
{ {
dotti = (DotTemplateInstanceExp *)e1; dotti = (DotTemplateInstanceExp *)e1;
ident = dotti->ti->name; ident = dotti->ti->name;
ethis = dotti->e1 = dotti->e1->semantic(sc); e = dotti->e1 = dotti->e1->semantic(sc);
if (ethis->op == TOKdotexp) if (e->op == TOKdotexp)
return NULL; return NULL;
ethis = resolveProperties(sc, ethis); e = resolveProperties(sc, e);
} }


if (ethis && ethis->type) if (e && e->type)
{ {
if (e->op == TOKtype || e->op == TOKimport)
return NULL;
//printf("resolveUCSS %s, e->op = %s\n", toChars(), Token::toChars(e->op));
AggregateDeclaration *ad; AggregateDeclaration *ad;
Expression *esave = e;
Lagain: Lagain:
Type *tthis = ethis->type->toBasetype(); Type *t = e->type->toBasetype();
if (tthis->ty == Tclass) if (t->ty == Tpointer)
{ Type *tn = t->nextOf();
if (tn->ty == Tclass || tn->ty == Tstruct)
{
e = new PtrExp(e->loc, e);
e = e->semantic(sc);
t = e->type->toBasetype();
}
}
if (t->ty == Tclass)
{ {
ad = ((TypeClass *)tthis)->sym; ad = ((TypeClass *)t)->sym;
if (search_function(ad, ident))
return NULL;
goto L1; goto L1;
} }
else if (tthis->ty == Tstruct) else if (t->ty == Tstruct)
{ {
ad = ((TypeStruct *)tthis)->sym; ad = ((TypeStruct *)t)->sym;
if (search_function(ad, ident))
return NULL;
L1: L1:
if (ad->search(loc, ident, 0))
return NULL;
if (ad->aliasthis) if (ad->aliasthis)
{ {
ethis = resolveAliasThis(sc, ethis); e = resolveAliasThis(sc, e);
goto Lagain; goto Lagain;
} }
if (ad->search(loc, Id::opDot, 0))
{
e = new DotIdExp(e->loc, e, Id::opDot);
e = e->semantic(sc);
e = resolveProperties(sc, e);
goto Lagain;
}
if (ad->search(loc, Id::opDispatch, 0))
return NULL;
e = esave;
goto Lshift;
}
else if ((t->isTypeBasic() && t->ty != Tvoid) ||
t->ty == Tenum || t->ty == Tnull)
{
goto Lshift;
} }
else if (tthis->ty == Taarray && e1->op == TOKdot) else if (t->ty == Taarray && e1->op == TOKdot)
{ {
if (ident == Id::remove) if (ident == Id::remove)
{ {
Expand All @@ -7132,20 +7178,20 @@ Expression *CallExp::resolveUFCS(Scope *sc)
key = key->semantic(sc); key = key->semantic(sc);
key = resolveProperties(sc, key); key = resolveProperties(sc, key);


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


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


return new RemoveExp(loc, ethis, key); return new RemoveExp(loc, e, key);
} }
else if (ident == Id::apply || ident == Id::applyReverse) else if (ident == Id::apply || ident == Id::applyReverse)
{ {
return NULL; return NULL;
} }
else else
{ TypeAArray *taa = (TypeAArray *)tthis; { TypeAArray *taa = (TypeAArray *)t;
assert(taa->ty == Taarray); assert(taa->ty == Taarray);
StructDeclaration *sd = taa->getImpl(); StructDeclaration *sd = taa->getImpl();
Dsymbol *s = sd->search(0, ident, 2); Dsymbol *s = sd->search(0, ident, 2);
Expand All @@ -7154,12 +7200,12 @@ Expression *CallExp::resolveUFCS(Scope *sc)
goto Lshift; goto Lshift;
} }
} }
else if (tthis->ty == Tarray || tthis->ty == Tsarray) else if (t->ty == Tarray || t->ty == Tsarray)
{ {
Lshift: Lshift:
if (!arguments) if (!arguments)
arguments = new Expressions(); arguments = new Expressions();
arguments->shift(ethis); arguments->shift(e);
if (e1->op == TOKdot) if (e1->op == TOKdot)
{ {
/* Transform: /* Transform:
Expand Down
77 changes: 77 additions & 0 deletions test/runnable/ufcs.d
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,77 @@
module ufcs;

extern (C) int printf(const char*, ...);

/*******************************************/
// 662

import std.stdio,std.string, std.conv;

enum Etest
{
a,b,c,d
}

//typedef int testi = 10;
//typedef Test Test2;

int test() { return 33; }

class Test
{
static int test(int i) { return i; }
}

int test(Etest test)
{
return cast(int)test;
}

//int test(testi i)
//{
// return cast(int)i;
//}

void test682()
{
assert(22.to!string() == "22");
assert((new Test).test(11) == 11);
assert(Test.test(11) == 11);
//assert(Test2.test(11) == 11);
assert(test() == 33);
assert(ufcs.test() == 33);
assert(Etest.d.test() == Etest.d);
//testi i;
//assert(i.test() == i.init);
}

/*******************************************/
// 3382

import std.range, std.algorithm;

@property T twice(T)(T x){ return x * x; }
real toreal(ireal x){ return x.im; }
char toupper(char c){ return ('a'<=c && c<='z') ? cast(char)(c - 'a' + 'A') : c; }

@property ref T setter(T)(ref T x, T v){ x = v; return x; }

void test3382()
{
auto r = iota(0, 10).map!"a*3"().filter!"a%2 != 0"();
foreach (e; r)
printf("e = %d\n", e);

assert(10.twice == 100);
assert(0.5.twice == 0.25);
assert(1.4i.toreal() == 1.4);
assert('c'.toupper() == 'C');
}

/*******************************************/

void main()
{
test682();
test3382();
}

1 comment on commit b7742f7

@torarin
Copy link

@torarin torarin commented on b7742f7 Mar 8, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very exciting!

Please sign in to comment.