[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