Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Issue 3382 - [tdpl] Implement uniform function call syntax #582

Merged
merged 2 commits into from about 2 years ago

4 participants

Hara Kenji Walter Bright Brad Roberts Andrei Alexandrescu
Hara Kenji
Collaborator

http://d.puremagic.com/issues/show_bug.cgi?id=3382

This pull contains a small lexer fix.
To allow 1.prop syntax, short floating point syntax (e.g. 1.f, 1.Li) are disallowed.

Supplemental change of Phobos: phobos/pull/#378

Walter Bright WalterBright commented on the diff December 26, 2011
src/expression.c
... ...
@@ -6595,6 +6595,25 @@ void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6595 6595
         e = e->semantic(sc);
6596 6596
         return e;
6597 6597
     }
  6598
+    else if ((t1b->isTypeBasic() && t1b->ty != Tvoid) ||
  6599
+             t1b->ty == Tenum || t1b->ty == Tnull)
  6600
+    {   /* If ident is not a valid property, rewrite:
  6601
+         *   e1.ident
  6602
+         * as:
  6603
+         *   .ident(e1)
  6604
+         */
4
Walter Bright Owner

I'm not sure what the justification is for this rewrite. And, of course, anything that uses gagging I'm very nervous about and want to avoid as much as possible.

Hara Kenji Collaborator
9rnsr added a note December 26, 2011

I thought that "uniform" means all types of objects, not only array + user-defined types. Is it my mistake?
And yes, use gagging is ugly, but at least it works for array UFCS. I'd also like to reduce use of them in the future, but today it's difficult.

Andrei Alexandrescu Owner
andralex added a note January 21, 2012

What does gagging mean?

Anyway, Kenji is right: uniform call syntax must apply to all types as a last resort. This has been agreed upon and consequently is part of TDPL.

It saves a lot of boilerplate, see D-Programming-Language/phobos#365. Also a lot of code in std.container consists of forwarding and aliasing that implement a rich interface in terms of a simpler one.

To recap: if all attempts to resolve a.b(c) fail, the call should be rewritten as b(a, c) and retried. The symbol "b" is looked up with the normal rules, i.e. it could be found in a different module than a's, which allows a module to extend functionality of a type defined by another module.

Hara Kenji Collaborator
9rnsr added a note January 22, 2012

In dmd source, "gagging" means that suppress any errors that raised in compilation.
In this case with x.prop, compiler will replace it to prop(x) with gagging errors that the fail of searching prop function/property from typeof(x), instead of raising them.

Thanks for comment, Andrei. Issue 662 is the report of UFCS with basic types.
I think you should write comment in both 3382 and 662.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Walter Bright

Is there any way to just pull ff7e522?

Hara Kenji
Collaborator

Is there any way to just pull ff7e522?

Opened a pull request contains just only ff7e522.
#583

Brad Roberts
Owner

This pull request seems to cause dmd to go into an infinite loop. Every platform stalls when it gets to this pull request. I'm going to put in a quick hack to the auto-tester to skip it until it's been fixed.

Hara Kenji
Collaborator
9rnsr commented March 02, 2012

Sorry, I close this pull temporary.

Hara Kenji 9rnsr closed this March 02, 2012
Hara Kenji 9rnsr reopened this March 02, 2012
Hara Kenji
Collaborator
9rnsr commented March 02, 2012

Fixed.

Walter Bright WalterBright merged commit b7742f7 into from March 07, 2012
Walter Bright WalterBright closed this March 07, 2012
Brad Roberts braddr referenced this pull request from a commit October 21, 2012
Commit has since been removed from the repository and is no longer available.
Deleted user Unknown referenced this pull request from a commit December 24, 2013
Commit has since been removed from the repository and is no longer available.
Deleted user Unknown referenced this pull request from a commit December 25, 2013
Commit has since been removed from the repository and is no longer available.
Deleted user Unknown referenced this pull request from a commit December 25, 2013
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 1 author.

Mar 06, 2012
fix Issue 3382 - [tdpl] Implement uniform function call syntax 984dac3
Mar 07, 2012
Fix unintended infinite loop in Phobos build 41229fb
This page is out of date. Refresh to see the latest.
94  src/expression.c
@@ -6562,6 +6562,25 @@ Expression *DotIdExp::semantic(Scope *sc, int flag)
6562 6562
         e = e->semantic(sc);
6563 6563
         return e;
6564 6564
     }
  6565
+    else if ((t1b->isTypeBasic() && t1b->ty != Tvoid) ||
  6566
+             t1b->ty == Tenum || t1b->ty == Tnull)
  6567
+    {   /* If ident is not a valid property, rewrite:
  6568
+         *   e1.ident
  6569
+         * as:
  6570
+         *   .ident(e1)
  6571
+         */
  6572
+        unsigned errors = global.startGagging();
  6573
+        Type *t1 = e1->type;
  6574
+        e = e1->type->dotExp(sc, e1, ident);
  6575
+        if (global.endGagging(errors))    // if failed to find the property
  6576
+        {
  6577
+            e1->type = t1;              // kludge to restore type
  6578
+            e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident);
  6579
+            e = new CallExp(loc, e, e1);
  6580
+        }
  6581
+        e = e->semantic(sc);
  6582
+        return e;
  6583
+    }
6565 6584
 #endif
6566 6585
     else
6567 6586
     {
@@ -7069,7 +7088,7 @@ Expression *CallExp::syntaxCopy()
7069 7088
 
7070 7089
 Expression *CallExp::resolveUFCS(Scope *sc)
7071 7090
 {
7072  
-    Expression *ethis = NULL;
  7091
+    Expression *e = NULL;
7073 7092
     DotIdExp *dotid;
7074 7093
     DotTemplateInstanceExp *dotti;
7075 7094
     Identifier *ident;
@@ -7078,46 +7097,73 @@ Expression *CallExp::resolveUFCS(Scope *sc)
7078 7097
     {
7079 7098
         dotid = (DotIdExp *)e1;
7080 7099
         ident = dotid->ident;
7081  
-        ethis = dotid->e1 = dotid->e1->semantic(sc);
7082  
-        if (ethis->op == TOKdotexp)
  7100
+        e = dotid->e1 = dotid->e1->semantic(sc);
  7101
+        if (e->op == TOKdotexp)
7083 7102
             return NULL;
7084  
-        ethis = resolveProperties(sc, ethis);
  7103
+        e = resolveProperties(sc, e);
7085 7104
     }
7086 7105
     else if (e1->op == TOKdotti)
7087 7106
     {
7088 7107
         dotti = (DotTemplateInstanceExp *)e1;
7089 7108
         ident = dotti->ti->name;
7090  
-        ethis = dotti->e1 = dotti->e1->semantic(sc);
7091  
-        if (ethis->op == TOKdotexp)
  7109
+        e = dotti->e1 = dotti->e1->semantic(sc);
  7110
+        if (e->op == TOKdotexp)
7092 7111
             return NULL;
7093  
-        ethis = resolveProperties(sc, ethis);
  7112
+        e = resolveProperties(sc, e);
7094 7113
     }
7095 7114
 
7096  
-    if (ethis && ethis->type)
  7115
+    if (e && e->type)
7097 7116
     {
  7117
+        if (e->op == TOKtype || e->op == TOKimport)
  7118
+            return NULL;
  7119
+        //printf("resolveUCSS %s, e->op = %s\n", toChars(), Token::toChars(e->op));
7098 7120
         AggregateDeclaration *ad;
  7121
+        Expression *esave = e;
7099 7122
 Lagain:
7100  
-        Type *tthis = ethis->type->toBasetype();
7101  
-        if (tthis->ty == Tclass)
  7123
+        Type *t = e->type->toBasetype();
  7124
+        if (t->ty == Tpointer)
  7125
+        {   Type *tn = t->nextOf();
  7126
+            if (tn->ty == Tclass || tn->ty == Tstruct)
  7127
+            {
  7128
+                e = new PtrExp(e->loc, e);
  7129
+                e = e->semantic(sc);
  7130
+                t = e->type->toBasetype();
  7131
+            }
  7132
+        }
  7133
+        if (t->ty == Tclass)
7102 7134
         {
7103  
-            ad = ((TypeClass *)tthis)->sym;
7104  
-            if (search_function(ad, ident))
7105  
-                return NULL;
  7135
+            ad = ((TypeClass *)t)->sym;
7106 7136
             goto L1;
7107 7137
         }
7108  
-        else if (tthis->ty == Tstruct)
  7138
+        else if (t->ty == Tstruct)
7109 7139
         {
7110  
-            ad = ((TypeStruct *)tthis)->sym;
7111  
-            if (search_function(ad, ident))
7112  
-                return NULL;
  7140
+            ad = ((TypeStruct *)t)->sym;
7113 7141
         L1:
  7142
+            if (ad->search(loc, ident, 0))
  7143
+                return NULL;
7114 7144
             if (ad->aliasthis)
7115 7145
             {
7116  
-                ethis = resolveAliasThis(sc, ethis);
  7146
+                e = resolveAliasThis(sc, e);
7117 7147
                 goto Lagain;
7118 7148
             }
  7149
+            if (ad->search(loc, Id::opDot, 0))
  7150
+            {
  7151
+                e = new DotIdExp(e->loc, e, Id::opDot);
  7152
+                e = e->semantic(sc);
  7153
+                e = resolveProperties(sc, e);
  7154
+                goto Lagain;
  7155
+            }
  7156
+            if (ad->search(loc, Id::opDispatch, 0))
  7157
+                return NULL;
  7158
+            e = esave;
  7159
+            goto Lshift;
  7160
+        }
  7161
+        else if ((t->isTypeBasic() && t->ty != Tvoid) ||
  7162
+                 t->ty == Tenum || t->ty == Tnull)
  7163
+        {
  7164
+            goto Lshift;
7119 7165
         }
7120  
-        else if (tthis->ty == Taarray && e1->op == TOKdot)
  7166
+        else if (t->ty == Taarray && e1->op == TOKdot)
7121 7167
         {
7122 7168
             if (ident == Id::remove)
7123 7169
             {
@@ -7132,20 +7178,20 @@ Expression *CallExp::resolveUFCS(Scope *sc)
7132 7178
                 key = key->semantic(sc);
7133 7179
                 key = resolveProperties(sc, key);
7134 7180
 
7135  
-                TypeAArray *taa = (TypeAArray *)tthis;
  7181
+                TypeAArray *taa = (TypeAArray *)t;
7136 7182
                 key = key->implicitCastTo(sc, taa->index);
7137 7183
 
7138 7184
                 if (!key->rvalue())
7139 7185
                     return new ErrorExp();
7140 7186
 
7141  
-                return new RemoveExp(loc, ethis, key);
  7187
+                return new RemoveExp(loc, e, key);
7142 7188
             }
7143 7189
             else if (ident == Id::apply || ident == Id::applyReverse)
7144 7190
             {
7145 7191
                 return NULL;
7146 7192
             }
7147 7193
             else
7148  
-            {   TypeAArray *taa = (TypeAArray *)tthis;
  7194
+            {   TypeAArray *taa = (TypeAArray *)t;
7149 7195
                 assert(taa->ty == Taarray);
7150 7196
                 StructDeclaration *sd = taa->getImpl();
7151 7197
                 Dsymbol *s = sd->search(0, ident, 2);
@@ -7154,12 +7200,12 @@ Expression *CallExp::resolveUFCS(Scope *sc)
7154 7200
                 goto Lshift;
7155 7201
             }
7156 7202
         }
7157  
-        else if (tthis->ty == Tarray || tthis->ty == Tsarray)
  7203
+        else if (t->ty == Tarray || t->ty == Tsarray)
7158 7204
         {
7159 7205
 Lshift:
7160 7206
             if (!arguments)
7161 7207
                 arguments = new Expressions();
7162  
-            arguments->shift(ethis);
  7208
+            arguments->shift(e);
7163 7209
             if (e1->op == TOKdot)
7164 7210
             {
7165 7211
                 /* Transform:
77  test/runnable/ufcs.d
... ...
@@ -0,0 +1,77 @@
  1
+module ufcs;
  2
+
  3
+extern (C) int printf(const char*, ...);
  4
+
  5
+/*******************************************/
  6
+// 662
  7
+
  8
+import std.stdio,std.string, std.conv;
  9
+
  10
+enum Etest
  11
+{
  12
+    a,b,c,d
  13
+}
  14
+
  15
+//typedef int testi = 10;
  16
+//typedef Test Test2;
  17
+
  18
+int test() { return 33; }
  19
+
  20
+class Test
  21
+{
  22
+    static int test(int i) { return i; }
  23
+}
  24
+
  25
+int test(Etest test)
  26
+{
  27
+    return cast(int)test;
  28
+}
  29
+
  30
+//int test(testi i)
  31
+//{
  32
+//  return cast(int)i;
  33
+//}
  34
+
  35
+void test682()
  36
+{
  37
+    assert(22.to!string() == "22");
  38
+    assert((new Test).test(11) == 11);
  39
+    assert(Test.test(11) == 11);
  40
+    //assert(Test2.test(11) == 11);
  41
+    assert(test() == 33);
  42
+    assert(ufcs.test() == 33);
  43
+    assert(Etest.d.test() == Etest.d);
  44
+    //testi i;
  45
+    //assert(i.test() == i.init);
  46
+}
  47
+
  48
+/*******************************************/
  49
+// 3382
  50
+
  51
+import std.range, std.algorithm;
  52
+
  53
+@property T twice(T)(T x){ return x * x; }
  54
+real toreal(ireal x){ return x.im; }
  55
+char toupper(char c){ return ('a'<=c && c<='z') ? cast(char)(c - 'a' + 'A') : c; }
  56
+
  57
+@property ref T setter(T)(ref T x, T v){ x = v; return x; }
  58
+
  59
+void test3382()
  60
+{
  61
+    auto r = iota(0, 10).map!"a*3"().filter!"a%2 != 0"();
  62
+    foreach (e; r)
  63
+        printf("e = %d\n", e);
  64
+
  65
+    assert(10.twice == 100);
  66
+    assert(0.5.twice == 0.25);
  67
+    assert(1.4i.toreal() == 1.4);
  68
+    assert('c'.toupper() == 'C');
  69
+}
  70
+
  71
+/*******************************************/
  72
+
  73
+void main()
  74
+{
  75
+    test682();
  76
+    test3382();
  77
+}
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.