[svn] r5953: nemerle/trunk/ncc: testsuite/negative/delayed-indexers.n testsuite/positive/delayed-indexers....

malekith svnadmin at nemerle.org
Sun Nov 20 19:38:00 CET 2005


Log:
Support delayed indexers.

Author: malekith
Date: Sun Nov 20 19:37:58 2005
New Revision: 5953

Added:
   nemerle/trunk/ncc/testsuite/negative/delayed-indexers.n
   nemerle/trunk/ncc/testsuite/positive/delayed-indexers.n
Modified:
   nemerle/trunk/ncc/typing/Typer-DelayedTyping.n
   nemerle/trunk/ncc/typing/Typer.n

Added: nemerle/trunk/ncc/testsuite/negative/delayed-indexers.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/negative/delayed-indexers.n	Sun Nov 20 19:37:58 2005
@@ -0,0 +1,14 @@
+using Nemerle.Collections;
+
+module M { public set42 (x : ref int) : void { x = 42; } }
+
+def f (s) {
+  s [0] = 's'; // E: read-only
+}
+f ("foo");
+
+def g (a) {
+  M.set42 (ref a ["foo"]) // E: ref/out
+}
+def ht = Hashtable ();
+g (ht);

Added: nemerle/trunk/ncc/testsuite/positive/delayed-indexers.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/positive/delayed-indexers.n	Sun Nov 20 19:37:58 2005
@@ -0,0 +1,34 @@
+using Nemerle.Collections;
+
+module M { public set42 (x : ref int) : void { x = 42; } }
+
+def f (s) { s [0] == 's' }
+_ = f ("foo");
+
+def g (a) { a [0] = 12; }
+def a = array [1, 2];
+g (a);
+System.Console.WriteLine (a [0]);
+
+def g (a) { M.set42 (ref a [1]) }
+g (a);
+System.Console.WriteLine (a [1]);
+
+def g (a) { a ["foo"] = "bar"; }
+def ht = Hashtable ();
+g (ht);
+System.Console.WriteLine (ht ["foo"]);
+
+def g (a) { a [0][0] = 12; }
+def a = array [array [1]];
+g (a);
+System.Console.WriteLine (a [0][0]);
+
+/*
+BEGIN-OUTPUT
+12
+42
+bar
+12
+END-OUTPUT
+*/

Modified: nemerle/trunk/ncc/typing/Typer-DelayedTyping.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer-DelayedTyping.n	(original)
+++ nemerle/trunk/ncc/typing/Typer-DelayedTyping.n	Sun Nov 20 19:37:58 2005
@@ -39,6 +39,40 @@
 {
   public partial class Typer
   {
+    public abstract class DelayedAction
+    {
+      public abstract Resolve (fail_loudly : bool) : option [TExpr];
+
+      public override ToString () : string
+      {
+        "delayed macro"
+      }
+    }
+
+    public class DelayedLambdaAction : DelayedAction
+    {
+      desc : string;
+      fn : bool -> option [TExpr];
+
+      public override ToString () : string
+      { 
+        desc
+      }
+
+      public override Resolve (fail_loudly : bool) : option [TExpr]
+      {
+        fn (fail_loudly)
+      }
+      
+      public this (fn : bool -> option [TExpr], desc = "delayed typing action")
+      {
+        this.fn = fn;
+        this.desc = desc;
+      }
+    }
+
+    
+    // TODO: object model seems to fit better here, upgrade most kinds to use DelayedAction
     public class DelayedTyping : Located, Nemerle.IComparable [DelayedTyping]
     {
       id : int;
@@ -51,14 +85,17 @@
       [Record]
       public variant Kind
       {
-        | MemberAccess { expr : TExpr; name : string; mutable need_writable : bool; }
+        | MemberAccess { expr : TExpr; name : string; }
         | Overloaded { overloads : list [OverloadPossibility]; }
         | Operator { t1 : TyVar; t2 : TyVar; name : string; env : GlobalEnv; }
         | Resolved { expr : TExpr; }
-        | Macro { resolve : bool -> option [PT.PExpr]; }
+        | Macro { action : DelayedAction }
         | Error
 
         public mutable filtering_expression : TExpr.Call;
+        public mutable need_ref : bool;
+        public mutable need_write : bool;
+
         public this () {}
       }
       
@@ -123,14 +160,26 @@
           }
           
         def solver = Passes.Solver;
-        when (k.filtering_expression == null)
+
           match (solver.dt_store.Find (this)) {
             | Some (k') =>
-              k.filtering_expression = k'.filtering_expression
+            when (k.filtering_expression == null)
+              k.filtering_expression = k'.filtering_expression;
+            k.need_ref = k'.need_ref;
+            k.need_write = k'.need_write;
             | None => {}
           }
 
         solver.dt_store = solver.dt_store.Replace (this, k);
+
+        match (k) {
+          | Kind.Resolved (expr) =>
+            when (k.need_write)
+              typer.CheckLValue (expr, k.need_ref, 
+                 if (k.need_ref) "ref/out parameter"
+                 else "assignment target");
+          | _ => {}
+        }
       }
       
       
@@ -182,8 +231,14 @@
       
       public ExpectLValue (need_ref : bool) : bool
       {
-        match (DtKind) {
+        def kind = DtKind;
+        kind.need_write = true;
+        when (need_ref)
+          kind.need_ref = true;
+          
+        match (kind) {
           | Kind.Overloaded (lst) =>
+            !need_ref &&
             match (List.RevFilter (lst, fun (o : OverloadPossibility) {
               match (o.Member) {
                 | p is IProperty => p.IsMutable && !need_ref
@@ -193,15 +248,16 @@
             })) {
               | [] => false
               | newlst =>
-                when (newlst : object != lst)
                   SetKind (Kind.Overloaded (newlst));
                 true
             }
  
           | Kind.Resolved (r) => typer.IsLValue (r, need_ref)
-          | Kind.MemberAccess as ma => ma.need_writable = true; true
-          | Kind.Error => true
+
+          | Kind.MemberAccess
           | Kind.Macro
+          | Kind.Error => true
+
           | Kind.Operator => false
         }
       }
@@ -237,13 +293,12 @@
           | Error => "an error"
           | Overloaded (overloads) =>
             "ambiguity between overloads:\n  " + overloads.ToString ("\n  ")
-          | MemberAccess (expr, name, _) =>
+          | MemberAccess (expr, name) =>
             $ "accessing member `$(name)' in `$(expr)' : $(expr.Type)"
           | Operator (t1, t2, name, _) =>
             $ "operator `$(name)' on $(t1)"
             + (if (t2 == null) "" else $ " and $(t2)")
-          | Macro =>
-            "delayed macro"
+          | Macro (action) => action.ToString ()
         }
       }
 
@@ -258,10 +313,10 @@
                overloads.Filter (used) 
              else 
                overloads).ToString ("\n  ")
-          | Macro (resolve) =>
-            // the resolve function should dump the error message
+          | Macro (action) =>
+            // the Resolve function should dump the error message
             Util.locate (loc, {
-              def res = resolve (true);
+              def res = action.Resolve (true);
               when (res.IsSome)
                 Message.Error ($ "the macro resolution function unexpectedly succeeded "
                                  "when run for the second time, the result is "
@@ -477,7 +532,7 @@
         def solver = typer.solver;
         def messenger = solver.CurrentMessenger;
         match (DtKind) {
-          | Kind.MemberAccess (e, name, need_writable) =>
+          | Kind.MemberAccess (e, name) =>
             match (typer.TypeMember (e, name, expected)) {
               | Some ([]) =>
                 ReportError (messenger,
@@ -487,7 +542,7 @@
                 
               | Some (lst) =>
                 SetKind (Kind.Overloaded (lst));
-                when (need_writable && !ExpectLValue (false))
+                when (DtKind.need_write && !ExpectLValue (false))
                   ReportError (messenger, $"needed writable value, got $lst");
                 
                 // restart with more information
@@ -558,11 +613,14 @@
             unless (typer.Expect (expected, expr.Type, "already resolved overload"))
               SetKind (Kind.Error ())
 
-          | Kind.Macro (resolve) =>
+          | Kind.Macro (action) =>
             Util.locate (loc,
-              match (resolve (false)) {
+              match (action.Resolve (false)) {
                 | Some (expr) =>
-                  SetKind (Kind.Resolved (typer.TypeExpr (expr, expected)))
+                  if (typer.Expect (expected, expr.Type, $ "result of $action execution"))
+                    SetKind (Kind.Resolved (expr))
+                  else
+                    SetKind (Kind.Error ())
                   
                 | None => {}
               })

Modified: nemerle/trunk/ncc/typing/Typer.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer.n	(original)
+++ nemerle/trunk/ncc/typing/Typer.n	Sun Nov 20 19:37:58 2005
@@ -423,10 +423,31 @@
     {
       when (expected == null)
         expected = FreshTyVar ();
-      def kind = DelayedTyping.Kind.Macro (resolve);
+      <[ $(DelayAction (expected, DelayedMacro (this, expected, resolve)) : typed) ]>
+    }
+
+    [Record]
+    class DelayedMacro : DelayedAction
+    {
+      typer : Typer;
+      expected : TyVar;
+      fn : bool -> option [PT.PExpr];
+      
+      public override Resolve (fail_loudly : bool) : option [TExpr]
+      {
+        match (fn (fail_loudly)) {
+          | Some (e) => Some (typer.TypeExpr (e, expected))
+          | None => None ()
+        }
+      }
+    }
+
+    internal DelayAction (expected : TyVar, action : DelayedAction) : TExpr
+    {
+      def kind = DelayedTyping.Kind.Macro (action);
       def dt = DelayedTyping (this, kind, expected);
       dt.Resolve ();
-      <[ $(TExpr.Delayed (expected, dt) : typed) ]>
+      TExpr.Delayed (expected, dt)
     }
 
 
@@ -908,7 +929,7 @@
               log (TYPING, e.loc, $ "intercepted: $e'");
               e'
             } else {
-              log (TYPING, e.loc, $ "running expand with: $e");
+              log (MACRO_EXPANSIONS, e.loc, $ "running expand with: $e");
               def e = MacroRegistry.expand_macro (this, e);
               log (MACRO_EXPANSIONS, e.loc, $ "after expansion: $e");
 
@@ -1636,7 +1657,7 @@
     #endregion
 
 
-    #region Arrays, literals, indexers
+    #region Arrays, literals
     // FIXME: make this tail rec
     TypeArray (rank : int, args : PT.PExpr, expected : TyVar) : TExpr
     {
@@ -1731,16 +1752,21 @@
       }
     }
 
+    #endregion
+
 
+    #region Indexers
     TypeIndexer (obj : PT.PExpr, args : list [PT.PExpr], expected : TyVar) : TExpr
     {
       def obj = TypeExpr (obj);
       
+      DelayAction (expected, 
+        DelayedLambdaAction (desc = "", fn = fun (fail_loudly) {
       match (obj) {
         | TExpr.PropertyMember (_, prop) when prop.IsIndexer
         | TExpr.StaticPropertyRef (_, prop) when prop.IsIndexer
-        | TExpr.Delayed =>
-          TypeCall (<[ $(obj : typed) ]>, args, expected, is_property = true)
+          | TExpr.Delayed (DelayedTyping where (DtKind = Overloaded)) =>
+            Some (TypeCall (<[ $(obj : typed) ]>, args, expected, is_property = true))
         
         | _ =>
           match (obj.Type.Hint) {
@@ -1748,7 +1774,7 @@
               when Option.IsSome (ti.DefaultIndexerName) =>
               // Message.Debug ($ "using $(ti.DefaultIndexerName) for $ti");
               def idx = Option.UnSome (ti.DefaultIndexerName);
-              TypeIndexer (<[ $(obj : typed) . $(idx : dyn) ]>, args, expected)
+                Some (TypeIndexer (<[ $(obj : typed) . $(idx : dyn) ]>, args, expected))
 
             | Some (MType.Tuple (types)) =>
               match (args) {
@@ -1760,22 +1786,22 @@
                                      $ "the indexed tuple has only "
                                        "$(types.Length) members, cannot "
                                        "index at argument $k");
-                        TExpr.Error ()
+                          None ()
                       } else {
                         _ = Expect (expected, types.Nth (k), "tuple indexer");
-                        TExpr.TupleIndexer (obj, k, types.Length)
+                          Some (TExpr.TupleIndexer (expected, obj, k, types.Length))
                       }
                     | _ =>
                       ReportError (messenger,
                                    "argument to tuple indexer must be a "
                                    "constant integer");
-                      TExpr.Error ()
+                        None ()
                   }
                 | _ =>
                   ReportError (messenger, 
                                "indexer over tuples expects a single "
                                "integer argument");
-                  TExpr.Error ()
+                    None ()
               }
               
             | Some (MType.Array (indexer_over_type, rank) as arty) =>
@@ -1794,17 +1820,20 @@
 
               if (args_amount != 0) {
                 ReportError (messenger, "wrong number of indexes");
-                TExpr.Error ()
+                  None ()
               } else {
-                TExpr.ArrayIndexer (indexer_over_type, obj, typed_args)
+                  Some (TExpr.ArrayIndexer (indexer_over_type, obj, typed_args))
               }
-            | _ =>
+                
+              | hint =>
+                when (hint.IsSome || fail_loudly)
               ReportError (messenger, 
                            $ "cannot find any suitable indexer in "
                              "$(TypeOf (obj))");
-              TExpr.Error ()
+                None ()
           }
       }
+      }))
     }
     #endregion
 
@@ -2105,7 +2134,7 @@
         | Some (lst) =>
           MakeOverloadedNode (lst, expected)
         | None =>
-          Delay (DelayedTyping.Kind.MemberAccess (obj, mem_name, false), expected)
+          Delay (DelayedTyping.Kind.MemberAccess (obj, mem_name), expected)
       }
     }
 
@@ -3039,7 +3068,11 @@
         | TExpr.OpCode => "an operator reference"
         
         | TExpr.Error => "an erroneous expression"
-        | TExpr.Delayed => "a yet-untyped expression"
+        | TExpr.Delayed (dt) =>
+          match (dt.DtKind) {
+            | Resolved (e) => DescribeExpression (e)
+            | _ => "a yet-untyped expression"
+          }
 
         | TExpr.NotNull
         | TExpr.Switch



More information about the svn mailing list