# See the License for the specific language governing permissions and
# limitations under the License.
-# Tools and utilities for language targetted FFI implementations
+# Tools and utilities for implement FFI with different languages
module light_ffi_base
import c_tools
import nitni::nitni_utilities
redef class ToolContext
+ # Phase that assign a `FFILanguage` to all `AExternCodeBlock`
var ffi_language_assignation_phase: Phase = new FFILanguageAssignationPhase(self, null)
end
+# Phase that assign a `FFILanguage` to all `AExternCodeBlock`
+#
+# It will also report errors when using an unknown foreign langages.
class FFILanguageAssignationPhase
super Phase
end
redef class MModule
+ # All FFI files linked to this module
var ffi_files = new Array[ExternFile]
end
redef class AExternCodeBlock
+ # User entered name for the language of this block
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
+
+ # `language_name`, in lower case
+ protected fun language_name_lowered: nullable String do
if language_name == null then return null
return language_name.to_lower
end
+ # User entered foreign code in the block
fun code: String do return n_extern_code_segment.without_guard
+ # `FFILanguage` assigned to this block
var language: nullable FFILanguage = null
end
# Visitor for a specific languages. Works kinda like a `Phase` and is executed
# by a `Phase`.
class FFILanguage
+ # `FFILanguageAssignationPhase` assigning `self` to `AExternCodeBlock`s
var ffi_language_assignation_phase: FFILanguageAssignationPhase
init
end
redef class CCompilationUnit
+ # Compile as `_ffi` files which contains the implementation of extern methods
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)
+ write_header_to_file(mmodule, "{compdir}/{h_file}", ["<stdint.h>"], guard)
var c_file = "{base_name}.c"
- write_body_to_file(mmodule, "{compdir}/{c_file}", ["<stdlib.h>", "<stdio.h>", "\"{h_file}\""])
+ write_body_to_file(mmodule, "{compdir}/{c_file}", ["<stdlib.h>", "<stdio.h>", "<stdint.h>", "\"{h_file}\""])
files.add( "{compdir}/{c_file}" )
end
+ # Write the header part to `file` including all `includes` using the `guard`
fun write_header_to_file(mmodule: MModule, file: String, includes: Array[String], guard: String)
do
var stream = new FileWriter.open( file )
stream.close
end
+ # Write the body part to `file` including all `includes`
fun write_body_to_file(mmodule: MModule, file: String, includes: Array[String])
do
var stream = new FileWriter.open(file)
end
end
+# Foreign equivalent types of extern classes
class ForeignType
+ # C type of `self`, by default it is `void*`
fun ctype: String do return "void*"
end