syntax: allow untyped variable declaration
[nit.git] / src / syntax / icode_generation.nit
index 4b6db99..fb4a801 100644 (file)
@@ -58,7 +58,9 @@ special ICodeBuilder
                if _variables.has_key(v) then
                        return _variables[v]
                else
-                       var reg = new_register(v.stype.as(not null))
+                       var t = v.stype
+                       if t == null then t = visitor.type_object.as_nullable
+                       var reg = new_register(t)
                        _variables[v] = reg
                        return reg
                end
@@ -79,12 +81,16 @@ special ICodeBuilder
        # Register where a functionnal nit return must store its value
        readable writable var _return_value: nullable IRegister
 
+       # The method associated to the iroutine (if any)
+       readable var _method: nullable MMMethod
+
        init(visitor: AbsSyntaxVisitor, r: IRoutine, m: nullable MMMethod)
        do
-               super(visitor.module, r, m)
+               super(visitor.module, r)
                _visitor = visitor
                _return_seq = r.body
                _return_value = r.result
+               _method = m
        end
 
        # Insert implicit super init calls
@@ -115,26 +121,26 @@ special ICodeBuilder
                end
                var l = n.super_init_calls.length
                while i < l do
-                       var p = n.super_init_calls[i]
-                       if p == stop_prop then break
+                       var sp = n.super_init_calls[i]
+                       if sp == stop_prop then break
                        var cargs = new Array[IRegister]
-                       if p.signature.arity == 0 then
+                       if sp.signature.arity == 0 then
                                cargs.add(iroutine.params.first)
                        else
                                for va in iroutine.params do
                                        cargs.add(va)
                                end
                        end
-                       stmt(new ICall(p, cargs))
+                       stmt(new ICall(sp, cargs))
                        i += 1
                end
        end
 
-       # The current  PExpr
-       var _current_node: nullable PExpr = null
+       # The current  AExpr
+       var _current_node: nullable AExpr = null
 
        # Generate icode in the current sequence from a statement
-       fun generate_stmt(n: nullable PExpr)
+       fun generate_stmt(n: nullable AExpr)
        do
                if n == null then return
                var old = _current_node
@@ -144,7 +150,7 @@ special ICodeBuilder
        end
 
        # Generate icode in the current sequence from an expression
-       fun generate_expr(n: PExpr): IRegister
+       fun generate_expr(n: AExpr): IRegister
        do
                var old = _current_node
                _current_node = n
@@ -285,7 +291,7 @@ end
 
 ###############################################################################
 
-redef class PNode
+redef class ANode
        fun accept_icode_generation(v: A2IVisitor) do accept_abs_syntax_visitor(v) end
 end
 
@@ -313,12 +319,8 @@ redef class AMethPropdef
        fun fill_iroutine(v: A2IContext, method: MMSrcMethod) is abstract
 end
 
-redef class PSignature
-       fun fill_iroutine_parameters(v: A2IContext, orig_sig: MMSignature, params: IndexedCollection[IRegister], closdecls: nullable IndexedCollection[IClosureDecl]) is abstract
-end
-
 redef class ASignature
-       redef fun fill_iroutine_parameters(v: A2IContext, orig_sig: MMSignature, params: IndexedCollection[IRegister], closdecls: nullable IndexedCollection[IClosureDecl])
+       fun fill_iroutine_parameters(v: A2IContext, orig_sig: MMSignature, params: Sequence[IRegister], closdecls: nullable Sequence[IClosureDecl])
        do
                for ap in n_params do
                        var reg = v.variable(ap.variable)
@@ -340,7 +342,7 @@ redef class AClosureDecl
        redef fun accept_icode_generation(vv)
        do
                var v = vv.icode_ctx
-               var iclos = variable.closure.signature.generate_empty_iclosuredef
+               var iclos = variable.closure.signature.generate_empty_iclosuredef(v)
                var old_seq = v.seq
                v.seq = iclos.body
                escapable.continue_seq = iclos.body
@@ -544,16 +546,16 @@ redef class AInternMethPropdef
                        end
                else if c == once "NativeArray".to_symbol then
                        if n == once "object_id".to_symbol then
-                               s = "TAG_Int(UNBOX_NativeArray(@@@))"
+                               s = "TAG_Int(((Nit_NativeArray)@@@)->object_id)"
                        else if n == once "[]".to_symbol then
-                               s = "UNBOX_NativeArray(@@@)[UNTAG_Int(@@@)]"
+                               s = "((Nit_NativeArray)@@@)->val[UNTAG_Int(@@@)]"
                        else if n == once "[]=".to_symbol then
-                               s = "UNBOX_NativeArray(@@@)[UNTAG_Int(@@@)]=@@@;"
+                               s = "((Nit_NativeArray)@@@)->val[UNTAG_Int(@@@)]=@@@"
                        else if n == once "copy_to".to_symbol then
                                var t = p[0]
                                p[0] = p[1]
                                p[1] = t
-                               s = "(void)memcpy(UNBOX_NativeArray(@@@), UNBOX_NativeArray(@@@), UNTAG_Int(@@@)*sizeof(val_t));"
+                               s = "(void)memcpy(((Nit_NativeArray )@@@)->val, ((Nit_NativeArray)@@@)->val, UNTAG_Int(@@@)*sizeof(val_t))"
                        end
                else if c == once "NativeString".to_symbol then
                        if n == once "object_id".to_symbol then
@@ -573,7 +575,7 @@ redef class AInternMethPropdef
                                s = "(void)memcpy(UNBOX_NativeString(@@@)+UNTAG_Int(@@@), UNBOX_NativeString(@@@)+UNTAG_Int(@@@), UNTAG_Int(@@@));"
                        end
                else if n == once "object_id".to_symbol then
-                       s = "TAG_Int((bigint)@@@)"
+                       s = "TAG_Int((bigint)((obj_t)@@@)[1].object_id)"
                else if n == once "sys".to_symbol then
                        s = "(G_sys)"
                else if n == once "is_same_type".to_symbol then
@@ -583,10 +585,10 @@ redef class AInternMethPropdef
                        s = "exit(UNTAG_Int(@@@));"
                else if n == once "calloc_array".to_symbol then
                        p[0] = p[1]
-                       s = "BOX_NativeArray((val_t*)malloc((UNTAG_Int(@@@) * sizeof(val_t))))"
+                       s = "NEW_NativeArray(UNTAG_Int(@@@), sizeof(val_t))"
                else if n == once "calloc_string".to_symbol then
                        p[0] = p[1]
-                       s = "BOX_NativeString((char*)malloc((UNTAG_Int(@@@) * sizeof(char))))"
+                       s = "BOX_NativeString((char*)raw_alloc((UNTAG_Int(@@@) * sizeof(char))))"
                end
                if s == null then
                        v.visitor.error(self, "Fatal error: unknown intern method {method.full_name}.")
@@ -603,7 +605,7 @@ end
 
 ###############################################################################
 
-redef class PExpr
+redef class AExpr
        redef fun accept_icode_generation(v) do end
 
        # Generate icode sequence in the current A2IContext
@@ -634,7 +636,15 @@ end
 redef class ADoExpr
        redef fun generate_icode(v)
        do
+               var seq_old = v.seq
+               var seq = new ISeq
+               v.stmt(seq)
+               escapable.break_seq = seq
+               v.seq = seq
+
                v.generate_stmt(n_block)
+
+               v.seq = seq_old
                return null
        end
 end
@@ -734,6 +744,29 @@ redef class AWhileExpr
        end
 end
 
+redef class ALoopExpr
+       redef fun generate_icode(v)
+       do
+               var seq_old = v.seq
+               var iloop = new ILoop
+               v.stmt(iloop)
+               escapable.break_seq = iloop
+               v.seq = iloop
+
+               # Process inside
+               if n_block != null then
+                       var seq = new ISeq
+                       v.stmt(seq)
+                       v.seq = seq
+                       escapable.continue_seq = seq
+                       v.generate_stmt(n_block)
+               end
+
+               v.seq = seq_old
+               return null
+       end
+end
+
 redef class AForExpr
        redef fun generate_icode(v)
        do
@@ -794,6 +827,7 @@ redef class AAssertExpr
                v.stmt(iif)
                var seq_old = v.seq
                v.seq = iif.else_seq
+               v.generate_stmt(n_else)
                var id = n_id
                if id == null then
                        v.add_abort("Assert failed")
@@ -883,7 +917,7 @@ redef class AOrExpr
                v.stmt(iif)
                var seq_old = v.seq
                v.seq = iif.then_seq
-               v.add_assignment(reg, v.generate_expr(n_expr))
+               v.add_assignment(reg, v.lit_true_reg)
 
                # Process right operand (in the else)
                v.seq = iif.else_seq
@@ -905,7 +939,7 @@ redef class AAndExpr
                v.stmt(iif)
                var seq_old = v.seq
                v.seq = iif.else_seq
-               v.add_assignment(reg, v.generate_expr(n_expr))
+               v.add_assignment(reg, v.lit_false_reg)
 
                # Process right operand (in the then)
                v.seq = iif.then_seq
@@ -953,14 +987,14 @@ end
 redef class ATrueExpr
        redef fun generate_icode(v)
        do
-               return v.expr(new INative("TAG_Bool(true)", null), stype)
+               return v.lit_true_reg
        end
 end
 
 redef class AFalseExpr
        redef fun generate_icode(v)
        do
-               return v.expr(new INative("TAG_Bool(false)", null), stype)
+               return v.lit_false_reg
        end
 end
 
@@ -1069,7 +1103,7 @@ end
 redef class ANullExpr
        redef fun generate_icode(v)
        do
-               return v.new_register(stype)
+               return v.lit_null_reg
        end
 end
 
@@ -1133,7 +1167,7 @@ redef class ASuperExpr
                                return null
                        end
                else
-                       var p = prop
+                       p = prop
                        var rtype = p.signature.return_type
                        if rtype == null then
                                v.stmt(new ISuper(p, args))
@@ -1188,10 +1222,29 @@ end
 
 redef class AAbsAbsSendExpr
        # Compile each argument and add them to the array
-       fun generate_icode_for_arguments_in(v: A2IContext, args: Array[IRegister])
-       do
-               for a in arguments do
-                       args.add(v.generate_expr(a))
+       fun generate_icode_for_arguments_in(v: A2IContext, args: Array[IRegister], signature: MMSignature)
+       do
+               var par_arity = signature.arity
+               var par_vararg = signature.vararg_rank
+               var raw_args = raw_arguments
+               var raw_arity = raw_args.length
+               var arg_idx = 0
+               for par_idx in [0..par_arity[ do
+                       var a: AExpr
+                       var par_type = signature[par_idx]
+                       if par_idx == par_vararg then
+                               var arr = v.add_new_array(v.visitor.type_array(par_type), raw_arity-par_arity)
+                               for i in [0..(raw_arity-par_arity)] do
+                                       a = raw_args[arg_idx]
+                                       v.add_call_array_add(arr, v.generate_expr(a))
+                                       arg_idx = arg_idx + 1
+                               end
+                               args.add(arr)
+                       else
+                               a = raw_args[arg_idx]
+                               args.add(v.generate_expr(a))
+                               arg_idx = arg_idx + 1
+                       end
                end
        end
 end
@@ -1202,8 +1255,8 @@ redef class ASendExpr
                var recv = v.generate_expr(n_expr)
                var args = new Array[IRegister]
                args.add(recv)
-               generate_icode_for_arguments_in(v, args)
                var prop = prop
+               generate_icode_for_arguments_in(v, args, prop.signature.as(not null))
                var r: nullable IRegister = null # The full result of the send (raw call + breaks)
                var r2: nullable IRegister # The raw result of the call
 
@@ -1221,14 +1274,24 @@ redef class ASendExpr
                        closcns = new Array[nullable IClosureDef]
                        var cdarity = 0
                        if closure_defs != null then cdarity = closure_defs.length
-                       for i in [0..cdarity[ do
-                               closure_defs[i].escapable.break_seq = seq
-                               closure_defs[i].escapable.break_value = r
-                               var cn = closure_defs[i].generate_iclosuredef(v)
-                               closcns.add(cn)
-                       end
-                       for i in [cdarity..prop_signature.closures.length[ do
-                               closcns.add(null)
+                       var closure_defs = closure_defs
+                       for mmc in prop_signature.closures do
+                               var found = false
+                               var name = mmc.name
+                               if closure_defs != null then
+                                       for cd in closure_defs do
+                                               if cd.n_id.to_symbol != name then continue
+                                               assert found == false
+                                               found = true
+                                               cd.escapable.break_seq = seq
+                                               cd.escapable.break_value = r
+                                               var cn = cd.generate_iclosuredef(v)
+                                               closcns.add(cn)
+                                       end
+                               end
+                               if not found then
+                                       closcns.add(null)
+                               end
                        end
                end
 
@@ -1256,7 +1319,7 @@ redef class ASendReassignExpr
                if n_expr.stype.is_nullable then v.add_null_reciever_check(recv)
                var args = new Array[IRegister]
                args.add(recv)
-               generate_icode_for_arguments_in(v, args)
+               generate_icode_for_arguments_in(v, args, read_prop.signature.as(not null))
 
                var e2 = v.expr(new ICall(read_prop, args), read_prop.signature.return_type.as(not null))
                var e3 = v.generate_expr(n_value)
@@ -1272,7 +1335,7 @@ redef class ANewExpr
        redef fun generate_icode(v)
        do
                var args = new Array[IRegister]
-               generate_icode_for_arguments_in(v, args)
+               generate_icode_for_arguments_in(v, args, prop.signature.as(not null))
                return v.expr(new INew(stype, prop, args), stype)
        end
 end
@@ -1301,14 +1364,10 @@ redef class AOnceExpr
 end
 
 
-redef class PClosureDef
+redef class AClosureDef
        var _iclosure_def: nullable IClosureDef
 
-       fun generate_iclosuredef(v: A2IContext): IClosureDef is abstract
-end
-
-redef class AClosureDef
-       redef fun generate_iclosuredef(v)
+       fun generate_iclosuredef(v: A2IContext): IClosureDef
        do
                # Prepare signature
                var args = new Array[IRegister]
@@ -1350,7 +1409,7 @@ redef class AClosureCallExpr
        do
                # Geneate arguments
                var args = new Array[IRegister]
-               generate_icode_for_arguments_in(v, args)
+               generate_icode_for_arguments_in(v, args, variable.closure.signature)
 
                # Prepare icall
                var closdecl = v.closurevariables[variable]
@@ -1362,7 +1421,7 @@ redef class AClosureCallExpr
                        var iseq = new ISeq
                        icall.break_seq = iseq
                        v.seq = iseq
-                       v.generate_stmt(n_closure_defs.first.as(AClosureDef).n_expr)
+                       v.generate_stmt(n_closure_defs.first.n_expr)
                        v.seq = seq_old
                end
 
@@ -1394,7 +1453,7 @@ redef class AClosureCallExpr
                                v.add_assignment(r, r2)
                        end
                        v.seq = iif.else_seq
-                       var r3 = closdecl_default.inline_in_seq(iif.else_seq, args)
+                       var r3 = v.inline_routine(closdecl_default, args, null)
                        if r != null then
                                assert r3 != null
                                v.add_assignment(r, r3)