[svn] r6013: nemerle/trunk/ncc: generation/ILEmitter.n
generation/Typer3.n generation/Typer4.n misc/Pretty...
malekith
svnadmin at nemerle.org
Sat Dec 17 23:09:06 CET 2005
Log:
Properly handle finally clauses in iterators.
Author: malekith
Date: Sat Dec 17 23:09:02 2005
New Revision: 6013
Modified:
nemerle/trunk/ncc/generation/ILEmitter.n
nemerle/trunk/ncc/generation/Typer3.n
nemerle/trunk/ncc/generation/Typer4.n
nemerle/trunk/ncc/misc/PrettyPrint.n
nemerle/trunk/ncc/testsuite/positive/yield-tree.n
nemerle/trunk/ncc/typing/TypedTree.n
nemerle/trunk/ncc/typing/Typer.n
nemerle/trunk/ncc/typing/Typer2.n
Modified: nemerle/trunk/ncc/generation/ILEmitter.n
==============================================================================
--- nemerle/trunk/ncc/generation/ILEmitter.n (original)
+++ nemerle/trunk/ncc/generation/ILEmitter.n Sat Dec 17 23:09:02 2005
@@ -1166,7 +1166,8 @@
/* emit the try/with construction */
- | TryWith (try_expr, catch_val, catch_expr) =>
+ | TryWith (try_expr, catch_val, catch_expr)
+ | TryFault (try_expr, catch_expr) with catch_val = null =>
def type_of_try_expr = expr.SystemType;
def ignore_try_with_result = is_void (try_expr.Type);
@@ -1182,6 +1183,10 @@
unless (try_expr.Throws || ignore_try_with_result)
_ilg.Emit (OpCodes.Stloc, try_result);
+ if (catch_val == null) {
+ _ilg.BeginFaultBlock ();
+ emit (catch_expr);
+ } else {
_ilg.BeginCatchBlock (catch_val.Type.SystemType);
def catch_val_local_slot = declare_val_local_slot (catch_val);
@@ -1193,6 +1198,7 @@
unless (catch_expr.Throws || ignore_try_with_result)
_ilg.Emit (OpCodes.Stloc, try_result);
+ }
_ilg.EndExceptionBlock ();
Modified: nemerle/trunk/ncc/generation/Typer3.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer3.n (original)
+++ nemerle/trunk/ncc/generation/Typer3.n Sat Dec 17 23:09:02 2005
@@ -430,10 +430,11 @@
{
if (hd.usage == FunctionUsage.UsedJustOnce) {
ClosureRef (hd.decl.DefinedIn)
- } else if (current_method.name == "_N_yielding_function") {
+ } else if (current_method.is_in_closure_of != 0) {
// Message.Debug ($ "lookup $(hd.name) from $(current_method.name)");
- Util.cassert (hd.id == current_method.id ||
- current_method.decl.DefinedIn.id == hd.id);
+ Util.cassert (hd.id == current_method.is_in_closure_of ||
+ (current_method.decl != null &&
+ current_method.decl.DefinedIn.id == hd.id));
TExpr.This (local_function_type.GetMemType ())
} else if (hd.id == current_method.id) {
PlainRef (current_closure)
@@ -674,7 +675,7 @@
public Dispose () : void
{
- this._N_state = -1;
+ foobar
}
public Reset () : void
@@ -684,23 +685,90 @@
public MoveNext () : bool
{
+ foobar
}
}
]>
}
+ static RewriteTryFinally (clo_type : TypeBuilder, fh : Fun_header) : void
+ {
+ mutable dispose_expr = Typer.VoidLiteral ();
+
+ def thisref = TExpr.This (clo_type.GetMemType ());
+
+ def rewrite (expr : TExpr) {
+ | TryFinally (body, handler) =>
+ def fld = clo_type.DefineAndReturn (<[ decl:
+ mutable $(Macros.NewSymbol ("finally_needed") : name) : bool;
+ ]>) :> IField;
+ fld.HasBeenAssigned = true;
+ fld.HasBeenUsed = true;
+ def fldref = TExpr.FieldMember (InternalType.Boolean, thisref, fld);
+ def for_dispose =
+ TExpr.If (InternalType.Void, fldref, handler, Typer.VoidLiteral ());
+ dispose_expr = TExpr.Sequence (dispose_expr.Type, for_dispose, dispose_expr);
+
+ BuildRevSequence (
+ [handler,
+ TExpr.Assign (InternalType.Void, fldref, TExpr.FalseLiteral),
+ body.Walk (rewrite),
+ TExpr.Assign (InternalType.Void, fldref, TExpr.TrueLiteral)])
- SetEnumeratorBody (clo_type : TypeInfo, subst : Subst) : void
+ | _ => null
+ }
+
+ match (fh.body) {
+ | FunBody.Typed (expr) =>
+ def expr = expr.Walk (rewrite);
+
+ def dispose_meth =
+ SingleMemberLookup (clo_type, "Dispose") :> IMethod;
+ def dispose_call =
+ TExpr.Call (InternalType.Void,
+ TExpr.MethodRef (dispose_meth.GetMemType (),
+ thisref, dispose_meth, [], true),
+ [], false);
+ def expr = TExpr.TryFault (expr.Type, expr, dispose_call);
+ fh.body = FunBody.Typed (expr);
+
+ def this_N_state =
+ TExpr.FieldMember (InternalType.Int32, thisref,
+ SingleMemberLookup (clo_type, "_N_state") :> IField);
+ dispose_expr =
+ TExpr.Sequence (InternalType.Void,
+ TExpr.Assign (InternalType.Void,
+ this_N_state,
+ TExpr.Literal (InternalType.Int32,
+ Literal.FromInt (-1))),
+ dispose_expr);
+ dispose_meth.GetHeader ().body = FunBody.Typed (dispose_expr);
+
+ | _ => Util.ice ()
+ }
+ }
+
+
+ SetEnumeratorBody (clo_type : TypeBuilder, subst : Subst) : void
{
match (current_local_fun.body) {
| FunBody.Typed (DefValIn (_, _, DefValIn (_, _, DefFunctionsIn ([fh], _)))) =>
def meth = SingleMemberLookup (clo_type, "MoveNext") :> MethodBuilder;
+ RewriteTryFinally (clo_type, fh);
fh.used_closures = fh.GetParents ();
+ fh.is_in_closure_of = fh.id;
PrepareForEmission (meth, fh, subst);
def child = Typer3 (this, meth);
child.current_subst = subst;
child.Run ();
+ def meth = SingleMemberLookup (clo_type, "Dispose") :> MethodBuilder;
+ meth.GetHeader ().used_closures = fh.GetParents ();
+ meth.GetHeader ().is_in_closure_of = fh.id;
+ def child = Typer3 (this, meth);
+ child.current_subst = subst;
+ child.Run ();
+
current_local_fun.body = FunBody.Typed (PlainRef (current_closure));
| FunBody.Typed (t)
@@ -784,11 +852,12 @@
clo_type.MarkWithSpecialName ();
clo_type.HasBeenUsed = true;
- clo_type.Compile ();
when (uses_yield)
SetEnumeratorBody (clo_type, subst);
+ clo_type.Compile ();
+
[TExpr.DefValIn (InternalType.Void, closure_val, ctor_call, null)]
}
}
@@ -1612,6 +1681,7 @@
| Assign
| Throw
| TryFinally
+ | TryFault
| Literal
| This
| Base
Modified: nemerle/trunk/ncc/generation/Typer4.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer4.n (original)
+++ nemerle/trunk/ncc/generation/Typer4.n Sat Dec 17 23:09:02 2005
@@ -378,6 +378,7 @@
exprs.Iter (NoThrowPlease);
false
+ | TryFault (body, handler)
| TryWith (body, _, handler)
| TryFinally (body, handler) =>
when (! allow_try)
@@ -632,6 +633,9 @@
| TryFinally (body, handler) =>
TExpr.TryFinally (WalkTry (body), Walk (handler))
+ | TryFault (body, handler) =>
+ TExpr.TryFault (WalkTry (body), Walk (handler))
+
| Goto as g =>
g.try_block = current_try_block;
null
Modified: nemerle/trunk/ncc/misc/PrettyPrint.n
==============================================================================
--- nemerle/trunk/ncc/misc/PrettyPrint.n (original)
+++ nemerle/trunk/ncc/misc/PrettyPrint.n Sat Dec 17 23:09:02 2005
@@ -1092,6 +1092,13 @@
append ("throw ");
recurse (exn)
+ | TT.TExpr.TryFault (body, handler) =>
+ append ("try {\n");
+ recurse_and_indent (body);
+ append ("\n" + indentation + "} fault {\n");
+ recurse_and_indent (handler);
+ append ("\n" + indentation + "}")
+
| TT.TExpr.TryWith (body /* PExpr */, exn /* LocalValue */, handler /* PExpr */) =>
append ("try {\n");
recurse_and_indent (body);
Modified: nemerle/trunk/ncc/testsuite/positive/yield-tree.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/yield-tree.n (original)
+++ nemerle/trunk/ncc/testsuite/positive/yield-tree.n Sat Dec 17 23:09:02 2005
@@ -35,3 +35,19 @@
foreach (e in n2)
System.Console.WriteLine (e)
+
+/*
+BEGIN-OUTPUT
+1
+2
+22
+33
+82
+chinczyk
+due
+ene
+rabe
+zabe
+zlapal
+END-OUTPUT
+*/
Modified: nemerle/trunk/ncc/typing/TypedTree.n
==============================================================================
--- nemerle/trunk/ncc/typing/TypedTree.n (original)
+++ nemerle/trunk/ncc/typing/TypedTree.n Sat Dec 17 23:09:02 2005
@@ -223,6 +223,7 @@
internal mutable children_funs : list [Fun_header] = [];
internal mutable uses_try_block : bool;
internal mutable yield_type : TyVar;
+ internal mutable is_in_closure_of : int;
// FIXME: move to hashtables in t3
internal mutable used_closures : list [Fun_header];
@@ -430,6 +431,7 @@
| Assign { target : TExpr; source : TExpr; }
| DefValIn { name : LocalValue; val : TExpr; mutable body : TExpr; }
| Throw { exn : TExpr; }
+ | TryFault { body : TExpr; handler : TExpr; }
| TryWith { body : TExpr; exn : LocalValue; handler : TExpr; }
| TryFinally { body : TExpr; handler : TExpr; }
| Literal { val : Nemerle.Compiler.Literal; }
@@ -879,6 +881,10 @@
TryFinally (walk (f, body), walk (f, handler))
+ | TryFault (body, handler) =>
+ TryFault (walk (f, body), walk (f, handler))
+
+
| TypeConversion (expr, t, kind) =>
def expr = null_walk (f, expr);
if (expr == null) null
Modified: nemerle/trunk/ncc/typing/Typer.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer.n (original)
+++ nemerle/trunk/ncc/typing/Typer.n Sat Dec 17 23:09:02 2005
@@ -629,7 +629,7 @@
}
- static VoidLiteral () : TExpr
+ static internal VoidLiteral () : TExpr
{
TExpr.Literal (InternalType.Void, Literal.Void ())
}
@@ -3243,6 +3243,7 @@
| _ => "a yet-untyped expression"
}
+ | TExpr.TryFault
| TExpr.NotNull
| TExpr.Switch
| TExpr.DefaultValue
Modified: nemerle/trunk/ncc/typing/Typer2.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer2.n (original)
+++ nemerle/trunk/ncc/typing/Typer2.n Sat Dec 17 23:09:02 2005
@@ -1215,6 +1215,7 @@
| TExpr.DefaultValue => null
+ | TExpr.TryFault
| TExpr.NotNull
| TExpr.Switch
| TExpr.MultipleAssign
More information about the svn
mailing list