compile: clean CompilerVisitor constructor
[nit.git] / src / compiling / compiling_methods.nit
index c823b83..856934e 100644 (file)
@@ -24,6 +24,7 @@ redef class CompilerVisitor
        # Compile a statment node
        meth compile_stmt(n: PExpr)
        do
+               if n == null then return
                add_instr("/* Compile stmt {n.locate} */")
                n.prepare_compile_stmt(self)
                var i = cfc._variable_index
@@ -38,7 +39,7 @@ redef class CompilerVisitor
                var i = cfc._variable_index
                var s = n.compile_expr(self)
                cfc._variable_index = i
-               if s[0] == ' ' then
+               if s[0] == ' ' or cfc.is_valid_variable(s) then
                        return s
                end
                var v = cfc.get_var("Result for expr {n.locate}")
@@ -49,7 +50,8 @@ redef class CompilerVisitor
        # Ensure that a c expression is a var
        meth ensure_var(s: String, comment: String): String
        do
-               if s.substring(0,3) == "variable" then
+               if cfc.is_valid_variable(s) then
+                       add_instr("/* Ensure var {s}: {comment}*/")
                        return s
                end
                var v = cfc.get_var(null)
@@ -83,11 +85,6 @@ redef class CompilerVisitor
                return s.to_s
        end
 
-       redef init(module: MMSrcModule)
-       do
-               super
-       end
-
        meth invoke_super_init_calls_after(start_prop: MMMethod)
        do
                var n = nmc.method.node
@@ -128,7 +125,7 @@ redef class CompilerVisitor
                                end
                        end
                        #s.append(" {p}")
-                       p.compile_call(self, cargs)
+                       p.compile_stmt_call(self, cargs)
                        i += 1
                end
                #s.append(" ]")
@@ -235,6 +232,15 @@ class CFunctionContext
                end
        end
 
+       # Is s a valid variable
+       protected meth is_valid_variable(s: String): Bool
+       do
+               for i in [0.._variable_index[ do
+                       if s == variable(i) then return true
+               end
+               return false
+       end
+
        # Mark the variable available
        meth free_var(v: String)
        do
@@ -302,11 +308,30 @@ redef class ClosureVariable
 end
 
 redef class MMMethod
+       # Compile as an expression.
+       # require that signature.return_type != null
+       meth compile_expr_call(v: CompilerVisitor, cargs: Array[String]): String
+       do
+               assert signature.return_type != null
+               var s = intern_compile_call(v, cargs)
+               assert s != null
+               return s
+       end
+
+       # Compile as a statement.
+       # require that signature.return_type == null
+       meth compile_stmt_call(v: CompilerVisitor, cargs: Array[String])
+       do
+               assert signature.return_type == null
+               var s = intern_compile_call(v, cargs)
+               assert s == null
+       end
+
        # Compile a call on self for given arguments
        # Most calls are compiled with a table access,
        # primitive calles are inlined
        # == and != are guarded and possibly inlined
-       meth compile_call(v: CompilerVisitor, cargs: Array[String]): String
+       private meth intern_compile_call(v: CompilerVisitor, cargs: Array[String]): String
        do
                var i = self
                if i isa MMSrcMethod then
@@ -321,7 +346,7 @@ redef class MMMethod
                var ne = once "!=".to_symbol
                if name == ne then
                        var eqp = signature.recv.local_class.select_method(ee)
-                       var eqcall = eqp.compile_call(v, cargs)
+                       var eqcall = eqp.compile_expr_call(v, cargs)
                        return "TAG_Bool(!UNTAG_Bool({eqcall}))"
                end
                if global.is_init then
@@ -376,7 +401,7 @@ redef class MMMethod
                v.nmc.break_value = old_bv
 
                # Call
-               var e = compile_call(v, realcargs)
+               var e = intern_compile_call(v, realcargs)
                if e != null then
                        v.add_assignment(ve, e)
                        e = ve
@@ -574,9 +599,9 @@ redef class MMImplicitInit
                                for i in [1..f[ do
                                        args.add(params[i])
                                end
-                               sp.compile_call(v, args)
+                               sp.compile_stmt_call(v, args)
                        else
-                               sp.compile_call(v, args_recv)
+                               sp.compile_stmt_call(v, args_recv)
                        end
                end
                for i in [f..params.length[ do
@@ -670,9 +695,7 @@ redef class AConcreteMethPropdef
                if self isa AConcreteInitPropdef then
                        v.invoke_super_init_calls_after(null)
                end
-               if n_block != null then
-                       v.compile_stmt(n_block)
-               end
+               v.compile_stmt(n_block)
                v.add_instr("{v.nmc.return_label}: while(false);")
                if self isa AConcreteInitPropdef then
                        v.add_instr("init_table[{itpos}] = 1;")
@@ -991,9 +1014,7 @@ end
 redef class ADoExpr
        redef meth compile_stmt(v)
        do
-                if n_block != null then
-                        v.compile_stmt(n_block)
-                end
+               v.compile_stmt(n_block)
        end
 end
 
@@ -1064,9 +1085,7 @@ redef class AWhileExpr
                var e = v.compile_expr(n_expr)
                v.add_instr("if (!UNTAG_Bool({e})) break; /* while*/")
                v.cfc.free_var(e)
-               if n_block != null then
-                       v.compile_stmt(n_block)
-               end
+               v.compile_stmt(n_block)
                v.add_instr("{v.nmc.continue_label}: while(0);")
                v.unindent
                v.add_instr("}")
@@ -1081,24 +1100,20 @@ redef class AForExpr
                var ittype = meth_iterator.signature.return_type
                v.cfc.free_var(e)
                var iter = v.cfc.get_var("For iterator")
-               v.add_assignment(iter, meth_iterator.compile_call(v, [e]))
+               v.add_assignment(iter, meth_iterator.compile_expr_call(v, [e]))
                v.add_instr("while (true) \{ /*for*/")
                v.indent
                var ok = v.cfc.get_var("For 'is_ok' result")
-               v.add_assignment(ok, meth_is_ok.compile_call(v, [iter]))
+               v.add_assignment(ok, meth_is_ok.compile_expr_call(v, [iter]))
                v.add_instr("if (!UNTAG_Bool({ok})) break; /*for*/")
                v.cfc.free_var(ok)
-               var e = meth_item.compile_call(v, [iter])
+               var e = meth_item.compile_expr_call(v, [iter])
                e = v.ensure_var(e, "For item")
                var cname = v.cfc.register_variable(variable)
                v.add_assignment(cname, e)
-               var n_block = n_block
-               if n_block != null then
-                       v.compile_stmt(n_block)
-               end
+               v.compile_stmt(n_block)
                v.add_instr("{v.nmc.continue_label}: while(0);")
-               e = meth_next.compile_call(v, [iter])
-               assert e == null
+               meth_next.compile_stmt_call(v, [iter])
                v.unindent
                v.add_instr("}")
                v.add_instr("{v.nmc.break_label}: while(0);")
@@ -1137,7 +1152,7 @@ redef class AVarReassignExpr
        do
                var e1 = v.cfc.varname(variable)
                var e2 = v.compile_expr(n_value)
-               var e3 = assign_method.compile_call(v, [e1, e2])
+               var e3 = assign_method.compile_expr_call(v, [e1, e2])
                v.add_assignment(v.cfc.varname(variable), "{e3} /*{variable.name}*/")
        end
 end
@@ -1323,12 +1338,14 @@ redef class ASuperstringExpr
                for ne in n_exprs do
                        var e = v.ensure_var(v.compile_expr(ne), "super-string element")
                        if ne.stype != stype then
-                               v.add_assignment(e, meth_to_s.compile_call(v, [e]))
+                               v.cfc.free_var(e)
+                               e = meth_to_s.compile_expr_call(v, [e])
                        end
-                       meth_add.compile_call(v, [array, e])
+                       v.cfc.free_var(e)
+                       meth_add.compile_stmt_call(v, [array, e])
                end
 
-               return meth_to_s.compile_call(v, [array])
+               return meth_to_s.compile_expr_call(v, [array])
        end
 end
 
@@ -1347,7 +1364,7 @@ redef class AArrayExpr
 
                for ne in n_exprs do
                        var e = v.compile_expr(ne)
-                       meth_add.compile_call(v, [recv, e])
+                       meth_add.compile_stmt_call(v, [recv, e])
                end
                return recv
        end
@@ -1365,12 +1382,21 @@ end
 redef class ASuperExpr
        redef meth compile_stmt(v)
        do
-               var e = compile_expr(v)
-               if e != null then v.add_instr("{e};")
+               var e = intern_compile_call(v)
+               if e != null then
+                       v.add_instr(e + ";")
+               end
        end
 
        redef meth compile_expr(v)
        do
+               var e = intern_compile_call(v)
+               assert e != null
+               return e
+       end
+
+       private meth intern_compile_call(v: CompilerVisitor): String
+       do
                var arity = v.nmc.method_params.length - 1
                if init_in_superclass != null then
                        arity = init_in_superclass.signature.arity
@@ -1388,7 +1414,7 @@ redef class ASuperExpr
                end
                #return "{prop.cname}({args.join(", ")}) /*super {prop.local_class}::{prop.name}*/"
                if init_in_superclass != null then
-                       return init_in_superclass.compile_call(v, args)
+                       return init_in_superclass.intern_compile_call(v, args)
                else
                        if prop.global.is_init then args.add("init_table")
                        return prop.compile_super_call(v, args)
@@ -1418,24 +1444,33 @@ redef class AAttrReassignExpr
                var e1 = v.compile_expr(n_expr)
                var e2 = prop.compile_access(v, e1)
                var e3 = v.compile_expr(n_value)
-               var e4 = assign_method.compile_call(v, [e2, e3])
+               var e4 = assign_method.compile_expr_call(v, [e2, e3])
                v.add_assignment(e2, e4)
        end
 end
 
+redef class AAbsSendExpr
+       # Compile each argument and add them to the array
+       meth compile_arguments_in(v: CompilerVisitor, cargs: Array[String])
+       do
+               for a in arguments do
+                       cargs.add(v.compile_expr(a))
+               end
+       end
+
+end
+
 redef class ASendExpr
-       redef meth compile_expr(v)
+       private meth intern_compile_call(v: CompilerVisitor): String
        do
                var recv = v.compile_expr(n_expr)
                var cargs = new Array[String]
                cargs.add(recv)
-               for a in arguments do
-                       cargs.add(v.compile_expr(a))
-               end
+               compile_arguments_in(v, cargs)
 
                var e: String
                if prop_signature.closures.is_empty then
-                       e = prop.compile_call(v, cargs)
+                       e = prop.intern_compile_call(v, cargs)
                else
                        e = prop.compile_call_and_closures(v, cargs, closure_defs)
                end
@@ -1446,9 +1481,16 @@ redef class ASendExpr
                return e
        end
 
+       redef meth compile_expr(v)
+       do
+               var e = intern_compile_call(v)
+               assert e != null
+               return e
+       end
+
        redef meth compile_stmt(v)
        do
-               var e = compile_expr(v)
+               var e = intern_compile_call(v)
                if e != null then
                        v.add_instr(e + ";")
                end
@@ -1456,20 +1498,20 @@ redef class ASendExpr
 end
 
 redef class ASendReassignExpr
-       redef meth compile_expr(v)
+       redef meth compile_expr(v) do abort
+
+       redef meth compile_stmt(v)
        do
                var recv = v.compile_expr(n_expr)
                var cargs = new Array[String]
                cargs.add(recv)
-               for a in arguments do
-                       cargs.add(v.compile_expr(a))
-               end
+               compile_arguments_in(v, cargs)
 
-               var e2 = read_prop.compile_call(v, cargs)
+               var e2 = read_prop.compile_expr_call(v, cargs)
                var e3 = v.compile_expr(n_value)
-               var e4 = assign_method.compile_call(v, [e2, e3])
+               var e4 = assign_method.compile_expr_call(v, [e2, e3])
                cargs.add(e4)
-               return prop.compile_call(v, cargs)
+               prop.compile_stmt_call(v, cargs)
        end
 end
 
@@ -1477,11 +1519,11 @@ redef class ANewExpr
        redef meth compile_expr(v)
        do
                var cargs = new Array[String]
-               for a in arguments do
-                       cargs.add(v.compile_expr(a))
-               end
+               compile_arguments_in(v, cargs)
                return prop.compile_constructor_call(v, stype, cargs) 
        end
+
+       redef meth compile_stmt(v) do abort
 end
 
 redef class PClosureDef
@@ -1603,7 +1645,7 @@ redef class AClosureDef
                v.nmc.continue_label = "continue_label{v.new_number}"
                v.nmc.break_label = v.nmc.return_label
 
-               if n_expr != null then v.compile_stmt(n_expr)
+               v.compile_stmt(n_expr)
 
                v.add_instr("{v.nmc.continue_label}: while(false);")
 
@@ -1634,7 +1676,7 @@ redef class AClosureDecl
                v.nmc.continue_label = "continue_label{v.new_number}"
                v.nmc.break_label = v.nmc.return_label
 
-               if n_expr != null then v.compile_stmt(n_expr)
+               v.compile_stmt(n_expr)
 
                v.add_instr("{v.nmc.continue_label}: while(false);")
 
@@ -1650,10 +1692,10 @@ redef class AClosureDecl
 end
 
 redef class AClosureCallExpr
-       redef meth compile_expr(v)
+       redef meth intern_compile_call(v)
        do
                var cargs = new Array[String]
-               for a in arguments do cargs.add(v.compile_expr(a))
+               compile_arguments_in(v, cargs)
                var va: String = null
                if variable.closure.signature.return_type != null then va = v.cfc.get_var("Closure call result value")