src/ffi: separate ffi::ffi_base in light/full modules
authorAlexis Laferrière <alexis.laf@xymus.net>
Fri, 8 May 2015 12:53:10 +0000 (08:53 -0400)
committerAlexis Laferrière <alexis.laf@xymus.net>
Fri, 8 May 2015 14:31:43 +0000 (10:31 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

src/ffi/ffi_base.nit
src/ffi/light_ffi_base.nit [new file with mode: 0644]

index b8a8103..963df27 100644 (file)
@@ -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, "FFI Error: two languages identified as possible handlers.")
-                               end
-                               n.language = v
-                               found = true
-                       end
-               end
-
-               if not found then toolcontext.error(n.location, "FFI Error: 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.c_name}._ffi"
-
-               var h_file = "{base_name}.h"
-               var guard = "{mmodule.c_name.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}", ["<stdlib.h>", "<stdio.h>", "\"{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 FileWriter.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 FileWriter.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
diff --git a/src/ffi/light_ffi_base.nit b/src/ffi/light_ffi_base.nit
new file mode 100644 (file)
index 0000000..e3014a5
--- /dev/null
@@ -0,0 +1,198 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Tools and utilities for language targetted FFI implementations
+module light_ffi_base
+
+import c_tools
+import parser
+import modelbuilder
+import nitni::nitni_utilities
+
+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, "FFI Error: two languages identified as possible handlers.")
+                               end
+                               n.language = v
+                               found = true
+                       end
+               end
+
+               if not found then toolcontext.error(n.location, "FFI Error: unsupported language.")
+       end
+end
+
+redef class MModule
+       var ffi_files = new Array[ExternFile]
+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
+
+       # 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.c_name}._ffi"
+
+               var h_file = "{base_name}.h"
+               var guard = "{mmodule.c_name.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}", ["<stdlib.h>", "<stdio.h>", "\"{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 FileWriter.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 FileWriter.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