X-Git-Url: http://nitlanguage.org diff --git a/src/ffi/ffi_base.nit b/src/ffi/ffi_base.nit index e470276..963df27 100644 --- a/src/ffi/ffi_base.nit +++ b/src/ffi/ffi_base.nit @@ -22,184 +22,17 @@ import parser import modelbuilder import nitni -redef class ToolContext - var ffi_language_assignation_phase: Phase = new FFILanguageAssignationPhase(self, null) -end - -class FFILanguageAssignationPhase - super Phase - - # All supported languages - var languages = new Array[FFILanguage] - - redef fun process_nmodule(nmodule) - do - for block in nmodule.n_extern_code_blocks do - verify_foreign_code_on_node( block ) - end - end - - redef fun process_npropdef(npropdef) - do - if npropdef isa AMethPropdef then - var code_block = npropdef.n_extern_code_block - if code_block != null then - verify_foreign_code_on_node( code_block ) - end - end - end - - redef fun process_nclassdef(nclassdef) - do - if nclassdef isa AStdClassdef and nclassdef.n_extern_code_block != null then - verify_foreign_code_on_node( nclassdef.n_extern_code_block.as(not null) ) - end - end - - private fun verify_foreign_code_on_node(n: AExternCodeBlock) - do - var found = false - for v in languages do - var identified = v.identify_language(n) - if identified then - if found and identified then - toolcontext.error(n.location, "Two languages identified as possible handlers.") - end - n.language = v - found = true - end - end - - if not found then toolcontext.error(n.location, "Unsupported language.") - end -end +import light_ffi_base redef class MModule - var ffi_files = new Array[ExternFile] - # Callbacks used by this module, classified by language var ffi_callbacks = new HashMap[FFILanguage, Set[NitniCallback]] end -redef class AExternCodeBlock - fun language_name: nullable String do - if n_in_language == null then return null - return n_in_language.n_string.without_quotes - end - fun language_name_lowered: nullable String do - if language_name == null then return null - return language_name.to_lower - end - - fun code: String do return n_extern_code_segment.without_guard - - var language: nullable FFILanguage = null -end - # Visitor for a specific languages. Works kinda like a `Phase` and is executed # by a `Phase`. -class FFILanguage - var ffi_language_assignation_phase: FFILanguageAssignationPhase - - init - do - ffi_language_assignation_phase.languages.add(self) - end - - # Is this `block` written in this language? - fun identify_language(block: AExternCodeBlock ): Bool is abstract - - # Generate wrapper code for this module/header code block - fun compile_module_block(block: AExternCodeBlock, ecc: CCompilationUnit, mmodule: MModule) is abstract - - # Generate wrapper code for this extern method - fun compile_extern_method(block: AExternCodeBlock, m: AMethPropdef, - ecc: CCompilationUnit, nmodule: MModule) is abstract - - # Generate wrapper code for this extern class - fun compile_extern_class(block: AExternCodeBlock, m: AClassdef, - ecc: CCompilationUnit, mmodule: MModule) is abstract - - # Get the foreign type of this extern class definition - fun get_ftype(block: AExternCodeBlock, m: AClassdef): ForeignType is abstract - +redef class FFILanguage # Generate the code to offer this callback if foreign code fun compile_callback(callback: NitniCallback, mmodule: MModule, mainmmodule: MModule, ecc: CCompilationUnit) is abstract - - # Complete compilation of generated code - fun compile_to_files(mmodule: MModule, directory: String) do end -end - -redef class TString - # Returns the content of this node without both of the surrounding " - fun without_quotes: String - do - assert text.length >= 2 - return text.substring(1, text.length-2) - end -end - -redef class TExternCodeSegment - # Returns the content of this node without the surrounding `{ and `} - fun without_guard: String - do - assert text.length >= 4 - return text.substring(2, text.length-4) - end -end - -redef class CCompilationUnit - fun write_as_impl(mmodule: MModule, compdir: String) - do - var base_name = "{mmodule.name}._ffi" - - var h_file = "{base_name}.h" - var guard = "{mmodule.cname.to_s.to_upper}_NIT_H" - write_header_to_file(mmodule, "{compdir}/{h_file}", new Array[String], guard) - - var c_file = "{base_name}.c" - write_body_to_file(mmodule, "{compdir}/{c_file}", ["", "", "\"{h_file}\""]) - - files.add( "{compdir}/{c_file}" ) - end - - fun write_header_to_file(mmodule: MModule, file: String, includes: Array[String], guard: String) - do - var stream = new OFStream.open( file ) - - # header comments - var module_info = "/*\n\tExtern implementation of Nit module {mmodule.name}\n*/\n" - - stream.write( module_info ) - - stream.write( "#ifndef {guard}\n" ) - stream.write( "#define {guard}\n\n" ) - - for incl in includes do stream.write( "#include {incl}\n" ) - - compile_header_core( stream ) - - # header file guard close - stream.write( "#endif\n" ) - stream.close - end - - fun write_body_to_file(mmodule: MModule, file: String, includes: Array[String]) - do - var stream = new OFStream.open(file) - - var module_info = "/*\n\tExtern implementation of Nit module {mmodule.name}\n*/\n" - - stream.write( module_info ) - for incl in includes do stream.write( "#include {incl}\n" ) - - compile_body_core( stream ) - - stream.close - end -end - -class ForeignType - fun ctype: String do return "void*" end