From: Alexis Laferrière Date: Fri, 8 May 2015 13:10:55 +0000 (-0400) Subject: src/ffi: separate ffi::ffi in light/full version X-Git-Tag: v0.7.5~64^2~8 X-Git-Url: http://nitlanguage.org src/ffi: separate ffi::ffi in light/full version Signed-off-by: Alexis Laferrière --- diff --git a/src/ffi/ffi.nit b/src/ffi/ffi.nit index 93acf66..15e1dac 100644 --- a/src/ffi/ffi.nit +++ b/src/ffi/ffi.nit @@ -33,19 +33,11 @@ import cpp import java import extra_java_files import objc +intrude import light_ffi redef class MModule - # Does this module uses the FFI? - var uses_ffi: Bool = false - - # C compilation unit for the FFI files - private var ffi_ccu: nullable CCompilationUnit = null - - # Foreign language used in this AModule - private var present_languages = new HashSet[FFILanguage] - # Complete the compilation of the FFI code - fun finalize_ffi_wrapper(compdir: String, mainmodule: MModule) + redef fun finalize_ffi_wrapper(compdir, mainmodule) do for language in ffi_callbacks.keys do for callback in ffi_callbacks[language] do @@ -60,82 +52,10 @@ redef class MModule if mod.uses_ffi then ffi_ccu.header_custom.add("#include \"{mod.c_name}._ffi.h\"\n") end - var cflags = self.cflags[""].join(" ") - - ffi_ccu.write_as_impl(self, compdir) - for filename in ffi_ccu.files do - var f = new ExternCFile(filename, cflags) - f.pkgconfigs.add_all pkgconfigs - ffi_files.add(f) - end - end - - # Avoid the compile a ffi propdef more than once - # See `AMethPropdef::compile_ffi_method` - # FIXME find a better way - private var compiled_ffi_methods = new HashSet[AMethPropdef] -end - -redef class AModule - - # Ensures all of the general foreign code of the module has been analyzed. - # Manages header blocks, extern class types and foreign dependancies between modules - fun ensure_compile_ffi_wrapper - do - var mmodule = mmodule - if mmodule == null or mmodule.ffi_ccu != null then return - - # ready extern code compiler - var ffi_ccu = new CCompilationUnit - mmodule.ffi_ccu = ffi_ccu - - # generate code - for block in n_extern_code_blocks do - var language = block.language - assert language != null - mmodule.present_languages.add(language) - language.compile_module_block(block, ffi_ccu, mmodule) - end - - ffi_ccu.header_c_base.add( "#include \"{mmodule.c_name}._nitni.h\"\n" ) - - ffi_ccu.body_decl.add("#ifdef ANDROID\n") - ffi_ccu.body_decl.add(" #include \n") - ffi_ccu.body_decl.add(" #define PRINT_ERROR(...) (void)__android_log_print(ANDROID_LOG_WARN, \"Nit\", __VA_ARGS__)\n") - ffi_ccu.body_decl.add("#else\n") - ffi_ccu.body_decl.add(" #define PRINT_ERROR(...) fprintf(stderr, __VA_ARGS__)\n") - ffi_ccu.body_decl.add("#endif\n") - - for nclassdef in n_classdefs do - # Does it declares an extern type? - if nclassdef isa AStdClassdef and nclassdef.n_extern_code_block != null then - mmodule.uses_ffi = true - var language = nclassdef.n_extern_code_block.language - assert language != null - mmodule.present_languages.add(language) - nclassdef.n_extern_code_block.language.compile_extern_class( - nclassdef.n_extern_code_block.as(not null), nclassdef, ffi_ccu, mmodule) - end - end + super end end -redef class AMethPropdef - # Compile the necessary wrapper around this extern method or constructor - fun compile_ffi_method(mmodule: MModule) - do - assert n_extern_code_block != null - - if mmodule.compiled_ffi_methods.has(self) then return - mmodule.compiled_ffi_methods.add self - - var language = n_extern_code_block.language - assert language != null - mmodule.present_languages.add(language) - n_extern_code_block.language.compile_extern_method( - n_extern_code_block.as(not null), self, mmodule.ffi_ccu.as(not null), mmodule) - end -end redef class VerifyNitniCallbacksPhase redef fun process_npropdef(npropdef) diff --git a/src/ffi/light_ffi.nit b/src/ffi/light_ffi.nit new file mode 100644 index 0000000..b099681 --- /dev/null +++ b/src/ffi/light_ffi.nit @@ -0,0 +1,118 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2013 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# FFI concers common between the compilers and the interpreter. +# Offers services to compile modules using foreign code. Mainly allows +# to wrap foreign code in Nit methods. +module light_ffi + +import modelbuilder + +import nitni::nitni_utilities + +intrude import light_ffi_base +import extern_classes +import light_c + +redef class MModule + # Does this module uses the FFI? + var uses_ffi: Bool = false + + # C compilation unit for the FFI files + private var ffi_ccu: nullable CCompilationUnit = null + + # Foreign language used in this AModule + private var present_languages = new HashSet[FFILanguage] + + # Complete the compilation of the FFI code + fun finalize_ffi_wrapper(compdir: String, mainmodule: MModule) + do + var cflags = self.cflags[""].join(" ") + + ffi_ccu.write_as_impl(self, compdir) + for filename in ffi_ccu.files do + var f = new ExternCFile(filename, cflags) + f.pkgconfigs.add_all pkgconfigs + ffi_files.add(f) + end + end + + # Avoid the compile a ffi propdef more than once + # See `AMethPropdef::compile_ffi_method` + # FIXME find a better way + private var compiled_ffi_methods = new HashSet[AMethPropdef] +end + +redef class AModule + + # Ensures all of the general foreign code of the module has been analyzed. + # Manages header blocks, extern class types and foreign dependancies between modules + fun ensure_compile_ffi_wrapper + do + var mmodule = mmodule + if mmodule == null or mmodule.ffi_ccu != null then return + + # ready extern code compiler + var ffi_ccu = new CCompilationUnit + mmodule.ffi_ccu = ffi_ccu + + # generate code + for block in n_extern_code_blocks do + var language = block.language + assert language != null + mmodule.present_languages.add(language) + language.compile_module_block(block, ffi_ccu, mmodule) + end + + ffi_ccu.header_c_base.add( "#include \"{mmodule.c_name}._nitni.h\"\n" ) + + ffi_ccu.body_decl.add("#ifdef ANDROID\n") + ffi_ccu.body_decl.add(" #include \n") + ffi_ccu.body_decl.add(" #define PRINT_ERROR(...) (void)__android_log_print(ANDROID_LOG_WARN, \"Nit\", __VA_ARGS__)\n") + ffi_ccu.body_decl.add("#else\n") + ffi_ccu.body_decl.add(" #define PRINT_ERROR(...) fprintf(stderr, __VA_ARGS__)\n") + ffi_ccu.body_decl.add("#endif\n") + + for nclassdef in n_classdefs do + # Does it declares an extern type? + if nclassdef isa AStdClassdef and nclassdef.n_extern_code_block != null then + mmodule.uses_ffi = true + var language = nclassdef.n_extern_code_block.language + assert language != null + mmodule.present_languages.add(language) + nclassdef.n_extern_code_block.language.compile_extern_class( + nclassdef.n_extern_code_block.as(not null), nclassdef, ffi_ccu, mmodule) + end + end + end +end + +redef class AMethPropdef + # Compile the necessary wrapper around this extern method or constructor + fun compile_ffi_method(mmodule: MModule) + do + assert n_extern_code_block != null + + if mmodule.compiled_ffi_methods.has(self) then return + mmodule.compiled_ffi_methods.add self + + var language = n_extern_code_block.language + assert language != null + mmodule.present_languages.add(language) + n_extern_code_block.language.compile_extern_method( + n_extern_code_block.as(not null), self, mmodule.ffi_ccu.as(not null), mmodule) + end +end