Merge remote-tracking branch 'alexandre/at/sep' into wip
[nit.git] / src / global_compiler.nit
index 7483a40..f6fb33d 100644 (file)
@@ -509,7 +509,7 @@ redef class MType
        # Return the name of the C structure associated to a Nit live type
        # FIXME: move to GlobalCompiler so we can check that self is a live type
        fun c_name: String is abstract
-       private var c_name_cache: nullable String
+       protected var c_name_cache: nullable String protected writable
 end
 
 redef class MClassType
@@ -1099,6 +1099,28 @@ class GlobalCompilerVisitor
                return res
        end
 
+       fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable])
+       do
+               var elttype = arguments.first.mtype
+               var recv = "((struct {arguments[0].mcasttype.c_name}*){arguments[0]})->values"
+               if pname == "[]" then
+                       self.ret(self.new_expr("{recv}[{arguments[1]}]", ret_type.as(not null)))
+                       return
+               else if pname == "[]=" then
+                       self.add("{recv}[{arguments[1]}]={arguments[2]};")
+                       return
+               else if pname == "copy_to" then
+                       var recv1 = "((struct {arguments[1].mcasttype.c_name}*){arguments[1]})->values"
+                       self.add("memcpy({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));")
+                       return
+               end
+       end
+
+       fun calloc_array(ret_type: MType, arguments: Array[RuntimeVariable])
+       do
+               self.ret(self.new_expr("NEW_{ret_type.c_name}({arguments[1]})", ret_type))
+       end
+
        # Generate a polymorphic send for the method `m' and the arguments `args'
        fun send(m: MMethod, args: Array[RuntimeVariable]): nullable RuntimeVariable
        do
@@ -1230,34 +1252,8 @@ class GlobalCompilerVisitor
                var recv = self.autobox(args.first, recvtype)
                recv = self.autoadapt(recv, recvtype)
 
-               var vararg_rank = m.msignature.vararg_rank
-               if vararg_rank >= 0 then
-                       assert args.length >= m.msignature.arity + 1 # because of self
-                       var rawargs = args
-                       args = new Array[RuntimeVariable]
-
-                       args.add(rawargs.first) # recv
-
-                       for i in [0..vararg_rank[ do
-                               args.add(rawargs[i+1])
-                       end
-
-                       var vararg_lastrank = vararg_rank + rawargs.length-1-m.msignature.arity
-                       var vararg = new Array[RuntimeVariable]
-                       for i in [vararg_rank..vararg_lastrank] do
-                               vararg.add(rawargs[i+1])
-                       end
-                       # FIXME: its it to late to determine the vararg type, this should have been done during a previous analysis
-                       var elttype = m.msignature.mparameters[vararg_rank].mtype
-                       elttype = self.resolve_for(elttype, recv)
-                       args.add(self.array_instance(vararg, elttype))
-
-                       for i in [vararg_lastrank+1..rawargs.length-1[ do
-                               args.add(rawargs[i+1])
-                       end
-               else
-                       args = args.to_a
-               end
+               args = args.to_a
+               self.varargize(m.msignature.as(not null), args)
                if args.length != m.msignature.arity + 1 then # because of self
                        add("printf(\"NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.\\n\"); exit(1);")
                        debug("NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.")
@@ -1282,6 +1278,42 @@ class GlobalCompilerVisitor
                end
        end
 
+       # Transform varargs, in raw arguments, into a single argument of type Array
+       # Note: this method modify the given `args`
+       # If there is no vararg, then `args` is not modified.
+       fun varargize(msignature: MSignature, args: Array[RuntimeVariable])
+       do
+               var recv = args.first
+               var vararg_rank = msignature.vararg_rank
+               if vararg_rank >= 0 then
+                       assert args.length >= msignature.arity + 1 # because of self
+                       var rawargs = args
+                       args = new Array[RuntimeVariable]
+
+                       args.add(rawargs.first) # recv
+
+                       for i in [0..vararg_rank[ do
+                               args.add(rawargs[i+1])
+                       end
+
+                       var vararg_lastrank = vararg_rank + rawargs.length-1-msignature.arity
+                       var vararg = new Array[RuntimeVariable]
+                       for i in [vararg_rank..vararg_lastrank] do
+                               vararg.add(rawargs[i+1])
+                       end
+                       # FIXME: its it to late to determine the vararg type, this should have been done during a previous analysis
+                       var elttype = msignature.mparameters[vararg_rank].mtype
+                       elttype = self.resolve_for(elttype, recv)
+                       args.add(self.array_instance(vararg, elttype))
+
+                       for i in [vararg_lastrank+1..rawargs.length-1[ do
+                               args.add(rawargs[i+1])
+                       end
+                       rawargs.clear
+                       rawargs.add_all(args)
+               end
+       end
+
        fun bugtype(recv: RuntimeVariable)
        do
                if recv.mtype.ctype != "val*" then return
@@ -1429,6 +1461,14 @@ class GlobalCompilerVisitor
                var res = self.new_var(bool_type)
 
                self.add("/* isa {mtype} on {value.inspect} */")
+               if value.mtype.ctype != "val*" then
+                       if value.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
+                               self.add("{res} = 1;")
+                       else
+                               self.add("{res} = 0;")
+                       end
+                       return res
+               end
                if value.mcasttype isa MNullableType then
                        self.add("if ({value} == NULL) \{")
                        if mtype isa MNullableType then
@@ -1944,23 +1984,8 @@ redef class AInternMethPropdef
                                return
                        end
                else if cname == "NativeArray" then
-                       var elttype = arguments.first.mtype
-                       #assert arguments[0].is_exact
-                       var recv = "((struct {arguments[0].mcasttype.c_name}*){arguments[0]})->values"
-                       if pname == "[]" then
-                               v.ret(v.new_expr("{recv}[{arguments[1]}]", ret.as(not null)))
-                               return
-                       else if pname == "[]=" then
-                               v.add("{recv}[{arguments[1]}]={arguments[2]};")
-                               return
-                       else if pname == "copy_to" then
-                               #assert arguments[1].is_exact
-                               #assert arguments[1].mcasttype == arguments[0].mcasttype else print "copy {arguments[0].mcasttype} to {arguments[1].mcasttype} "
-                               #assert arguments[1].mcasttype == arguments[0].mcasttype else print "copy {arguments[0].mcasttype} to {arguments[1].mcasttype} "
-                               var recv1 = "((struct {arguments[1].mcasttype.c_name}*){arguments[1]})->values"
-                               v.add("memcpy({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));")
-                               return
-                       end
+                       v.native_array_def(pname, ret, arguments)
+                       return
                end
                if pname == "exit" then
                        v.add("exit({arguments[1]});")
@@ -1972,9 +1997,7 @@ redef class AInternMethPropdef
                        v.ret(v.new_expr("(char*)GC_MALLOC({arguments[1]})", ret.as(not null)))
                        return
                else if pname == "calloc_array" then
-                       #var elttype = arguments.first.mtype.supertype_to(v.compiler.mainmodule,arguments.first.mtype.as(MClassType),v.get_class("ArrayCapable")).arguments.first
-
-                       v.ret(v.new_expr("NEW_{ret.c_name}({arguments[1]})", ret.as(not null)))
+                       v.calloc_array(ret.as(not null), arguments)
                        return
                else if pname == "object_id" then
                        v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))