[svn] r5992: nemerle/trunk: boot/Nemerle.Compiler.dll
boot/Nemerle.Macros.dll boot/Nemerle.dll boot/ncc.ex...
malekith
svnadmin at nemerle.org
Sun Dec 4 12:47:52 CET 2005
Log:
Yield implementation: the simplest example seems to work. Moving local variables to the class level and this-masquarading doesn't yet work.
Author: malekith
Date: Sun Dec 4 12:47:27 2005
New Revision: 5992
Added:
nemerle/trunk/ncc/testsuite/negative/yield.n
nemerle/trunk/ncc/testsuite/negative/yield2.n
nemerle/trunk/ncc/testsuite/positive/yield.n
Modified:
nemerle/trunk/boot/Nemerle.Compiler.dll
nemerle/trunk/boot/Nemerle.Macros.dll
nemerle/trunk/boot/Nemerle.dll
nemerle/trunk/boot/ncc.exe
nemerle/trunk/macros/core.n
nemerle/trunk/ncc/external/InternalTypes.n
nemerle/trunk/ncc/generation/Typer3.n
nemerle/trunk/ncc/generation/Typer4.n
nemerle/trunk/ncc/hierarchy/ClassMembers.n
nemerle/trunk/ncc/misc/PrettyPrint.n
nemerle/trunk/ncc/typing/TypedTree.n
nemerle/trunk/ncc/typing/Typer.n
nemerle/trunk/ncc/typing/Typer2.n
Modified: nemerle/trunk/boot/Nemerle.Compiler.dll
==============================================================================
Binary files. No diff available.
Modified: nemerle/trunk/boot/Nemerle.Macros.dll
==============================================================================
Binary files. No diff available.
Modified: nemerle/trunk/boot/Nemerle.dll
==============================================================================
Binary files. No diff available.
Modified: nemerle/trunk/boot/ncc.exe
==============================================================================
Binary files. No diff available.
Modified: nemerle/trunk/macros/core.n
==============================================================================
--- nemerle/trunk/macros/core.n (original)
+++ nemerle/trunk/macros/core.n Sun Dec 4 12:47:27 2005
@@ -132,6 +132,14 @@
<[ dont_use_me ($expr) ]>
}
+
+ /// Yet another syntax extender.
+ macro @yield (expr = null)
+ syntax ("yield", expr)
+ {
+ <[ dont_use_me ($expr) ]>
+ }
+
/** specialized macro for [if] condition with good warning messages,
it performs typing of given expressions to check their type
correctness
Modified: nemerle/trunk/ncc/external/InternalTypes.n
==============================================================================
--- nemerle/trunk/ncc/external/InternalTypes.n (original)
+++ nemerle/trunk/ncc/external/InternalTypes.n Sun Dec 4 12:47:27 2005
@@ -383,6 +383,7 @@
public mutable Nemerle_list_tc : TypeInfo;
public mutable IEnumerable_tc : TypeInfo;
public mutable Generic_IEnumerable_tc : TypeInfo;
+ public mutable Generic_IEnumerator_tc : TypeInfo;
public mutable DllImport_tc : TypeInfo;
public mutable Serializable_tc : TypeInfo;
@@ -527,6 +528,7 @@
ValueType_tc = lookup ("System.ValueType"); ValueType = MType.Class (ValueType_tc, []);
IEnumerable_tc = lookup ("System.Collections.IEnumerable");
Generic_IEnumerable_tc = lookup ("System.Collections.Generic.IEnumerable");
+ Generic_IEnumerator_tc = lookup ("System.Collections.Generic.IEnumerator");
DllImport_tc = lookup ("System.Runtime.InteropServices.DllImportAttribute");
Serializable_tc = lookup ("System.SerializableAttribute");
IObjectReference = MType.Class (lookup ("System.Runtime.Serialization.IObjectReference"), []);
Modified: nemerle/trunk/ncc/generation/Typer3.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer3.n (original)
+++ nemerle/trunk/ncc/generation/Typer3.n Sun Dec 4 12:47:27 2005
@@ -230,7 +230,7 @@
}
- static SingleMemberLookup (tb : TypeInfo, name : string) : IMember
+ static internal SingleMemberLookup (tb : TypeInfo, name : string) : IMember
{
match (tb.LookupMember (name)) {
| [mem] => mem
@@ -1575,7 +1575,6 @@
| DefFunctionsIn
| Match
| SelfTailCall
- | Yield
| Block =>
Util.cassert (Message.SeenError);
null
Modified: nemerle/trunk/ncc/generation/Typer4.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer4.n (original)
+++ nemerle/trunk/ncc/generation/Typer4.n Sun Dec 4 12:47:27 2005
@@ -309,7 +309,6 @@
| DefFunctionsIn
| Match
| Block
- | Yield
| SelfTailCall =>
Util.cassert (Message.SeenError);
false
Modified: nemerle/trunk/ncc/hierarchy/ClassMembers.n
==============================================================================
--- nemerle/trunk/ncc/hierarchy/ClassMembers.n (original)
+++ nemerle/trunk/ncc/hierarchy/ClassMembers.n Sun Dec 4 12:47:27 2005
@@ -598,6 +598,8 @@
internal mutable overridden_method : IMethod;
+ internal yield_stuff : option [PT.PExpr * list [PT.Fun_parm]] = None ();
+
is_var_args : bool;
public GetMethodBase () : MethodBase
@@ -710,7 +712,7 @@
when (t is <[ _ ]>)
Message.Error (t.Location, "type inference on global methods is not yet supported");
def ty = par.MonoBindType (tenv', t);
- types_to_check = ty :: types_to_check;
+ types_to_check ::= ty;
ty
}
@@ -846,8 +848,21 @@
| (x, _) => x
};
+ def ret_type = bind (f.header.ret_type);
+ match (ret_type.Fix ()) {
+ | Class (tc, [_])
+ when tc.Equals (InternalType.Generic_IEnumerator_tc) =>
+ match (f.header.ret_type) {
+ | <[ $_ [ $t ] ]> =>
+ // we need it at the parsetree level
+ yield_stuff = Some ((t, f.header.parms));
+ | _ => {}
+ }
+ | _ => {}
+ }
+
fun_header = Fun_header (
- ret_type = bind (f.header.ret_type),
+ ret_type = ret_type,
typarms = typarms,
name = this.name,
parms = parms,
Modified: nemerle/trunk/ncc/misc/PrettyPrint.n
==============================================================================
--- nemerle/trunk/ncc/misc/PrettyPrint.n (original)
+++ nemerle/trunk/ncc/misc/PrettyPrint.n Sun Dec 4 12:47:27 2005
@@ -1048,12 +1048,6 @@
recurse_and_indent (body);
- | TT.TExpr.Yield (body) =>
- append ("yield (");
- recurse (body);
- append (")");
-
-
| TT.TExpr.Goto (id, t) =>
append ($ "goto l$id [$t];");
Added: nemerle/trunk/ncc/testsuite/negative/yield.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/negative/yield.n Sun Dec 4 12:47:27 2005
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+class D
+{
+ public GetEnumerator () : string
+ {
+ yield "foo"; // E: yield used in a function returning string
+ }
+}
Added: nemerle/trunk/ncc/testsuite/negative/yield2.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/negative/yield2.n Sun Dec 4 12:47:27 2005
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+class D
+{
+ public GetEnumerator () : IEnumerator [int]
+ {
+ yield "foo"; // E: expected int, got string in assigned value
+ }
+}
Added: nemerle/trunk/ncc/testsuite/positive/yield.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/positive/yield.n Sun Dec 4 12:47:27 2005
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+
+class C : IEnumerable [int]
+{
+ public GetEnumerator () : IEnumerator [int]
+ {
+ yield 42;
+ yield 13;
+ yield 77;
+ }
+}
+
+foreach (e in C ())
+ System.Console.WriteLine (e);
+
+foreach (e in C ())
+ System.Console.WriteLine (e);
+
+/*
+BEGIN-OUTPUT
+42
+13
+77
+42
+13
+77
+END-OUTPUT
+*/
Modified: nemerle/trunk/ncc/typing/TypedTree.n
==============================================================================
--- nemerle/trunk/ncc/typing/TypedTree.n (original)
+++ nemerle/trunk/ncc/typing/TypedTree.n Sun Dec 4 12:47:27 2005
@@ -447,13 +447,12 @@
| StaticEventRef { from : MType.Class; ev : IEvent; }
| ConstantObjectRef { from : MType.Class; mem : IField; }
| Block { jump_out : LocalValue; body : TExpr; }
- | Yield { expr : TExpr; }
| Delayed { susp : Typer.DelayedTyping; }
| Error
// invalid after T3
| DefFunctionsIn { funs : list [Fun_header]; mutable body : TExpr; }
- | Match { expr : TExpr; cases : list [Match_case]; }
+ | Match { expr : TExpr; mutable cases : list [Match_case]; }
| SelfTailCall { parms : list [Parm]; }
| LocalFunRef { decl : LocalValue; type_parms : list [TyVar]; }
@@ -752,7 +751,6 @@
| StaticPropertyRef
| EventMember
| Block
- | Yield
| StaticEventRef =>
// this is supposed to be run after Typer2
Message.Warning (expr.loc,
Modified: nemerle/trunk/ncc/typing/Typer.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer.n (original)
+++ nemerle/trunk/ncc/typing/Typer.n Sun Dec 4 12:47:27 2005
@@ -66,13 +66,20 @@
locals_stack : Stack [LocalContext];
mutable skip_n_return : bool;
+ mutable inside_yielding_function : bool;
+ yield_stuff : option [PT.PExpr * list [PT.Fun_parm]];
+ mutable yield_labels : list [int] = [];
+
#region Toplevel typing
+ class SwitchToYielding : System.Exception { }
+
// FIXME: copy doc from TypeMethod
/** Walk through method body typing it. */
public this (m : MethodBuilder)
{
solver = Passes.Solver;
current_type = m.DeclaringType;
+ yield_stuff = m.yield_stuff;
parent_typer = None ();
env = current_type.GlobalEnv;
current_fun = m.GetHeader ();
@@ -80,6 +87,10 @@
messenger = solver.CurrentMessenger;
locals_stack = Stack ();
+ inside_yielding_function =
+ m.Name == "MoveNext" &&
+ current_type.LookupMember ("_N_current") is [_];
+
local_context = LocalContext.Empty;
assert (solver.IsTopLevel);
@@ -101,6 +112,16 @@
mutable typer_done = false;
assert (messenger.IsTopLevel);
+ def put_in_error_mode () {
+ solver.Unwind ();
+ messenger.Cleanup ();
+ assert (!messenger.InErrorMode);
+ assert (messenger.IsTopLevel);
+ messenger.InErrorMode = true;
+ local_context = LocalContext.Empty;
+ assert (!typer_done);
+ }
+
try {
messenger.Cleanup ();
messenger.InErrorMode = false;
@@ -122,18 +143,23 @@
} catch {
| _ is RestartInErrorMode =>
def errcnt = Message.ErrorCount;
- solver.Unwind ();
- messenger.Cleanup ();
- assert (!messenger.InErrorMode);
- assert (messenger.IsTopLevel);
- messenger.InErrorMode = true;
- local_context = LocalContext.Empty;
-
- assert (!typer_done);
+ put_in_error_mode ();
RunTyper ();
when (errcnt == Message.ErrorCount)
Util.ice ($"hidden errors compiling $m");
+
+ | _ is SwitchToYielding =>
+ def errcnt = Message.ErrorCount;
+ // just in case
+ put_in_error_mode ();
+ m.Body = MakeEnumeratorClass (m.Body);
+ when (errcnt == Message.ErrorCount)
+ RunTyper ();
+ when (errcnt == Message.ErrorCount) {
+ RunSecondPass (m);
+ MaybeDumpTypedTree ();
+ }
}
})
} finally {
@@ -257,10 +283,7 @@
MakeImplicitBlockJumpOut ("_N_return", current_fun.ret_type);
def e' = TypeExpr (e);
messenger.CleanLocalError ();
- def ret_type =
- if (UsedYield) InternalType.Void
- else current_fun.ret_type;
- def e' = AddCastTo (e', ret_type, "function return type");
+ def e' = AddCastTo (e', current_fun.ret_type, "function return type");
def e' =
if (skip_n_return) e'
else TExpr.Block (e'.Type, local, e');
@@ -277,7 +300,13 @@
RunSecondPass (meth : MethodBuilder) : void
{
- def t2 = Typer2 (current_type, meth, UsedYield);
+ when (inside_yielding_function)
+ match (current_fun.body) {
+ | FunBody.Typed (t) => AddYieldStateMachine (t)
+ | _ => Util.ice ()
+ }
+
+ def t2 = Typer2 (current_type, meth);
t2.Run ();
def t3 = Typer3 (meth);
t3.Run ();
@@ -2982,6 +3011,10 @@
PopLocals ();
}
} else if (ns.Equals (yield_macro)) {
+ when (! inside_yielding_function) {
+ _ = GetYieldStuff ();
+ throw SwitchToYielding ();
+ }
_ = Expect (expected, InternalType.Void, "yield ``result''");
HandleYield (expr)
} else null
@@ -2993,48 +3026,130 @@
#region yield handling
- GetYieldType () : TyVar
+ MakeEnumeratorClass (body : PT.PExpr) : PT.PExpr
+ {
+ def (yield_type, parms) = GetYieldStuff ();
+ def this_type = Util.ExprOfQid (current_type.FullName);
+ def all_parms = <[ parameter: _N_this : $this_type ]> :: parms;
+
+ def pt = <[ decl:
+ class $(Macros.NewSymbol ("Enumerator") : name) :
+ System.Collections.IEnumerator,
+ System.Collections.Generic.IEnumerator [$yield_type]
+ {
+ mutable _N_current : $yield_type;
+ mutable _N_state : int;
+
+ public Current : $yield_type
+ {
+ get { _N_current }
+ }
+
+ public MoveNext () : bool
+ {
+ _N_MoveNext_exit : {
+ match (_N_state) {
+ // AddYieldStateMachine will add something here
+ | 0 => {}
+ | _ => _N_MoveNext_exit (false)
+ }
+ {
+ $body;
+ false
+ }
+ }
+ }
+
+ public Dispose () : void
+ {
+ _N_state = -1;
+ }
+
+ public Reset () : void
+ {
+ throw System.NotSupportedException ();
+ }
+
+ public this (.. $all_parms)
+ {
+ }
+ }
+ ]>;
+
+ def tb = current_type.DefineNestedType (pt);
+
+ def ctor_assigns =
+ all_parms.Map (fun (fp) {
+ when (fp.ty is <[ ref $_ ]> || fp.ty is <[ out $_ ]>)
+ ReportError (messenger,
+ "ref/out parameters not allowed in functions "
+ "using ``yield''");
+ tb.Define (<[ decl: mutable $(fp.name) : $(fp.ty) ]>);
+ <[ this . $(fp.name) = $(fp.name.GetName () : name) ]>
+ });
+
+ def meth = Typer3.SingleMemberLookup (tb, ".ctor") :> MethodBuilder;
+ meth.Body = <[ { .. $ctor_assigns } ]>;
+
+ tb.Compile ();
+
+ def parm_refs =
+ <[ this ]> :: parms.Map (fun (fp) { <[ $(fp.name.GetName () : name) ]> });
+
+ <[ $(Util.ExprOfQid (tb.FullName)) (.. $parm_refs) ]>
+ }
+
+
+ GetYieldStuff () : PT.PExpr * list [PT.Fun_parm]
{
match (parent_typer) {
- | Some (t) => t.GetYieldType ()
+ | Some (t) => t.GetYieldStuff ()
+ | None =>
+ match (yield_stuff) {
+ | Some (x) => x
| None =>
- match (current_fun.ret_type.Fix ()) {
- | Class (tc, [t])
- when tc.Equals (InternalType.Generic_IEnumerable_tc) =>
- t
- | t =>
ReportError (messenger,
- $ "yield used in a function returning $t (it "
+ $ "yield used in a function returning "
+ "$(current_fun.ret_type) (it "
"should be System.Collections.Generic."
"IEnumerable[T])");
- InternalType.Object
+ (<[ object ]>, [])
}
}
}
HandleYield (expr : PT.PExpr) : TExpr
{
- when (solver.IsTopLevel)
- UsedYield = true;
- TExpr.Yield (InternalType.Void,
- AddCastTo (TypeExpr (expr), GetYieldType (), "yielded expression"))
- }
+ Util.cassert (solver.IsTopLevel);
+ def label_no = Util.next_id ();
+ yield_labels ::= label_no;
+ def label =
+ TExpr.Label (InternalType.Void, label_no, VoidLiteral ());
+ def state_no = yield_labels.Length;
- UsedYield : bool
+ TypeExpr (<[
{
- mutable used_yield : bool;
-
- get {
- match (parent_typer) {
- | Some (t) => t.UsedYield
- | None => used_yield
+ $(This () : typed) . _N_current = $expr;
+ $(This () : typed) . _N_state = $(state_no : int);
+ _N_MoveNext_exit (true);
+ $(label : typed)
}
+ ]>)
}
- set {
- match (parent_typer) {
- | Some (t) => t.UsedYield = value
- | None => used_yield = value
- }
+
+ AddYieldStateMachine (e : TExpr) : void
+ {
+ match (e) {
+ | Block (_, Block (_, Sequence (Match as m, _))) =>
+ mutable cnt = 1;
+ def cases = yield_labels.Rev ().Map (fun (id) {
+ def cntpat = Pattern.Literal (InternalType.Int32, Literal.FromInt (cnt));
+ cnt++;
+ def yes = TExpr.Literal (InternalType.Boolean, Literal.Bool (true));
+ Match_case ([(cntpat, yes, [])], TExpr.Goto (m.Type, id, 1), false)
+ });
+ m.cases = cases + m.cases;
+ | _ => Util.ice ($ "e = $e")
}
}
#endregion
@@ -3139,7 +3254,6 @@
| TExpr.Goto
| TExpr.Label
| TExpr.Block
- | TExpr.Yield
| TExpr.MultipleAssign
| TExpr.MethodAddress =>
$ "!!!shouldn't happen: $(expr.GetType())!!!"
Modified: nemerle/trunk/ncc/typing/Typer2.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer2.n (original)
+++ nemerle/trunk/ncc/typing/Typer2.n Sun Dec 4 12:47:27 2005
@@ -42,7 +42,6 @@
mutable current_fun : Fun_header;
current_type : TypeBuilder;
messenger : Messenger;
- used_yield : bool;
[System.Flags]
enum Context {
@@ -61,13 +60,12 @@
| TopLevel = IsTail %| AllowGoto %| AllowTry
}
- public this (ty : TypeBuilder, fn : MethodBuilder, used_yield : bool)
+ public this (ty : TypeBuilder, fn : MethodBuilder)
{
current_fun = fn.GetHeader ();
current_fun.usage = FunctionUsage.Used;
top_level_fun = fn;
current_type = ty;
- this.used_yield = used_yield;
messenger = Passes.Solver.CurrentMessenger;
}
@@ -168,13 +166,11 @@
| _ => false
}
| TExpr.StaticRef (Class (tc, _) as from, meth is IMethod, typarms) =>
- !used_yield &&
meth.GetHeader ().id == current_fun.id &&
tc.GetMemType ().Equals (from) &&
AreSelfMethodTyParms (meth, typarms)
| TExpr.MethodRef (th, meth : IMethod, typarms, _) =>
- !used_yield &&
meth.GetHeader ().id == current_fun.id &&
Unfold (th) is TExpr.This &&
AreSelfMethodTyParms (meth, typarms)
@@ -659,12 +655,6 @@
}
- [Nemerle.NotImplemented]
- static ExpandYield (expr : TExpr) : TExpr
- {
- }
-
-
/* block (foo) {
...
when (...) foo (33);
@@ -1203,10 +1193,6 @@
Walk (ctx, ExpandBlock (b))
- | TExpr.Yield (e) =>
- Walk (ctx, ExpandYield (e))
-
-
| TExpr.If (cond, e1, e2) =>
TExpr.If (Walk (cond), Walk (ctx, e1), Walk (ctx, e2))
More information about the svn
mailing list