[svn] r6014: nemerle/trunk/ncc: generation/Typer3.n
testsuite/positive/yield.n typing/Typer.n
malekith
svnadmin at nemerle.org
Sun Dec 18 13:20:03 CET 2005
Log:
Implement IEnumerable as well as IEnumerator yield pattern.
Author: malekith
Date: Sun Dec 18 13:20:02 2005
New Revision: 6014
Modified:
nemerle/trunk/ncc/generation/Typer3.n
nemerle/trunk/ncc/testsuite/positive/yield.n
nemerle/trunk/ncc/typing/Typer.n
Modified: nemerle/trunk/ncc/generation/Typer3.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer3.n (original)
+++ nemerle/trunk/ncc/generation/Typer3.n Sun Dec 18 13:20:02 2005
@@ -666,7 +666,8 @@
<[ decl:
class $(Macros.NewSymbol ("Enumerator") : name) :
System.Collections.IEnumerator,
- System.Collections.Generic.IEnumerator [$(yield_type : typed)]
+ System.Collections.Generic.IEnumerator [$(yield_type : typed)],
+ System.IDisposable
{
public Current : $(yield_type : typed)
{
@@ -691,6 +692,66 @@
]>
}
+ PrepareEnumerableObject (yield_type : TyVar) : Parsetree.ClassMember
+ {
+ def name = Macros.NewSymbol ("Enumerable");
+
+ def has_mutable_parm = current_local_fun.parms.Exists (fun (fp) { fp.decl.IsMutable });
+
+ def interlocked_stuff =
+ if (has_mutable_parm)
+ <[ true ]>
+ else
+ <[ System.Threading.Interlocked.CompareExchange
+ (ref _N_this_used, 1, 0) != 0 ]>;
+
+ <[ decl:
+ class $(name : name) :
+ System.Collections.IEnumerator,
+ System.Collections.Generic.IEnumerator [$(yield_type : typed)],
+ System.IDisposable,
+ System.Collections.Generic.IEnumerable [$(yield_type : typed)]
+ {
+ public Current : $(yield_type : typed)
+ {
+ get { this._N_current }
+ }
+
+ public Dispose () : void
+ {
+ foobar
+ }
+
+ public Reset () : void
+ {
+ throw System.NotSupportedException ();
+ }
+
+ public MoveNext () : bool
+ {
+ foobar
+ }
+
+ mutable _N_this_used : int;
+
+ public GetEnumerator () : System.Collections.Generic.IEnumerator [$(yield_type : typed)]
+ {
+ if ($interlocked_stuff) {
+ def res = $(name : name) ();
+ res.CopyFrom (this);
+ res
+ } else
+ this
+ }
+
+ CopyFrom (other : $(name : name)) : void
+ {
+ _N_this_used = 1;
+ }
+ }
+ ]>
+ }
+
static RewriteTryFinally (clo_type : TypeBuilder, fh : Fun_header) : void
{
mutable dispose_expr = Typer.VoidLiteral ();
@@ -749,7 +810,7 @@
}
- SetEnumeratorBody (clo_type : TypeBuilder, subst : Subst) : void
+ SetEnumeratorBody (clo_type : TypeBuilder, subst : Subst, parm_field_names : list [string]) : void
{
match (current_local_fun.body) {
| FunBody.Typed (DefValIn (_, _, DefValIn (_, _, DefFunctionsIn ([fh], _)))) =>
@@ -769,6 +830,14 @@
child.current_subst = subst;
child.Run ();
+ unless (parm_field_names.IsEmpty) {
+ def meth = SingleMemberLookup (clo_type, "CopyFrom") :> MethodBuilder;
+ def assigns = meth.Body :: parm_field_names.Map (fun (name) {
+ <[ this . $(name : dyn) = other . $(name : dyn) ]>
+ });
+ meth.Body = <[ { .. $assigns } ]>;
+ }
+
current_local_fun.body = FunBody.Typed (PlainRef (current_closure));
| FunBody.Typed (t)
@@ -794,6 +863,14 @@
}
def uses_yield = current_local_fun.yield_type != null;
+ def is_enumerable =
+ if (uses_yield)
+ match (current_local_fun.ret_type.Fix ()) {
+ | Class (tc, _) =>
+ tc.Equals (InternalType.Generic_IEnumerable_tc)
+ | _ => Util.ice ()
+ }
+ else false;
def clo_decl =
if (!uses_yield)
@@ -803,7 +880,11 @@
internal this () {}
}
]>
- else PrepareEnumeratorObject (fix_type (current_local_fun.yield_type));
+ else
+ if (is_enumerable)
+ PrepareEnumerableObject (fix_type (current_local_fun.yield_type));
+ else
+ PrepareEnumeratorObject (fix_type (current_local_fun.yield_type));
def clo_type = CurrentType.DefineNestedType (clo_decl, do_fixup = false);
clo_type.forced_typarms = new_tp;
@@ -832,6 +913,8 @@
}
});
+ mutable parm_field_names = [];
+
foreach (decl in vars) {
def name =
if (decl.Name == "_N_current" || decl.Name == "_N_state")
@@ -845,6 +928,8 @@
def fld = clo_type.DefineAndReturn (ptdecl);
decl.ClosureField = fld :> IField;
decl.ClosureField.HasBeenAssigned = true;
+ when (is_enumerable && decl.ValKind is FunParm (_))
+ parm_field_names ::= name.Id;
}
def ctor = SingleMemberLookup (clo_type, ".ctor");
def ctor_ref = TExpr.StaticRef (ctor.GetMemType (), clo_mtype, ctor, []);
@@ -854,7 +939,8 @@
clo_type.HasBeenUsed = true;
when (uses_yield)
- SetEnumeratorBody (clo_type, subst);
+ SetEnumeratorBody (clo_type, subst, parm_field_names);
+
clo_type.Compile ();
Modified: nemerle/trunk/ncc/testsuite/positive/yield.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/yield.n (original)
+++ nemerle/trunk/ncc/testsuite/positive/yield.n Sun Dec 18 13:20:02 2005
@@ -29,7 +29,12 @@
yield qux.ToString ();
yield ene;
yield this.due;
+ try {
yield rabe;
+ } catch {
+ | _ =>
+ yield rabe;
+ }
}
}
@@ -42,6 +47,22 @@
}
}
+class X {
+ public static FromTo (from : int, to : int) : IEnumerable [int]
+ {
+ for (mutable i = from; i <= to; ++i)
+ yield i;
+ }
+
+ public static FromTo2 (mutable from : int, to : int) : IEnumerable [int]
+ {
+ while (from <= to) {
+ yield from;
+ from++;
+ }
+ }
+}
+
foreach (e in C ())
System.Console.WriteLine (e);
@@ -59,6 +80,23 @@
foreach (e in E ())
System.Console.WriteLine (e);
+def x = X.FromTo (42, 47);
+System.Console.WriteLine ("------------");
+foreach (e in x)
+ System.Console.WriteLine (e);
+System.Console.WriteLine ("------------");
+foreach (e in x)
+ System.Console.WriteLine (e);
+
+def x = X.FromTo2 (42, 47);
+System.Console.WriteLine ("------------");
+foreach (e in x)
+ System.Console.WriteLine (e);
+System.Console.WriteLine ("------------");
+foreach (e in x)
+ System.Console.WriteLine (e);
+System.Console.WriteLine ("------------");
+
/*
BEGIN-OUTPUT
42
@@ -79,5 +117,34 @@
2
3
4
+------------
+42
+43
+44
+45
+46
+47
+------------
+42
+43
+44
+45
+46
+47
+------------
+42
+43
+44
+45
+46
+47
+------------
+42
+43
+44
+45
+46
+47
+------------
END-OUTPUT
*/
Modified: nemerle/trunk/ncc/typing/Typer.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer.n (original)
+++ nemerle/trunk/ncc/typing/Typer.n Sun Dec 18 13:20:02 2005
@@ -3086,12 +3086,14 @@
| None =>
match (current_fun.ret_type.Fix ()) {
| Class (tc, [t])
- when tc.Equals (InternalType.Generic_IEnumerator_tc) => t
+ when tc.Equals (InternalType.Generic_IEnumerator_tc) ||
+ tc.Equals (InternalType.Generic_IEnumerable_tc) => t
| t =>
ReportError (messenger,
$ "yield used in a function returning "
"$t (it should be System.Collections.Generic."
- "IEnumerator[T])");
+ "IEnumerator[T] or System.Collections.Generic."
+ "IEnumerable[T])");
InternalType.Object
}
}
More information about the svn
mailing list