[svn] r7720: nemerle/trunk/ncc: testsuite/positive/operators2.n typing/Typer-CallTyper.n typing/Typer-Dela...

divan svnadmin at nemerle.org
Thu Jun 28 22:12:26 CEST 2007


Log:
Improve delayed operators (fix 635, 1026).

Author: divan
Date: Thu Jun 28 22:12:21 2007
New Revision: 7720

Added:
   nemerle/trunk/ncc/testsuite/positive/operators2.n
Modified:
   nemerle/trunk/ncc/typing/Typer-CallTyper.n
   nemerle/trunk/ncc/typing/Typer-DelayedTyping.n
   nemerle/trunk/ncc/typing/Typer.n

Added: nemerle/trunk/ncc/testsuite/positive/operators2.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/positive/operators2.n	Thu Jun 28 22:12:21 2007
@@ -0,0 +1,89 @@
+using Nemerle.Collections.List;
+using System.Console;
+
+module Bug635 {
+
+  [Record]
+  public class T0 { //simplified bug 635
+    public x : list [int];
+    public y : list [int];
+
+    public static @+ (_a : T0, _b : T0) : T0 {
+      def f = _ + _;
+      def _g = f(1, 2);
+      null;
+    }
+  }
+
+  [Record]
+  public class T { //bug 635
+    public x : list [int];
+    public y : list [int];
+
+    public static @+ (a : T, b : T) : T {
+      T (Map2 (a.x, b.x, _ + _), Map2 (a.y, b.y, _ + _))
+    }
+  }
+
+  public Go () : void {
+    _ = T0 ([], []) + T0 ([], []);
+    def a = T ([1], [2, 3]);
+    def b = T ([4], [5, 6]);
+    def c = a + b;
+    WriteLine ($"$(c.x) $(c.y)");
+  }
+}
+
+
+namespace A {
+using System;
+using Bug1026.DateHelper;
+
+module Bug1026 {
+
+  public class DateHelper {
+    public static @+ (date : DateTime, delta : double) : DateTime {
+      date.AddDays (delta);
+    }
+    public static @+ (_ : int, _ : DateTime) : int {
+      1
+    }
+  }
+  public Go () : void {
+    def x = [1.0].FoldLeft (2.0, _ + _);
+    WriteLine (x);
+    def x = 2 + DateTime ();
+    WriteLine (x);
+    _ = DateTime () + 1;
+  }  
+}
+}
+
+namespace B {
+using System.UInt32; 
+//this makes only one global op_Addition, which caused bugs
+
+module BugSingle {
+  
+  public Go () : void {
+    def a = (_ + _) ([1], [2]);
+    def b = (_ + _) (1, 2);
+    def c = [1].FoldLeft (2, _ + _);
+    WriteLine ($"$a $b $c")
+  }
+}
+}
+
+
+Bug635.Go ();
+A.Bug1026.Go ();
+B.BugSingle.Go ();
+
+/*
+BEGIN-OUTPUT
+[5] [7, 9]
+3
+1
+[1, 2] 3 3
+END-OUTPUT
+*/

Modified: nemerle/trunk/ncc/typing/Typer-CallTyper.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer-CallTyper.n	(original)
+++ nemerle/trunk/ncc/typing/Typer-CallTyper.n	Thu Jun 28 22:12:21 2007
@@ -183,9 +183,13 @@
       {
         //Message.Debug ($ "$(parm.expr.Type) <<< $ftype");
 
-        Util.cassert (parm.required_type == null);
         when (is_final)
+        {
+          if (parm.required_type == null)
           parm.required_type = ftype;
+          else
+            _ = parm.required_type.Provide (ftype);
+        }
 
         def msg =
           if (messenger.NeedMessage)
@@ -566,4 +570,3 @@
     }
   }
 }
-

Modified: nemerle/trunk/ncc/typing/Typer-DelayedTyping.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer-DelayedTyping.n	(original)
+++ nemerle/trunk/ncc/typing/Typer-DelayedTyping.n	Thu Jun 28 22:12:21 2007
@@ -87,6 +87,10 @@
       {
         | MemberAccess { expr : TExpr; name : PT.Name; }
         | Overloaded { overloads : list [OverloadPossibility]; }
+        | OverloadedOperator { overloads : list [OverloadPossibility]; 
+                               t1 : TyVar; t2 : TyVar; name : string; env : GlobalEnv; 
+                               seen : list [OverloadPossibility];
+                             }
         | Operator { t1 : TyVar; t2 : TyVar; name : string; env : GlobalEnv; }
         | Resolved { expr : TExpr; }
         | Macro { action : DelayedAction }
@@ -142,11 +146,14 @@
               }
             | Kind.Overloaded (lst) =>
               Kind.Overloaded (OverloadPossibility.Unique (lst))
+            | Kind.OverloadedOperator (lst, t1, t2, n, e, s) =>
+              Kind.OverloadedOperator (OverloadPossibility.Unique (lst), t1, t2, n, e, s)
             | _ => k
           }
 
         when (generic_specifier != null)
           match (k) {
+            | Kind.OverloadedOperator (lst, _, _, _, _, _) 
             | Kind.Overloaded (lst) =>
               foreach (o in lst)
                 o.SetGenericSpecifier (generic_specifier);
@@ -198,6 +205,7 @@
       { 
         get {
           match (DtKind) {
+            | Kind.OverloadedOperator (lst, _, _, _, _, _) 
             | Kind.Overloaded (lst) =>
               List.ForAll (lst, fun (op : OverloadPossibility) {
                 match (op.Member) {
@@ -219,6 +227,7 @@
       {
         get {
           match (DtKind) {
+            | Kind.OverloadedOperator (lst, _, _, _, _, _) 
             | Kind.Overloaded (lst) =>
               lst.ForAll (fun (op) { op.Member is IMethod })
 
@@ -258,6 +267,7 @@
           | Kind.Macro
           | Kind.Error => true
 
+          | Kind.OverloadedOperator 
           | Kind.Operator => false
         }
       }
@@ -273,6 +283,20 @@
         }
 
         match (DtKind) {
+          | Kind.OverloadedOperator (lst, t1, t2, n, e, s) => 
+            when (InternalType.Object_tc.LookupMember (name) is []) {
+              // otherwise it's pointless
+              def newlst = List.RevFilter (lst, fun (o : OverloadPossibility) {
+                match (o.Type.Hint) {
+                  | Some (mt) => can_have (mt)
+                  | None => true // we don't yet know
+                }
+              });
+
+              if (newlst is []) {}
+              else SetKind (Kind.OverloadedOperator (newlst, t1, t2, n, e, s));
+            }
+          
           | Kind.Overloaded (lst) =>
             when (InternalType.Object_tc.LookupMember (name) is []) {
               // otherwise it's pointless
@@ -327,6 +351,10 @@
           | Operator (t1, t2, name, _) =>
             $ "operator `$(name)' on $(t1)"
             + (if (t2 == null) "" else $ " and $(t2)")
+          | OverloadedOperator (lst, t1, t2, name, _, _) => 
+            $ "overloaded operator `$(name)' on $(t1)"
+            + (if (t2 == null) "" else $ " and $(t2)") + "\n" 
+            + lst.ToString ("\n ")
           | Macro (action) => action.ToString ()
         }
       }
@@ -335,6 +363,16 @@
       public GetDescriptionForError () : list [string]
       {
         match (DtKind) {
+          | OverloadedOperator (overloads, t1, t2, name, _env, _seen) =>
+            def used (o) { o.UsedLastTime }
+            "ambiguity between operator " +
+            $"$name($t1" + (if (t2 != null) $", $t2" else "") + ")"
+            " overloads:" :: 
+            (if (overloads.Exists (used))
+               overloads.Filter (used) 
+             else 
+             overloads).Map (x => $"Posible overload: $x")
+            
           | Overloaded (overloads) =>
             def used (o) { o.UsedLastTime }
             "ambiguity between overloads:" :: 
@@ -360,7 +398,7 @@
 
       public IsOverloaded : bool
       {
-        get { DtKind is Kind.Overloaded }
+        get { DtKind is Kind.Overloaded || DtKind is Kind.OverloadedOperator }
       }
 
 
@@ -376,6 +414,7 @@
           match (DtKind) {
             | MemberAccess
             | Overloaded
+            | OverloadedOperator
             | Error
             | Operator => true
             | Resolved
@@ -632,6 +671,63 @@
                 | lst =>
                   SetKind (Kind.Overloaded (lst))
               }
+          | Kind.OverloadedOperator (overloads, t1, t2, name, env, seen) =>
+            def not_seen (l) { 
+              | None with l = []
+              | Some (l) =>
+                l.Filter ( fun (x) { !seen.Contains (x) } );
+            }
+            def new_operators = not_seen (LookupOperator (t1, name)) + not_seen (LookupOperator (t2, name));
+            def seen = new_operators + seen;
+            def added = 
+              match (new_operators) {
+                | lst when lst != [] =>
+                  def lst = OverloadPossibility.Unique (overloads + lst);
+                  if (lst == overloads)
+                    false
+                  else
+                  {
+                    SetKind (Kind.OverloadedOperator (lst, t1, t2, name, env, seen));
+                    true
+                  }
+                | _ => false
+              }
+            unless (added)
+            {
+                def args = if (t2 == null) 1 else 2;
+                def hints = (if (t1.Hint.IsSome) 1 else 0) + (if (t2 != null && t2.Hint.IsSome) 1 else 0);
+
+                def expr = DtKind.filtering_expression;
+                def o' =
+                  if (expr == null) {
+                    RemoveExtensionMethods (OverloadPossibility.OnlyPossible (overloads, expected))
+                  } else {
+                    if (typer.Expect (expected, expr.func.Type, 
+                                        "overloaded function call"))
+                      match (overloads) {
+                        | [one] when hints == 0 
+                                  || typer.BadnessAllowed > 1 => 
+                          [one] //don't call ResolveOverload early, as it can add wrong hints
+                        | _ => ResolveOverload (overloads, expr.parms, expr.Type)
+                      }
+                    else
+                      []
+                  }
+           
+                when (o'.Length != overloads.Length || o'.Length == 1)
+                  match (o') {
+                    | [] =>
+                      SetKind (Kind.Error ())
+                  
+                    | [one] when hints == args
+                              || hints > 0 && typer.BadnessAllowed > 0
+                              || typer.BadnessAllowed > 1 =>
+                      SetKind (Kind.Resolved (one.Compile ()))
+           
+                    | lst =>
+                      SetKind (Kind.OverloadedOperator (lst, t1, t2, name, env, seen));
+                  }
+              }
             
           | Kind.Operator (t1, t2, name, env) =>
             def operators =
@@ -660,7 +756,7 @@
                 SetKind (Kind.Error ())
                 
               | Some (lst) =>
-                SetKind (Kind.Overloaded (lst));
+                SetKind (Kind.OverloadedOperator (lst, t1, t2, name, env, lst));
                 Resolve ()
                 
               | None => {}

Modified: nemerle/trunk/ncc/typing/Typer.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer.n	(original)
+++ nemerle/trunk/ncc/typing/Typer.n	Thu Jun 28 22:12:21 2007
@@ -386,7 +386,7 @@
         }
       });
 
-      def max_badness = 1;
+      def max_badness = 2;
 
       if (did_something)
         RunDelayedTypings ();



More information about the svn mailing list