From: Jean Privat Date: Wed, 3 Jun 2009 13:47:35 +0000 (-0400) Subject: compile: Fix inlined return in closure X-Git-Tag: v0.2.1~9 X-Git-Url: http://nitlanguage.org compile: Fix inlined return in closure Signed-off-by: Jean Privat --- diff --git a/src/compiling/compiling_methods.nit b/src/compiling/compiling_methods.nit index ca03727..6f8bd60 100644 --- a/src/compiling/compiling_methods.nit +++ b/src/compiling/compiling_methods.nit @@ -153,11 +153,11 @@ class CFunctionContext attr _varnames: Map[Variable, String] = new HashMap[Variable, String] # Are we currenlty in a closure definition? - readable writable attr _in_closure: Bool = false + readable writable attr _closure: NitMethodContext = null meth varname(v: Variable): String do - if _in_closure then + if _closure != null then return "closctx->{_varnames[v]}" else return _varnames[v] @@ -191,7 +191,7 @@ class CFunctionContext var s = "closurevariable[{_closurevariable_index}]" _closurevariable_index += 1 _varnames[v] = s - if _in_closure then + if _closure != null then return "(closctx->{s})" else return s @@ -201,7 +201,7 @@ class CFunctionContext # Return the ith variable protected meth variable(i: Int): String do - if _in_closure then + if _closure != null then return "(closctx->variable[{i}])" else return "variable[{i}]" @@ -363,7 +363,7 @@ redef class MMMethod # A passtrought break or a return is intercepted: go the the next closure v.add_instr("if ({closcns[i]}->has_broke != &({ve})) \{") v.indent - if v.cfc.in_closure then v.add_instr("closctx->has_broke = {closcns[i]}->has_broke; closctx->broke_value = {closcns[i]}->broke_value;") + if v.cfc.closure == v.nmc then v.add_instr("closctx->has_broke = {closcns[i]}->has_broke; closctx->broke_value = {closcns[i]}->broke_value;") v.add_instr("goto {v.nmc.return_label};") v.unindent # A direct break is interpected @@ -930,7 +930,7 @@ redef class AReturnExpr var e = v.compile_expr(n_expr) v.add_assignment(v.nmc.return_value, e) end - if v.cfc.in_closure then v.add_instr("closctx->has_broke = &({v.nmc.return_value});") + if v.cfc.closure == v.nmc then v.add_instr("closctx->has_broke = &({v.nmc.return_value});") v.add_instr("goto {v.nmc.return_label};") end end @@ -942,7 +942,7 @@ redef class ABreakExpr var e = v.compile_expr(n_expr) v.add_assignment(v.nmc.break_value, e) end - if v.cfc.in_closure then v.add_instr("closctx->has_broke = &({v.nmc.break_value}); closctx->broke_value = *closctx->has_broke;") + if v.cfc.closure == v.nmc then v.add_instr("closctx->has_broke = &({v.nmc.break_value}); closctx->broke_value = *closctx->has_broke;") v.add_instr("goto {v.nmc.break_label};") end end @@ -1478,12 +1478,12 @@ redef class AClosureDef v.ctx = new CContext v.out_contexts.add(v.ctx) - var cfc_old = v.cfc.in_closure - v.cfc.in_closure = true + var cfc_old = v.cfc.closure + v.cfc.closure = v.nmc var old_rv = v.nmc.return_value var old_bv = v.nmc.break_value - if not cfc_old then + if cfc_old == null then v.nmc.return_value = "closctx->{old_rv}" v.nmc.break_value = "closctx->{old_bv}" end @@ -1522,7 +1522,7 @@ redef class AClosureDef v.add_instr("}") v.ctx = ctx_old - v.cfc.in_closure = cfc_old + v.cfc.closure = cfc_old v.nmc.return_value = old_rv v.nmc.break_value = old_bv @@ -1531,7 +1531,7 @@ redef class AClosureDef v.add_decl("struct {closcn} {closcnv};") v.add_instr("{closcnv}.fun = {cname};") v.add_instr("{closcnv}.has_broke = NULL;") - if cfc_old then + if cfc_old != null then v.add_instr("{closcnv}.variable = closctx->variable;") v.add_instr("{closcnv}.closurevariable = closctx->closurevariable;") else @@ -1659,7 +1659,7 @@ redef class AClosureCallExpr if n_closure_defs != null and n_closure_defs.length == 1 then do n_closure_defs.first.do_compile_inside(v, null) end - if v.cfc.in_closure then v.add_instr("if ({ivar}->has_broke) \{ closctx->has_broke = {ivar}->has_broke; closctx->broke_value = {ivar}->broke_value;\}") + if v.cfc.closure == v.nmc then v.add_instr("if ({ivar}->has_broke) \{ closctx->has_broke = {ivar}->has_broke; closctx->broke_value = {ivar}->broke_value;\}") v.add_instr("goto {v.nmc.return_label};") v.unindent v.add_instr("\}") diff --git a/tests/sav/test_closure_inlined_return.sav b/tests/sav/test_closure_inlined_return.sav new file mode 100644 index 0000000..d1e72ca --- /dev/null +++ b/tests/sav/test_closure_inlined_return.sav @@ -0,0 +1,17 @@ +<0 + <1 + <2 + =10 + >2 + >1 + <1 + <2 + =20 + >2 + >1 + <1 + <2 + =30 + >2 + >1 +>0 diff --git a/tests/sav/test_closure_inlined_return_alt1.sav b/tests/sav/test_closure_inlined_return_alt1.sav new file mode 100644 index 0000000..f558a2f --- /dev/null +++ b/tests/sav/test_closure_inlined_return_alt1.sav @@ -0,0 +1,15 @@ +<0 + <1 + <2 + =10 + >2 + >1 + <1 + <2 + =20 + <1 + <2 + =30 + >2 + >1 +>0 diff --git a/tests/test_closure_inlined_return.nit b/tests/test_closure_inlined_return.nit new file mode 100644 index 0000000..b172ba5 --- /dev/null +++ b/tests/test_closure_inlined_return.nit @@ -0,0 +1,42 @@ +meth foo with k +do + ' '.output + '<'.output + 1.output + k + ' '.output + '>'.output + 1.output +end + +meth test +do + var a = [10, 20, 30] + '<'.output + 0.output + var i = 0 + while i < 3 do + foo with do + ' '.output + ' '.output + '<'.output + 2.output + ' '.output + ' '.output + '='.output + a[i].output # a[i] is usually inlined + if i == 1 then + #alt1#break + end + ' '.output + ' '.output + '>'.output + 2.output + end + i += 1 + end + '>'.output + 0.output +end + +test