Merge: Better Objective-C FFI and cleanup for OS X
authorJean Privat <jean@pryen.org>
Fri, 16 Jan 2015 10:36:02 +0000 (17:36 +0700)
committerJean Privat <jean@pryen.org>
Fri, 16 Jan 2015 10:36:02 +0000 (17:36 +0700)
This PR opens the way for the iOS platform support.

Two commits may look very similar: "ObjC FFI: import public Objective-C headers for imported modules" and "nitc: fix duplication on imports of public foreign code". They both manage importing headers from other modules so public extern classes may work across module, but one is for Objective-C and the other for C. This service will have to be implemented for other languages too (mostly C++), I'll be looking for a higher level service at that time.

Pull-Request: #1105
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Jean Privat <jean@pryen.org>

12 files changed:
lib/cocoa/examples/cocoa_message_box.nit
lib/cocoa/examples/hello_cocoa.nit
lib/glesv2/examples/opengles2_hello_triangle.nit
src/compiler/compiler.nit
src/ffi/header_dependency.nit
src/ffi/objc.nit
src/platform/android.nit [moved from src/compiler/android_platform.nit with 99% similarity]
src/platform/android_annotations.nit [moved from src/compiler/android_annotations.nit with 100% similarity]
src/platform/emscripten.nit [moved from src/compiler/emscripten_platform.nit with 97% similarity]
src/platform/platform.nit [moved from src/platform.nit with 100% similarity]
src/platform/pnacl.nit [moved from src/compiler/pnacl_platform.nit with 99% similarity]
tests/sav/opengles2_hello_triangle.res [deleted file]

index 72e35d7..224c7ab 100644 (file)
@@ -19,10 +19,6 @@ module cocoa_message_box
 
 import cocoa
 
-in "ObjC" `{
-       #import <Cocoa/Cocoa.h>
-`}
-
 fun dialog in "ObjC" `{
        NSAlert *alert = [[[NSAlert alloc] init] autorelease];
        [alert setMessageText:@"Hello world!"];
index 3a2b168..960b001 100644 (file)
@@ -19,10 +19,6 @@ module hello_cocoa
 
 import cocoa::foundation
 
-in "ObjC" `{
-       #import <Foundation/Foundation.h>
-`}
-
 # Print `"Hello world!"` to the log
 fun hello_world in "ObjC" `{
        @autoreleasepool {
index cfab7ae..cbf851f 100644 (file)
@@ -22,7 +22,7 @@ module opengles2_hello_triangle
 
 import glesv2
 import egl
-import mnit_linux # for sdl
+import mnit_linux::sdl
 import x11
 
 if "NIT_TESTING".environ == "true" then exit(0)
index 902a656..ea60c0a 100644 (file)
@@ -19,6 +19,6 @@ import separate_erasure_compiler
 import global_compiler
 import compiler_ffi
 
-import android_platform
-import pnacl_platform
-import emscripten_platform
+import platform::android
+import platform::pnacl
+import platform::emscripten
index 10c1db3..84bbb29 100644 (file)
@@ -33,36 +33,32 @@ redef class AModule
 end
 
 redef class MModule
-       private var header_dependencies_cache: nullable Array[MModule] = null
-       fun header_dependencies: Array[MModule]
-       do
-               var cache = header_dependencies_cache
-               assert cache != null
-               return cache
-       end
+       # Modules with public foreign code blocks (C header)
+       var header_dependencies: nullable HashSet[MModule] = null
 
        private fun compute_header_dependencies(v: HeaderDependancyPhase)
        do
-               if header_dependencies_cache != null then return
+               if header_dependencies != null then return
 
-               var header_dependencies = new Array[MModule]
+               var header_dependencies = new HashSet[MModule]
 
                # gather from importation
                for m in in_importation.direct_greaters do
-                       m.compute_header_dependencies(v)
+                       m.compute_header_dependencies v
 
-                       # does the super module has inherited dependancies?
+                       # does the super module has inherited dependencies?
                        var hd = m.header_dependencies
+                       assert hd != null
                        if not hd.is_empty then
-                               header_dependencies.add_all(hd)
+                               header_dependencies.add_all hd
                        end
 
-                       # does the super module itself has extern dependancies?
+                       # does the super module itself has extern dependencies?
                        var amodule = v.toolcontext.modelbuilder.mmodule2node(m)
                        if amodule != null and amodule.has_public_c_header then header_dependencies.add(m)
                end
 
-               header_dependencies_cache = header_dependencies
+               self.header_dependencies = header_dependencies
        end
 end
 
index 5c7eeeb..f031289 100644 (file)
@@ -32,6 +32,27 @@ end
 
 redef class MModule
        private var objc_file: nullable ObjCCompilationUnit = null
+
+       private var has_public_objc_header = false
+
+       # Imported modules with public Objective-C code blocks
+       var objc_imported_headers: HashSet[MModule] is lazy do
+               var dep = new HashSet[MModule]
+
+               # gather from importation
+               for m in in_importation.direct_greaters do
+                       # does the super module has inherited dependencies?
+                       var import_dep = m.objc_imported_headers
+                       if not import_dep.is_empty then
+                               dep.add_all import_dep
+                       end
+
+                       # does the super module itself has a public header?
+                       if m.has_public_objc_header then dep.add(m)
+               end
+
+               return dep
+       end
 end
 
 # The Objective-C langugage visitor
@@ -47,6 +68,8 @@ class ObjCLanguage
                if block.is_objc_header then
                        mmodule.objc_file.header_custom.add block.location.as_line_pragma
                        mmodule.objc_file.header_custom.add block.code
+
+                       mmodule.has_public_objc_header = true
                else if block.is_objc_body then
                        mmodule.objc_file.body_custom.add block.location.as_line_pragma
                        mmodule.objc_file.body_custom.add block.code
@@ -77,6 +100,12 @@ class ObjCLanguage
                var objc_file = mmodule.objc_file
                assert objc_file != null
 
+               # Import public Objective-C header of imported modules
+               var dep = mmodule.objc_imported_headers
+               for mod in dep do
+                       objc_file.header_custom.add "#include \"{mod.c_name}._ffi_m.h\"\n"
+               end
+
                # write .m and _m.h file
                mmodule.objc_file.header_c_types.add """
        #include "{{{mmodule.c_name}}}._ffi.h"
@@ -211,6 +240,13 @@ end
 private class FromObjCCallContext
        super ObjCCallContext
 
+       redef fun cast_to(mtype, name)
+       do
+               if mtype isa MClassType and mtype.mclass.ftype isa ForeignObjCType then
+                       return "(__bridge void*)({name})"
+               else return name
+       end
+
        redef fun cast_from(mtype, name)
        do
                if mtype isa MClassType and mtype.mclass.ftype isa ForeignObjCType then
similarity index 99%
rename from src/compiler/android_platform.nit
rename to src/platform/android.nit
index b7069e3..6ba5502 100644 (file)
 # limitations under the License.
 
 # Compile program for the Android platform
-module android_platform
+module android
 
 import platform
-import abstract_compiler
+import compiler::abstract_compiler
 import ffi
 intrude import ffi::extra_java_files
 import android_annotations
similarity index 97%
rename from src/compiler/emscripten_platform.nit
rename to src/platform/emscripten.nit
index 6332098..dc2662f 100644 (file)
 # limitations under the License.
 
 # Compile to JavaScript using the Emscripten SDK
-module emscripten_platform
+module emscripten
 
 import platform
-import abstract_compiler
+import compiler::abstract_compiler
 
 redef class ToolContext
        redef fun platform_from_name(name)
similarity index 100%
rename from src/platform.nit
rename to src/platform/platform.nit
similarity index 99%
rename from src/compiler/pnacl_platform.nit
rename to src/platform/pnacl.nit
index 3f96318..9fceaad 100644 (file)
 # limitations under the License.
 
 # Compile program for the PNaCl platform
-module pnacl_platform
+module pnacl
 
 import platform
-import abstract_compiler
+import compiler::abstract_compiler
 
 redef class ToolContext
        redef fun platform_from_name(name)
diff --git a/tests/sav/opengles2_hello_triangle.res b/tests/sav/opengles2_hello_triangle.res
deleted file mode 100644 (file)
index c1dad34..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-../lib/mnit_linux/linux_app.nit:29,16--31: Redef Error: a virtual type cannot be refined.
-../lib/mnit_linux/linux_app.nit:30,16--29: Redef Error: a virtual type cannot be refined.