engines: no more `super_inits` method used in old-style automatic init
[nit.git] / src / compiler / abstract_compiler.nit
index a4c55f8..c98d54e 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}"
@@ -1053,16 +1053,21 @@ abstract class AbstractCompilerVisitor
                if not initializers.is_empty then
                        var recv = arguments.first
 
-                       assert initializers.length == arguments.length - 1 else debug("expected {initializers.length}, got {arguments.length - 1}")
                        var i = 1
                        for p in initializers do
                                if p isa MMethod then
-                                       self.send(p, [recv, arguments[i]])
+                                       var args = [recv]
+                                       for x in p.intro.msignature.mparameters do
+                                               args.add arguments[i]
+                                               i += 1
+                                       end
+                                       self.send(p, args)
                                else if p isa MAttribute then
                                        self.write_attribute(p, recv, arguments[i])
+                                       i += 1
                                else abort
-                               i += 1
                        end
+                       assert i == arguments.length
 
                        return self.send(callsite.mproperty, [recv])
                end
@@ -1150,12 +1155,22 @@ abstract class AbstractCompilerVisitor
        # Generate a super call from a method definition
        fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable is abstract
 
+       # Adapt the arguments of a method according to targetted `MMethodDef`
        fun adapt_signature(m: MMethodDef, args: Array[RuntimeVariable]) is abstract
 
+       # Unbox all the arguments of a method when implemented `extern` or `intern`
+       fun unbox_signature_extern(m: MMethodDef, args: Array[RuntimeVariable]) is abstract
+
        # Box or unbox a value to another type iff a C type conversion is needed
        # ENSURE: `result.mtype.ctype == mtype.ctype`
        fun autobox(value: RuntimeVariable, mtype: MType): RuntimeVariable is abstract
 
+       # Box extern classes to be used in the generated code
+       fun box_extern(value: RuntimeVariable, mtype: MType): RuntimeVariable is abstract
+
+       # Unbox extern classes to be used in extern code (legacy NI and FFI)
+       fun unbox_extern(value: RuntimeVariable, mtype: MType): RuntimeVariable is abstract
+
        #  Generate a polymorphic subtype test
        fun type_test(value: RuntimeVariable, mtype: MType, tag: String): RuntimeVariable is abstract
 
@@ -1287,6 +1302,16 @@ abstract class AbstractCompilerVisitor
                return res
        end
 
+       # The difference with `new_var` is the C static type of the local variable
+       fun new_var_extern(mtype: MType): RuntimeVariable
+       do
+               mtype = self.anchor(mtype)
+               var name = self.get_name("var")
+               var res = new RuntimeVariable(name, mtype, mtype)
+               self.add_decl("{mtype.ctype_extern} {name} /* : {mtype} for extern */;")
+               return res
+       end
+
        # Return a new uninitialized named runtime_variable
        fun new_named_var(mtype: MType, name: String): RuntimeVariable
        do
@@ -1611,6 +1636,10 @@ redef class MType
        # Return the C type associated to a given Nit static type
        fun ctype: String do return "val*"
 
+       # C type outside of the compiler code and in boxes
+       fun ctype_extern: String do return "val*"
+
+       # Short name of the `ctype` to use in unions
        fun ctypename: String do return "val"
 
        # Return the name of the C structure associated to a Nit live type
@@ -1642,13 +1671,20 @@ redef class MClassType
                        return "char*"
                else if mclass.name == "NativeArray" then
                        return "val*"
-               else if mclass.kind == extern_kind then
-                       return "void*"
                else
                        return "val*"
                end
        end
 
+       redef fun ctype_extern: String
+       do
+               if mclass.kind == extern_kind then
+                       return "void*"
+               else
+                       return ctype
+               end
+       end
+
        redef fun ctypename: String
        do
                if mclass.name == "Int" then
@@ -1664,8 +1700,6 @@ redef class MClassType
                else if mclass.name == "NativeArray" then
                        #return "{self.arguments.first.ctype}*"
                        return "val"
-               else if mclass.kind == extern_kind then
-                       return "ptr"
                else
                        return "val"
                end
@@ -1913,6 +1947,7 @@ redef class AMethPropdef
                end
                if pname != "==" and pname != "!=" then
                        v.adapt_signature(mpropdef, arguments)
+                       v.unbox_signature_extern(mpropdef, arguments)
                end
                if cname == "Int" then
                        if pname == "output" then
@@ -2149,9 +2184,7 @@ redef class AMethPropdef
                        externname = at.arg_as_string(v.compiler.modelbuilder)
                        if externname == null then return false
                else
-                       var nextern = self.n_extern
-                       if nextern == null then return false
-                       externname = nextern.text.substring(1, nextern.text.length-2)
+                       return false
                end
                if location.file != null then
                        var file = location.file.filename
@@ -2161,14 +2194,16 @@ redef class AMethPropdef
                var ret = mpropdef.msignature.return_mtype
                if ret != null then
                        ret = v.resolve_for(ret, arguments.first)
-                       res = v.new_var(ret)
+                       res = v.new_var_extern(ret)
                end
                v.adapt_signature(mpropdef, arguments)
+               v.unbox_signature_extern(mpropdef, arguments)
 
                if res == null then
                        v.add("{externname}({arguments.join(", ")});")
                else
                        v.add("{res} = {externname}({arguments.join(", ")});")
+                       res = v.box_extern(res, ret.as(not null))
                        v.ret(res)
                end
                return true
@@ -2184,21 +2219,21 @@ redef class AMethPropdef
                        externname = at.arg_as_string(v.compiler.modelbuilder)
                        if externname == null then return false
                else
-                       var nextern = self.n_extern
-                       if nextern == null then return false
-                       externname = nextern.text.substring(1, nextern.text.length-2)
+                       return false
                end
                if location.file != null then
                        var file = location.file.filename
                        v.add_extern(file)
                end
                v.adapt_signature(mpropdef, arguments)
+               v.unbox_signature_extern(mpropdef, arguments)
                var ret = arguments.first.mtype
-               var res = v.new_var(ret)
+               var res = v.new_var_extern(ret)
 
                arguments.shift
 
                v.add("{res} = {externname}({arguments.join(", ")});")
+               res = v.box_extern(res, ret)
                v.ret(res)
                return true
        end
@@ -2289,33 +2324,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
@@ -2893,7 +2907,7 @@ redef class ANewExpr
                        return v.native_array_instance(elttype, l)
                else if ctype == "val*" then
                        recv = v.init_instance(mtype)
-               else if ctype == "void*" then
+               else if ctype == "char*" then
                        recv = v.new_expr("NULL/*special!*/", mtype)
                else
                        recv = v.new_expr("({ctype})0/*special!*/", mtype)