scope: create two escapemaks in loops
[nit.git] / src / compiler / abstract_compiler.nit
index cf1e0f2..58cb346 100644 (file)
@@ -330,7 +330,7 @@ class MakefileToolchain
 
                var outname = outfile(mainmodule)
 
-               var orig_dir=".." # FIXME only works if `compile_dir` is a subdirectory of cwd
+               var orig_dir = compile_dir.relpath(".")
                var outpath = orig_dir.join_path(outname).simplify_path
                var makename = makefile_name(mainmodule)
                var makepath = "{compile_dir}/{makename}"
@@ -1266,6 +1266,14 @@ abstract class AbstractCompilerVisitor
                return name
        end
 
+       # Insert a C label for associated with an escapemark
+       fun add_escape_label(e: nullable EscapeMark)
+       do
+               if e == null then return
+               if e.escapes.is_empty then return
+               add("BREAK_{escapemark_name(e)}: (void)0;")
+       end
+
        private var escapemark_names = new HashMap[EscapeMark, String]
 
        # Return a "const char*" variable associated to the classname of the dynamic type of an object
@@ -2324,33 +2332,12 @@ redef class AClassdef
        private fun compile_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable])
        do
                if mpropdef == self.mfree_init then
-                       if mpropdef.mproperty.is_root_init then
-                               assert self.super_inits == null
-                               assert arguments.length == 1
-                               if not mpropdef.is_intro then
-                                       v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
-                               end
-                               return
-                       end
-
-                       var super_inits = self.super_inits
-                       if super_inits != null then
-                               var args_of_super = arguments
-                               if arguments.length > 1 then args_of_super = [arguments.first]
-                               for su in super_inits do
-                                       v.send(su, args_of_super)
-                               end
-                       end
-
-                       var recv = arguments.first
-                       var i = 1
-                       # Collect undefined attributes
-                       for npropdef in self.n_propdefs do
-                               if npropdef isa AAttrPropdef and npropdef.n_expr == null and not npropdef.noinit then
-                                       v.write_attribute(npropdef.mpropdef.mproperty, recv, arguments[i])
-                                       i += 1
-                               end
+                       assert mpropdef.mproperty.is_root_init
+                       assert arguments.length == 1
+                       if not mpropdef.is_intro then
+                               v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
                        end
+                       return
                else
                        abort
                end
@@ -2451,11 +2438,7 @@ redef class ASelfExpr
        redef fun expr(v) do return v.frame.arguments.first
 end
 
-redef class AContinueExpr
-       redef fun stmt(v) do v.add("goto CONTINUE_{v.escapemark_name(self.escapemark)};")
-end
-
-redef class ABreakExpr
+redef class AEscapeExpr
        redef fun stmt(v) do v.add("goto BREAK_{v.escapemark_name(self.escapemark)};")
 end
 
@@ -2518,10 +2501,7 @@ redef class ADoExpr
        redef fun stmt(v)
        do
                v.stmt(self.n_block)
-               var escapemark = self.escapemark
-               if escapemark != null then
-                       v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
-               end
+               v.add_escape_label(break_mark)
        end
 end
 
@@ -2532,9 +2512,9 @@ redef class AWhileExpr
                var cond = v.expr_bool(self.n_expr)
                v.add("if (!{cond}) break;")
                v.stmt(self.n_block)
-               v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(continue_mark)
                v.add("\}")
-               v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(break_mark)
        end
 end
 
@@ -2543,9 +2523,9 @@ redef class ALoopExpr
        do
                v.add("for(;;) \{")
                v.stmt(self.n_block)
-               v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(continue_mark)
                v.add("\}")
-               v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(break_mark)
        end
 end
 
@@ -2575,12 +2555,12 @@ redef class AForExpr
 
                        v.stmt(self.n_block)
 
-                       v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+                       v.add_escape_label(continue_mark)
                        var succ = v.send(v.get_property("successor", variable.mtype), [variable, one])
                        assert succ != null
                        v.assign(variable, succ)
                        v.add("\}")
-                       v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+                       v.add_escape_label(break_mark)
                        return
                end
 
@@ -2616,12 +2596,18 @@ redef class AForExpr
                        abort
                end
                v.stmt(self.n_block)
-               v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(continue_mark)
                var next_meth = self.method_next
                assert next_meth != null
                v.compile_callsite(next_meth, [it])
                v.add("\}")
-               v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(break_mark)
+
+               var method_finish = self.method_finish
+               if method_finish != null then
+                       # TODO: Find a way to call this also in long escape (e.g. return)
+                       v.compile_callsite(method_finish, [it])
+               end
        end
 end