src: remove remaining references of subclasses on AMethPropdef
[nit.git] / src / compiler_ffi.nit
index 6588b1b..24eb876 100644 (file)
@@ -21,38 +21,53 @@ intrude import abstract_compiler
 intrude import common_ffi
 import nitni
 
-redef class AModule
+redef class MModule
        private var foreign_callbacks = new ForeignCallbackSet
        var nitni_ccu: nullable CCompilationUnit = null
 
-       redef var uses_legacy_ni: Bool = false
-
-       redef fun finalize_ffi(v: AbstractCompilerVisitor, modelbuilder: ModelBuilder)
+       private fun nmodule(v: AbstractCompilerVisitor): nullable AModule
        do
-               finalize_ffi_wrapper(v.compiler.modelbuilder.compile_dir, v.compiler.mainmodule)
-               for file in ffi_files do v.compiler.extern_bodies.add(file)
+               var m2n = v.compiler.modelbuilder.mmodule2nmodule
+               return m2n.get_or_null(self)
        end
 
-       fun ensure_compile_nitni_base(v: AbstractCompilerVisitor)
+       redef fun finalize_ffi(compiler: AbstractCompiler)
        do
-               if nitni_ccu != null then return
+               if not uses_ffi then return
 
-               nitni_ccu = new CCompilationUnit
-       end
+               var v = compiler.new_visitor
+               var n = nmodule(v)
+               if n == null then return
+               n.finalize_ffi_wrapper(v.compiler.modelbuilder.compile_dir, v.compiler.mainmodule)
+               for file in n.ffi_files do v.compiler.extern_bodies.add(file)
 
-       redef fun finalize_nitni(v: AbstractCompilerVisitor)
-       do
                ensure_compile_nitni_base(v)
 
-               nitni_ccu.header_c_types.add("#include \"{mmodule.name}._ffi.h\"\n")
+               nitni_ccu.header_c_types.add("#include \"{name}._ffi.h\"\n")
 
-               nitni_ccu.write_as_nitni(self, v.compiler.modelbuilder.compile_dir)
+               nitni_ccu.write_as_nitni(n, v.compiler.modelbuilder.compile_dir)
 
                for file in nitni_ccu.files do
                        v.compiler.extern_bodies.add(new ExternCFile(file, c_compiler_options))
                end
        end
 
+       fun ensure_compile_nitni_base(v: AbstractCompilerVisitor)
+       do
+               if nitni_ccu != null then return
+
+               nitni_ccu = new CCompilationUnit
+       end
+
+       redef fun collect_linker_libs
+       do
+               var s = c_linker_options
+               if s.is_empty then return null
+               var res = new ArraySet[String]
+               res.add s
+               return res
+       end
+
        var compiled_callbacks: Array[NitniCallback] = new Array[NitniCallback]
 
        # Returns true if callbacks has yet to be generated and register it as being generated
@@ -64,11 +79,12 @@ redef class AModule
        end
 end
 
-redef class AExternPropdef
+redef class AMethPropdef
        fun compile_ffi_support_to_c(v: AbstractCompilerVisitor)
        do
                var mmodule = mpropdef.mclassdef.mmodule
-               var amainmodule = v.compiler.modelbuilder.mmodule2nmodule[v.compiler.mainmodule]
+               var mainmodule = v.compiler.mainmodule
+               var amainmodule = v.compiler.modelbuilder.mmodule2nmodule[mainmodule]
                var amodule = v.compiler.modelbuilder.mmodule2nmodule[mmodule]
                var mclass_type = mpropdef.mclassdef.bound_mtype
 
@@ -79,39 +95,39 @@ redef class AExternPropdef
                # FFI part
                compile_ffi_method(amodule)
 
+               assert self isa AExternPropdef
+
                # nitni - Compile missing callbacks
-               amodule.ensure_compile_nitni_base(v)
-               var ccu = amodule.nitni_ccu.as(not null)
+               mmodule.ensure_compile_nitni_base(v)
+               var ccu = mmodule.nitni_ccu.as(not null)
 
                for mtype in foreign_callbacks.types do
                        if not mtype.is_cprimitive then
                                mtype.compile_extern_type(v, ccu)
 
                                # has callbacks already been compiled? (this may very well happen with global compilation)
-                               if amodule.check_callback_compilation(mtype) then mtype.compile_extern_helper_functions(v, ccu)
+                               if mmodule.check_callback_compilation(mtype) then mtype.compile_extern_helper_functions(v, ccu)
                        end
                end
 
                # compile callbacks
-               for cb in foreign_callbacks.callbacks do if amainmodule.check_callback_compilation(cb) then
+               for cb in foreign_callbacks.callbacks do if mainmodule.check_callback_compilation(cb) then
                        cb.compile_extern_callback(v, ccu)
                end
 
-               for cb in foreign_callbacks.supers do if amainmodule.check_callback_compilation(cb) then
+               for cb in foreign_callbacks.supers do if mainmodule.check_callback_compilation(cb) then
                        cb.compile_extern_callback(v, ccu)
                end
 
-               for cb in foreign_callbacks.casts do if amainmodule.check_callback_compilation(cb) then
+               for cb in foreign_callbacks.casts do if mainmodule.check_callback_compilation(cb) then
                        cb.compile_extern_callbacks(v, ccu)
                end
 
                # manage nitni callback set
-               amodule.foreign_callbacks.join(foreign_callbacks)
+               mmodule.foreign_callbacks.join(foreign_callbacks)
        end
-end
 
-redef class AExternMethPropdef
-       redef fun compile_to_c(v, mpropdef, arguments)
+       redef fun compile_externmeth_to_c(v, mpropdef, arguments)
        do
                var mmodule = mpropdef.mclassdef.mmodule
                var amodule = v.compiler.modelbuilder.mmodule2nmodule[mmodule]
@@ -119,12 +135,6 @@ redef class AExternMethPropdef
                # if using the old native interface fallback on previous implementation
                var nextern = self.n_extern
                if nextern != null then
-                       amodule.uses_legacy_ni = true
-                       super
-                       return
-               end
-
-               if not v.compiler.supports_ffi then
                        super
                        return
                end
@@ -180,10 +190,8 @@ redef class AExternMethPropdef
 
                compile_ffi_support_to_c(v)
        end
-end
 
-redef class AExternInitPropdef
-       redef fun compile_to_c(v, mpropdef, arguments)
+       redef fun compile_externinit_to_c(v, mpropdef, arguments)
        do
                var mmodule = mpropdef.mclassdef.mmodule
                var amodule = v.compiler.modelbuilder.mmodule2nmodule[mmodule]
@@ -191,18 +199,11 @@ redef class AExternInitPropdef
                # if using the old native interface fallback on previous implementation
                var nextern = self.n_extern
                if nextern != null then
-                       amodule.uses_legacy_ni = true
-                       super
-                       return
-               end
-
-               if not v.compiler.supports_ffi then
                        super
                        return
                end
 
                amodule.mmodule.uses_ffi = true
-
                var mclass_type = mpropdef.mclassdef.bound_mtype
 
                var externname = mpropdef.mproperty.build_cname(mpropdef.mclassdef.bound_mtype, mmodule, "___impl", long_signature)
@@ -315,28 +316,35 @@ redef class MNullableType
        do
                super
 
+               var base_cname = "null_{mtype.mangled_cname}"
+               var full_cname = "NIT_NULL___{base_cname}"
+
                # In nitni files, declare internal function as extern 
-               var full_friendly_csignature = "{cname} {v.compiler.mainmodule.name}___null_{mtype.mangled_cname}()"
+               var full_friendly_csignature = "{cname_blind} {full_cname}()"
                ccu.header_decl.add("extern {full_friendly_csignature};\n")
 
                # In nitni files, #define friendly as extern
-               var base_cname = "null_{mtype.mangled_cname}"
-               ccu.header_decl.add("#define {base_cname} {v.compiler.mainmodule.name}___{base_cname}\n")
+               ccu.header_decl.add("#define {base_cname} {full_cname}\n")
+
+               # FIXME: This is ugly an broke the separate compilation principle
+               # The real function MUST be compiled only once, #define pragma only protect the compiler, not the loader
+               # However, I am not sure of the right approach here (eg. week refs are ugly)
+               if is_already_compiled then return
+               is_already_compiled = true
 
                # Internally, implement internal function
                var nitni_visitor = v.compiler.new_visitor
                nitni_visitor.frame = v.frame
-               var full_internal_csignature = "{cname_blind} {v.compiler.mainmodule.name}___null_{mtype.mangled_cname}()"
-               nitni_visitor.add("#ifndef NIT_NULL_null_{mtype.mangled_cname}")
-               nitni_visitor.add("#define NIT_NULL_null_{mtype.mangled_cname}")
+               var full_internal_csignature = "{cname_blind} {full_cname}()"
                nitni_visitor.add("{full_internal_csignature} \{")
                nitni_visitor.add("struct nitni_instance* ret_for_c;")
                nitni_visitor.add("ret_for_c = malloc(sizeof(struct nitni_instance));")
                nitni_visitor.add("ret_for_c->value = NULL;")
                nitni_visitor.add("return ret_for_c;")
                nitni_visitor.add("\}")
-               nitni_visitor.add("#endif")
        end
+
+       private var is_already_compiled = false # FIXME to remove, show above
 end
 
 redef class MExplicitCall
@@ -352,7 +360,7 @@ redef class MExplicitCall
                # Internally, implement internal function
                var nitni_visitor = v.compiler.new_visitor
                nitni_visitor.frame = v.frame
-               var msignature = mproperty.intro.msignature
+               var msignature = mproperty.lookup_first_definition(v.compiler.mainmodule, recv_mtype).msignature
                var csignature_blind = mproperty.build_csignature(recv_mtype, v.compiler.mainmodule, null, long_signature, internal_call_context)
 
                nitni_visitor.add_decl("/* nitni callback for {mproperty.full_name} */")
@@ -393,6 +401,7 @@ redef class MExplicitCall
                if return_mtype != null then
                        assert ret_var != null
                        return_mtype = return_mtype.anchor_to(v.compiler.mainmodule, recv_mtype)
+                       ret_var = nitni_visitor.autobox(ret_var, return_mtype)
                        nitni_visitor.ret_to_c(ret_var, return_mtype)
                end
                nitni_visitor.add("\}")
@@ -419,7 +428,7 @@ redef class MExplicitSuper
                # Internally, implement internal function
                var nitni_visitor = v.compiler.new_visitor
                nitni_visitor.frame = v.frame
-               var msignature = mproperty.intro.msignature
+               var msignature = mproperty.lookup_first_definition(v.compiler.mainmodule, mclass_type).msignature
 
                var csignature_blind = mproperty.build_csignature(mclass_type, v.compiler.mainmodule, "___super", long_signature, internal_call_context)