From: Alexis Laferrière Date: Wed, 29 Jan 2014 16:03:21 +0000 (-0500) Subject: src: delete old ffi and native_interface code X-Git-Tag: v0.6.4~27^2~2 X-Git-Url: http://nitlanguage.org src: delete old ffi and native_interface code Signed-off-by: Alexis Laferrière --- diff --git a/src/ffi/c.nit b/src/ffi/c.nit deleted file mode 100644 index 329d9a3..0000000 --- a/src/ffi/c.nit +++ /dev/null @@ -1,61 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# Copyright 2012-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. - -# Handles C inline code -# Wraps all code in a thin wrapper. -module c - -import ffi_base - -redef class ExternCode - fun is_c : Bool do return language == null or - language_lowered == "c" or language_lowered.has_prefix( "c " ) - - fun is_c_body : Bool do return language == null or - language_lowered == "c" or language_lowered == "c body" - - fun is_c_header : Bool do return language_lowered == "c header" - - redef fun accept_ffi_visitor( v ) - do - if is_c_header then - v.compilation_unit.header_custom.add( code ) - else if is_c_body then - v.compilation_unit.body_custom.add( code ) - end - end -end - -redef class MMMethod - redef fun accept_ffi_visitor( v ) - do - if extern_implementation.is_c then - var fc = new CFunction( impl_csignature ) - fc.decls.add( extern_implementation.location.as_line_pragma ) - fc.exprs.add( extern_implementation.code ) - v.compilation_unit.add_exported_function( fc ) - else - super - end - end -end - -redef class Location - fun as_line_pragma : String - do - return "#line {line_start} \"{file.filename}\"\n" - end -end diff --git a/src/ffi/ffi.nit b/src/ffi/ffi.nit deleted file mode 100644 index aa85bbd..0000000 --- a/src/ffi/ffi.nit +++ /dev/null @@ -1,78 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# Copyright 2012-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. - -# This module implements the FFI with different languages -module ffi - -import c - -redef class MMSrcModule - redef fun compile_separate_module(cprogram: CProgram) - do - super - - if is_extern_hybrid then - var visitor = new FFIVisitor( cprogram.program.tc, self ) - # TODO use cprogram to add generated files? - - # actually compile stub - accept_ffi_visitor( visitor ) - - # write to file - if uses_ffi then - visitor.compile - end - end - end -end - -redef class FFIVisitor - fun compile - do - var compdir = tc.compdir.as(not null) - var base_name = "{mmmodule.cname}._ffi" - var c_file = "{base_name}.c" - var h_file = "{base_name}.h" - - # header comments - var module_info = "/*\n\tExtern implementation of Nit module {mmmodule.name}\n*/\n" - - # header file guard - var guard = "{mmmodule.cname.to_s.to_upper}_NIT_H" - - # .h - var stream = new OFStream.open( "{compdir}/{h_file}" ) - stream.write( module_info ) - stream.write( "#include <{mmmodule.name}._nitni.h>\n\n" ) - stream.write( "#ifndef {guard}\n" ) - stream.write( "#define {guard}\n\n" ) - compilation_unit.header_c_base.write_to_stream( stream ) - compilation_unit.header_custom.write_to_stream( stream ) - compilation_unit.header_c_types.write_to_stream( stream ) - compilation_unit.header_decl.write_to_stream( stream ) - stream.write( "#endif\n" ) - stream.close - - # .c - stream = new OFStream.open( "{compdir}/{c_file}" ) - stream.write( module_info ) - stream.write( "#include \"{h_file}\"\n" ) - compilation_unit.body_decl.write_to_stream( stream ) - compilation_unit.body_custom.write_to_stream( stream ) - compilation_unit.body_impl.write_to_stream( stream ) - stream.close - end -end diff --git a/src/ffi/ffi_base.nit b/src/ffi/ffi_base.nit deleted file mode 100644 index 7b24be8..0000000 --- a/src/ffi/ffi_base.nit +++ /dev/null @@ -1,126 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# Copyright 2012-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. - -module ffi_base - -import native_interface -import syntax # TODO move extern_implementation to MM -import c_tools - -interface FFIVisited - fun accept_ffi_visitor( v : FFIVisitor ) do end -end - -redef class ExternCode - super FFIVisited - - # last resort for extern method - # assumes this is a code block in the root of a module - # should never be called if the extern method is implemented inline by a known language - redef fun accept_ffi_visitor( v ) - do - var language = self.language - if language != null then - v.tc.warning( null, "language \"{language}\" used to implement a code block in {v.mmmodule} is unknown." ) - else - v.tc.warning( null, "please specify a language to implement code blocks in {v.mmmodule}." ) # is ok with spec as of now, won't be raised - end - end - - var language_lowered : nullable String = null - - redef init ( language, code, loc ) - do - super - if language != null then language_lowered = language.to_lower - end -end - -redef class MMMethod - super FFIVisited - - # last resort for extern method - # should never be called if the extern method is implemented inline by a known language - redef fun accept_ffi_visitor( v ) - do - if extern_implementation != null then - var language = extern_implementation.language - if language != null then - v.tc.warning( null, "language \"{language}\" used to implement {full_name} is unknown." ) - else - v.tc.warning( null, "please specify a language to implement {full_name}." ) # is ok with spec as of now, won't be raised - end - end - end -end - -# set of extern imports in a language to be used by a module -# FIXME move to native_interface or MM? -class ExternImportSet - # set of imported functions, cached to avoid repetitions - var callbacks : Set[ MMExplicitImport ] = new HashSet[ MMExplicitImport ] - - # set of imported functions, cached to avoid repetitions - var supers : Set[ MMExplicitImport ] = new HashSet[ MMExplicitImport ] - - # set of relevant types, cached to avoid repetitions - var types : Set[ MMType ] = new HashSet[ MMType ] - - # set of imported casts and as, cached to avoid repetitions - var casts : Set[ MMImportedCast ] = new HashSet[ MMImportedCast ] -end - -redef class MMLocalClass - super FFIVisited - - fun c_type : nullable String do return null -end - -redef class MMModule - super FFIVisited - - redef fun accept_ffi_visitor( v ) - do - for local_class in local_classes do - # if class is extern and defined here first - if local_class.global.intro == local_class and - local_class.global.is_extern then - local_class.accept_ffi_visitor( v ) - end - - for prop in local_class.local_local_properties do - # if defined of redefined in this module and is extern - if prop.mmmodule == self and prop isa MMMethod and prop.is_extern and - prop.extern_implementation != null then - prop.accept_ffi_visitor( v ) - end - end - - end - - for block in extern_code_blocks do block.accept_ffi_visitor( v ) - end -end - -class FFIVisitor - var tc : ToolContext - - # module being visited - var mmmodule : MMModule - - var compilation_unit = new CCompilationUnit -end - diff --git a/src/native_interface/frontier.nit b/src/native_interface/frontier.nit deleted file mode 100644 index 3d12896..0000000 --- a/src/native_interface/frontier.nit +++ /dev/null @@ -1,679 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# Copyright 2011 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. - -# Information and tools relevant to the frontier files -module frontier - -import metamodel - -import ni_tools -import ni_metamodel - -import syntax # FIXME: to remove since it breaks modularity - -# Transitive variable through the frontier file -# Represents a variable going from Nit to C or from C to Nit -abstract class NiVariable - fun ni_from_name : String is abstract - fun ni_to_name : String is abstract - fun ni_type : MMType is abstract - - # needs to be boxed or unboxed - # anything using the GC - fun needs_preparation : Bool - do - return ni_type.local_class.primitive_info == null or - not ni_type.local_class.primitive_info.tagged or - ni_type.is_nullable - end - - # prepare variable to callback to Nit - fun prepare_for_nit( fc : FunctionCompiler ) - do - if needs_preparation then - fc.decls.add( "val_t {ni_to_name};\n" ) - fc.exprs.add( "{ni_type.assign_from_friendly( ni_to_name, ni_from_name )};\n" ) - end - end - - fun prepare_for_c( fc : FunctionCompiler ) - do - if needs_preparation then - ni_type.compile_new_local_ref( ni_to_name, fc, not self isa ReturnVariable ) # TODO - fc.exprs.add( "{ni_type.assign_to_friendly( ni_to_name, ni_from_name )};\n" ) - end - end - - # format of the variable to callback to Nit - fun as_arg_to_nit : String - do - if needs_preparation then - return ni_to_name - else if ( ni_type.local_class.primitive_info != null or ni_type.local_class.global.is_extern ) and - not ni_type.is_nullable then # int, float, point/void* ... - return ni_type.boxtype(ni_from_name) - else - return "{ni_from_name}->ref.val" - end - end - - # format of the variable to call C implementation functions - fun as_arg_to_c : String - do - if needs_preparation then - return ni_to_name - else - return ni_type.unboxtype( ni_from_name ) - end - end -end - -redef class MMParam - super NiVariable - - redef fun ni_from_name do return name.to_s - redef fun ni_to_name do return "trans___{name}" - redef fun ni_type do return mmtype -end - -class ReceiverVariable - super NiVariable - - redef fun ni_from_name do return "recv" - redef fun ni_to_name do return "trans_recv" - - redef var ni_type : MMType - init ( t : MMType ) do ni_type = t -end - -class ReturnVariable - super NiVariable - - redef fun ni_from_name do return "orig_return" - redef fun ni_to_name do return "trans_return" - - redef var ni_type : MMType - init ( t : MMType ) do ni_type = t - - # used only by friendly callbacks to Nit - redef fun prepare_for_c( fc ) - do - fc.decls.add( "val_t {ni_from_name};\n" ) - ni_type.compile_new_local_ref( ni_to_name, fc, true ) - end - redef fun prepare_for_nit( fc ) - do - ni_type.compile_new_local_ref( ni_from_name, fc, false ) - fc.decls.add( "val_t {ni_to_name};\n" ) - end -end - -redef class MMSrcModule - fun compile_frontier( v : FrontierVisitor ) - do - # assumes is extern hybrid (verified by caller) - - v.body.add( "#include \"{name}._nitni.h\"\n" ) - - # guard - v.header_top.add( "#include \n" ) - v.header_top.add( "#include \"{v.cprogram.module_header_name(self)}\"\n" ) - - var guard_name = "{name.to_s.to_upper}_NITNI_H" - v.header_top.add( "#ifndef {guard_name}\n" ) - v.header_top.add( "#define {guard_name}\n\n" ) - - # import custom _nit.h file from frontier - var native_header = "{directory.path}/{name}.nit.h" - if not native_header.file_exists then # try old style - native_header = "{directory.path}/{name}_nit.h" - end - if native_header.file_exists then - var path = "..".join_path(native_header).simplify_path - v.body.add( "#include \"{path}\"\n" ) - v.header.add( "#include \"{path}\"\n" ) - end - if uses_ffi then - v.header.add( "#include <{cname}._ffi.h>\n" ) - end - - for local_class in local_classes do - ### extern methods - for prop in local_class.local_local_properties do - # if defined of redefined in this module - # and is extern - if prop.mmmodule == self and - prop isa MMSrcMethod and prop.is_extern then - prop.compile_extern_to_frontier( v ) - end - end - end - - v.compile_cached - - v.header.add( "#endif\n" ) - end -end - -redef class MMSrcMethod - fun compile_extern_to_frontier( v : FrontierVisitor ) - do - # defines types used in signature - if signature != null then - signature.compile_frontier( v ) - end - - for imported in explicit_imports do - # adds friendly access to property - v.friendlys.add( imported ) - - # defines relevant types - imported.signature.compile_frontier( v ) - end - - # adds casts and as verifications - for cast in explicit_casts do - v.casts.add( cast ) - - v.types.add( cast.from.direct_type ) - v.types.add( cast.to.direct_type ) - end - - # adds super - if need_super then - compile_super_to_frontier( v ) - end - - # adds function in frontier to be called by pure nit - compile_out_to_frontier( v ) - end - - # Compiles body and header for the friendly super method. - # The friendly super method is called by custom native code and - # calls the generated C code to execute the real implementation. - # It handles types conversion and verifications. - fun compile_super_to_frontier( v : FrontierVisitor ) - do - # header - v.header.add( "\n/* friendly for super of {full_name} */\n" ) - v.header.add( "{frontier_super_csignature_from( mmmodule )};\n" ) - - # Defines a local name for simplier use, as with friendlys. - v.header.add( "#ifndef {friendly_super_cname}\n" ) - v.header.add( "#define {friendly_super_cname} {local_friendly_super_name_from( mmmodule )}\n" ) - v.header.add( "#endif\n" ) - - # body - v.body.add( "\n/* friendly for super of {full_name} */\n" ) - var fc = new FunctionCompiler( friendly_super_csignature ) - - # params - var params = new Array[NiVariable] - params.add( signature.recv_ni_variable ) - params.add_all( signature.params ) - - # prepare transition - for p in params do p.prepare_for_nit( fc ) - - # extract strings - var args = new Array[String] - for p in params do args.add( p.as_arg_to_nit ) - - # hook to generated C - var rnv = signature.return_ni_variable - var s = new Buffer - if rnv != null then - rnv.prepare_for_c( fc ) - s.append( "{rnv.ni_from_name} = " ) - end - - s.append( "{super_meth_call}( {signature.recv_ni_variable.as_arg_to_nit} )" ) - s.append( "( {args.join( ", " )} );\n" ) - - fc.exprs.add( s.to_s ) - - # return - if rnv != null then - fc.exprs.add( "{rnv.ni_type.assign_to_friendly( rnv.ni_to_name, rnv.ni_from_name )};\n" ) - fc.exprs.add( "return {rnv.ni_to_name};\n" ) - end - - v.body.append( fc.to_writer ) - end - - # Compiles body and header for the out method. - # The out method is called by generated C code - # It handles variables conversions and verification - fun compile_out_to_frontier( v : FrontierVisitor ) - do - # a simple out method can be optimized - # To qualify as simple this method must: - # - have no explicit imports (including super and casts) - # - return nothing or return a primitive to C - var is_simple = explicit_imports.is_empty and not need_super and - explicit_casts.is_empty and (signature.return_type == null or - signature.return_type.local_class.primitive_info != null ) - - # header - v.header.add( "\n/* out/indirect function for {full_name} */\n" ) - v.header.add( "{out_csignature};\n" ) # incoming types boxed - - # body - v.body.add( "/* out/indirect function for {full_name} */\n" ) - var fc = new FunctionCompiler( out_csignature ) - - # params - var params = new List[NiVariable] - if not is_init then params.add( signature.recv_ni_variable ) - params.add_all( signature.params ) - - var args = new List[String] - - for nv in params do - if not is_simple or nv.ni_type.local_class.primitive_info != null then - nv.prepare_for_c( fc ) - args.add( nv.as_arg_to_c ) - else - args.add( "NULL" ) - end - end - - # call to impl - var rnv = signature.return_ni_variable - if rnv == null and is_init then - rnv = new ReturnVariable( signature.recv ) - end - - var s = new Buffer - if rnv != null then - rnv.prepare_for_nit( fc ) - s.append( "{rnv.ni_from_name} = " ) - end - - s.append( "{extern_name.as(not null)}( {args.join( ", " )} );\n" ) - - fc.exprs.add( s.to_s ) - - if rnv != null then - fc.exprs.add( "{rnv.ni_type.assign_from_friendly( rnv.ni_to_name, rnv.ni_from_name )};\n" ) - end - - fc.exprs.add( "nitni_local_ref_clean( );\n" ) - - # return - if rnv != null then - fc.exprs.add( "return {rnv.ni_to_name};\n" ) - end - - v.body.append( fc.to_writer ) - end - -end - -redef class MMSignature - var recv_ni_variable : ReceiverVariable - var return_ni_variable : nullable ReturnVariable - redef init( params, return_type, recv_type ) - do - super - - if return_type != null then - return_ni_variable = new ReturnVariable( return_type ) - else - return_ni_variable = null - end - recv_ni_variable = new ReceiverVariable( recv_type ) - end - - fun compile_frontier( v : FrontierVisitor ) - do - # receiver - v.types.add( recv.direct_type ) - - # params - for p in params do v.types.add( p.mmtype.direct_type ) - - # return - var rt = return_type - if rt != null then - v.types.add( rt.direct_type ) - end - end -end - -class FrontierVisitor - # frontier file header - - # header comments, imports, guard and types - var header_top : Writer = new Writer - - # rest of header - var header : Writer = new Writer - - # frontier file body - var body : Writer = new Writer - - # set of imported functions, cached to avoid repetitions - var friendlys : Set[ MMExplicitImport ] = new HashSet[ MMExplicitImport ] - - # set of relevant types, cached to avoid repetitions - var types : Set[ MMType ] = new HashSet[ MMType ] - - # set of imported casts and as, cached to avoid repetitions - var casts : Set[ MMImportedCast ] = new HashSet[ MMImportedCast ] - - var mmmodule : MMModule - - var cprogram : CProgram - - # compiles cached types and callbacks - fun compile_cached - do - # types - for t in types do t.compile_to_frontier( self ) - - # friendlys - for friendly in friendlys do friendly.compile_friendly_to_frontier( self ) - - # casts - for cast in casts do cast.compile_to_frontier( self ) - end - - fun write_to_files( base_path : String ) - do - var path = "{base_path}._nitni.h" - var stream = new OFStream.open( path ) - header_top.write_to_stream( stream ) - header.write_to_stream( stream ) - stream.close - - path = "{base_path}._nitni.c" - stream = new OFStream.open( path ) - body.write_to_stream( stream ) - stream.close - end -end - -redef class MMImportedCast - # Defines functions to cast types and verify the type of an object. - fun compile_to_frontier( v : FrontierVisitor ) - do - # compile isa check - if not ( is_about_nullable_only and is_not_null_to_nullable ) then - v.header.add( "\n/* Type check for {from} with {to} */\n" ) - v.header.add( "{is_a_local_csignature( v.mmmodule )};\n" ) - - v.header.add( "#ifndef {is_a_friendly_extern_name}\n" ) - v.header.add( "#define {is_a_friendly_extern_name} {is_a_local_cname( v.mmmodule )}\n" ) - v.header.add( "#endif\n" ) - - var fc = compile_is( v.mmmodule ) - v.body.append( fc.to_writer ) - end - - # compile cast itself - v.header.add( "\n/* Cast for {from} to {to} */\n" ) - v.header.add( "{as_local_csignature( v.mmmodule )};\n" ) - - v.header.add( "#ifndef {as_friendly_extern_name}\n" ) - v.header.add( "#define {as_friendly_extern_name} {as_local_cname( v.mmmodule )}\n" ) - v.header.add( "#endif\n" ) - - var fc = compile_as( v.mmmodule ) - v.body.append( fc.to_writer ) - end - - # Compiles a function to cast an object to a different type. - # Verify type and if it is null. - fun compile_as( m : MMModule ) : FunctionCompiler - do - var fc = new FunctionCompiler( as_local_csignature( m ) ) - - var out_name = "out" - var temp_name = "temp" - - fc.decls.add( "val_t {temp_name};\n" ) - to.compile_new_local_ref( out_name, fc, true ) - - fc.exprs.add( "{from.assign_from_friendly(temp_name, in_name)};\n" ) - - # makes sur it is not null if it cannot be - if not to.is_nullable then - compile_check_is_not_null( fc, temp_name ) - end - - # makes sure it's the right type, unless it's only a cast about null - if not is_about_nullable_only then # inter types - to.compile_check_isa( fc, temp_name ) - end - - fc.exprs.add( "{to.assign_to_friendly(out_name, temp_name)};\n" ) - - fc.exprs.add( "return {out_name};\n" ) - - return fc - end - - # Compiles a function to verify if an object is of the given type. - # Verify type and if it is null. - fun compile_is( m : MMModule ) : FunctionCompiler - do - var fc = new FunctionCompiler( is_a_local_csignature( m ) ) - - var temp_name = "temp" - fc.decls.add( "val_t {temp_name};\n" ) - - fc.exprs.add( "{from.assign_from_friendly(temp_name, in_name)};\n" ) - - if is_nullable_to_not_null then # from null - if is_about_nullable_only then # opposite, we want to know if null - fc.exprs.add( "if ( ! ISNULL({temp_name}) ) return 0;\n" ) - else - fc.exprs.add( "if ( ISNULL({temp_name}) ) return 0;\n" ) - end - end - - if not is_about_nullable_only then # inter types - fc.exprs.add( "if ( ! {to.compile_condition_isa( temp_name )} ) return 0;\n" ) - end - - fc.exprs.add( "return 1;\n" ) - - return fc - end - - # Compiles lines of code to check if an object is not null. - # Is to be nested within another function. - fun compile_check_is_not_null( fc : FunctionCompiler, name : String ) - do - fc.exprs.add( "if ( ISNULL({name}) )\{" ) - fc.exprs.add( "\tfprintf( stderr, \"Casting from {from} to {to} failed because value is null.\" );\n" ) - fc.exprs.add( "\tabort();\n" ) - fc.exprs.add( "\}" ) - end - - redef fun ==( other ) - do - return other isa MMImportedCast and - other.from == from and other.to == to - end - redef fun hash - do - return from.hash + to.hash - end -end - -redef class MMType - # Compiles a lines of code to ensure that an object is of the given type. - # Aborts when it is of the wrong type - # Does not check if it is null. - # Is to be nested within another function. - fun compile_check_isa( fc : FunctionCompiler, name : String ) - do - fc.exprs.add( "if ( ! {compile_condition_isa( name )} )\{\n" ) - fc.exprs.add( "\tfprintf( stderr, \"Casting to {self} failed because value is not a {self}.\" );\n" ) - fc.exprs.add( "\tabort();\n" ) - fc.exprs.add( "\}\n" ) - end - - # Compiles an expression to verify if an object is of the given type. - # To be nested within a condition. - fun compile_condition_isa( var_name : String ) : String - do - return "( ISOBJ( {var_name} ) ? ISNULL( {var_name} ) || OBJISA( {var_name}, {local_class.cname} ): VALISA( {var_name}, {local_class.cname} ) )" - end - - # Defines a friendly type in C for a given Nit type. - # Standard Nit classes are kept within a struct. - fun compile_to_frontier( v : FrontierVisitor ) - do - var pi = local_class.primitive_info - if pi == null or is_nullable then - var name = friendly_extern_name - var guard = "{name.to_s.to_upper}_TYPE" - - # defines struct - v.header_top.add( "#ifndef {guard}\n" ) - v.header_top.add( "#define {guard}\n" ) - v.header_top.add( "struct s_{name}\{\n" ) - v.header_top.add( "\t\tstruct nitni_ref ref; /* real ref struct, must be first */\n" ) - v.header_top.add( "\};\n" ) - v.header_top.add( "typedef struct s_{name} *{name};\n" ) - - # add null version, as a struct - if is_nullable then - var local_null_getter = local_friendly_null_getter_from( mmmodule ) - - v.header_top.add( "#ifndef {friendly_null_getter}\n" ) - v.header_top.add( "#define {friendly_null_getter} {local_null_getter}\n" ) - v.header_top.add( "#endif\n" ) - - v.header_top.add( "{name} {local_null_getter}();\n" ) - - var fc = new FunctionCompiler( "{name} {local_null_getter}()" ) - compile_new_local_ref( "n", fc, true ) - fc.exprs.add( "return n;\n" ) - v.body.append( fc.to_writer ) - end - - # reference incr - var incr_name = "{as_notnull.mangled_name}_incr_ref" - v.header_top.add( "#define {incr_name}( x ) nitni_global_ref_incr( (struct nitni_ref*)(x) )\n" ) - - # reference decr - var decr_name = "{as_notnull.mangled_name}_decr_ref" - v.header_top.add( "#define {decr_name}( x ) nitni_global_ref_decr( (struct nitni_ref*)(x) )\n" ) - - v.header_top.add( "#endif\n" ) - end - end - - fun compile_new_local_ref( var_name : String, fc : FunctionCompiler, stack_it : Bool ) - do - var type_name = friendly_extern_name - - fc.decls.add( "{type_name} {var_name};\n" ) - if uses_nitni_ref then - fc.exprs.add( "{var_name} = malloc( sizeof( struct s_{type_name} ) );\n" ) - fc.exprs.add( "{var_name}->ref.val = NIT_NULL;\n" ) - fc.exprs.add( "{var_name}->ref.count = 0;\n" ) - if stack_it then - fc.exprs.add( "nitni_local_ref_add( (struct nitni_ref *){var_name} );\n" ) - end - end - end - - # compiles a stub local reference for unused references - # allows to maintain static typing but avoids malloc and free - fun compile_stub_local_ref( var_name : String, fc : FunctionCompiler ) - do - var type_name = friendly_extern_name - fc.decls.add( "{type_name} {var_name};\n" ) - if uses_nitni_ref then - fc.exprs.add( "{var_name} = ({type_name})NULL;\n" ) - end - end -end - -redef class MMExplicitImport - fun compile_friendly_to_frontier( v : FrontierVisitor ) - do - # prototype in header - v.header.add( "/* friendly for {method.full_name} */\n" ) - v.header.add( "{method.frontier_csignature_from( v.mmmodule, local_class )};\n" ) - - # Defines a simplier name to be used within this module and to prevent - # conflict with other modules importing the same friendly. - v.header.add( "#ifndef {method.friendly_extern_name( local_class )}\n" ) - v.header.add( "#define {method.friendly_extern_name( local_class )} {method.local_friendly_name_from( v.mmmodule, local_class )}\n" ) - v.header.add( "#endif\n" ) - - # implementation in body - v.body.add( "/* friendly for {method.full_name} */\n" ) - - var fc = new FunctionCompiler( method.frontier_csignature_from( v.mmmodule, local_class ) ) - - # params - var params = new Array[NiVariable] - if not method.is_init then params.add( signature.recv_ni_variable ) - params.add_all( signature.params ) - - for nv in params do nv.prepare_for_nit( fc ) - - # handles return of method or constructor - var rnv = signature.return_ni_variable - if rnv == null and method.is_init then - rnv = new ReturnVariable( signature.recv ) - end - var s = new Buffer - if rnv != null then - rnv.prepare_for_c( fc ) - s.append( "{rnv.ni_from_name} = " ) - end - - # hook to generated C code - if method.is_init then - s.append( "NEW_{local_class}_{method.global.intro.cname}" ) - else - s.append( "{method.global.meth_call}( {signature.recv_ni_variable.as_arg_to_nit} )" ) - end - - var args = new Array[String] - for p in params do args.add( p.as_arg_to_nit ) - - s.append( "( {args.join( ", " )} );\n" ) - - fc.exprs.add( s.to_s ) - - # return - if rnv != null then - fc.exprs.add( "{rnv.ni_type.assign_to_friendly( rnv.ni_to_name, rnv.ni_from_name )};\n" ) - fc.exprs.add( "return {rnv.ni_to_name};\n" ) - end - - v.body.append( fc.to_writer ) - end - - redef fun hash - do - return method.global.to_s.hash + local_class.to_s.hash - end - redef fun == ( other ) - do - return other isa MMExplicitImport and - method == other.method and local_class == other.local_class - end -end diff --git a/src/native_interface/native_interface.nit b/src/native_interface/native_interface.nit deleted file mode 100644 index 80a0fd0..0000000 --- a/src/native_interface/native_interface.nit +++ /dev/null @@ -1,36 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# Copyright 2011 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. - -# Hooks in the compiler to add generation of frontier files -module native_interface - -import frontier -import compiling - -redef class MMSrcModule - redef fun compile_separate_module(cprogram: CProgram) - do - if is_extern_hybrid then - var visitor = new FrontierVisitor( self, cprogram ) - compile_frontier( visitor ) - - var base_path = "{cprogram.compdir}/{name}" - visitor.write_to_files( base_path ) - end - - super - end -end diff --git a/src/native_interface/ni_metamodel.nit b/src/native_interface/ni_metamodel.nit deleted file mode 100644 index 08df52b..0000000 --- a/src/native_interface/ni_metamodel.nit +++ /dev/null @@ -1,299 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# Copyright 2011 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. - -# Information relevant to the native interface -module ni_metamodel - -import compiling -import primitive_info -import utils - -redef class MMType - - # Friendly name used by frontier and custom code. - # It's mainly the nit class name or the primitive type when available. - fun friendly_extern_name: String - do - var pi = local_class.primitive_info - if is_nullable then - return "nullable_{local_class.name.to_s}" - else if pi == null then - return local_class.name.to_s - else - return pi.cname - end - end - - fun mangled_name: String - do - var pi = local_class.primitive_info - if is_nullable then - return "nullable_{local_class.name.to_s}" - else - return local_class.name.to_s - end - end - - # Return the expression to convert this type from its native version. - fun from_native( name : String ) : String - do - if ( local_class.primitive_info != null or local_class.global.is_extern ) and - not is_nullable then - return boxtype( name ) - else - var getter = "{name}->ref.val" - - return boxtype( getter ) - end - end - - # Return the expression to convert and assign this type to its - # friendly/native version. - fun assign_to_friendly( native_name, nit_name : String ) : String - do - if ( local_class.primitive_info != null or local_class.global.is_extern ) and - not is_nullable then - return "{native_name} = {unboxtype( nit_name )}" - else - return "{native_name}->ref.val = {unboxtype( nit_name )}" - end - end - - # Return the expression to convert and assign this type to its - # generated C version, from friendly/native. - fun assign_from_friendly( nit_name, native_name : String ) : String - do - if ( local_class.primitive_info != null or local_class.global.is_extern ) and - not is_nullable then # int, float, point/void* ... - return "{nit_name} = {boxtype(native_name)}" - else - return "{nit_name} = {native_name}->ref.val" - end - end - - fun uses_nitni_ref : Bool do return local_class.primitive_info == null or is_nullable - - fun friendly_null_getter : String - do - return "null_{as_notnull.mangled_name}" - end - - fun local_friendly_null_getter_from( m : MMModule ) : String - do - return "{m.to_s}_{friendly_null_getter}" - end -end - -redef class MMMethod - # Local friendly name from a given module. - # Used to avoid conflits between modules. - fun local_friendly_name_from( m : MMModule, local_class : MMLocalClass ) : String - do - return "{m.to_s}_{friendly_extern_name(local_class)}" - end - - fun friendly_super_cname : String - do - return "{friendly_extern_name(local_class)}___super" - end - - fun local_friendly_super_name_from( m : MMModule ) : String - do - return "{m.to_s}_{friendly_super_cname}" - end - - private fun friendly_cparams( local_class : MMLocalClass ) : List[ String ] - do - var params = new List[String] - - if not global.is_init then - params.add( "{local_class.get_type.friendly_extern_name} recv" ) - end - - for p in signature.params do - params.add( "{p.mmtype.friendly_extern_name} {p.name}" ) - end - - return params - end - - private fun csignature_with_suffix( suffix : String, local_class : MMLocalClass ) : String - do - var name = "{friendly_extern_name(local_class)}{suffix}" - - return csignature_with_name( name, local_class ) - end - - private fun csignature_with_name( name : nullable String, local_class : MMLocalClass ) : String - do - var s = new Buffer - - # return type - if signature.return_type != null then - s.append( "{signature.return_type.friendly_extern_name} " ) - else if global.is_init then - s.append( "{local_class.get_type.friendly_extern_name} " ) - else - s.append( "void " ) - end - - # function name - if name == null then - s.append( friendly_extern_name( local_class ) ) - else - s.append( name ) - end - - # params - var params = friendly_cparams( local_class ) - - s.append( "( {params.join( ", " )} )" ) - - return s.to_s - end - - fun friendly_csignature( local_class : MMLocalClass ) : String - do - return csignature_with_name( null, local_class ) - end - - fun frontier_csignature_from( m : MMModule, local_class : MMLocalClass ) : String - do - return csignature_with_name( local_friendly_name_from(m, local_class), local_class ) - end - - fun friendly_super_csignature : String - do - return csignature_with_suffix( "___super", local_class ) - end - - fun frontier_super_csignature_from( m : MMModule ) : String - do - return csignature_with_name( local_friendly_super_name_from(m), local_class ) - end - - fun impl_csignature : String - do - return csignature_with_suffix( "___impl", local_class ) - end - - # below is for frontier only - private fun cparams : List[ String ] - do - var params = new List[String] - if not global.is_init then params.add( "val_t recv" ) - for p in signature.params do params.add( "val_t {p.name}" ) - return params - end - - fun out_csignature : String - do # boxed types - var s = new Buffer - - # return type - if signature.return_type != null or global.is_init then - s.append( "val_t " ) - else - s.append( "void " ) - end - - # function name - if global.is_init then - s.append( "NEW_{local_class}_{cname}" ) - else - s.append( "{friendly_extern_name(local_class)}___out" ) - end - - # params - s.append( "( {cparams.join( ", " )} )" ) - - return s.to_s - end -end - -redef class MMImportedCast - - var in_name : String = "value" - - fun as_friendly_extern_name : String do - if is_about_nullable_only then - if is_not_null_to_nullable then # to null - # nullable_Object Object_as_nullable( Object o ) - return "{from.mangled_name}_as_nullable" - else if is_nullable_to_not_null then # from null - # Object Object_as_not_null( nullable_Object o ) - return "{to.mangled_name}_as_not_null" - else - abort - end - else # inter types - # String Object_as_String( Object o ) - return "{from.mangled_name}_as_{to.mangled_name}" - end - end - - fun as_local_cname( m : MMModule ) : String do - return "{m.to_s}_{as_friendly_extern_name}" - end - - fun as_local_csignature( m : MMModule ) : String - do - return "{to.friendly_extern_name} {as_local_cname( m )}( {from.friendly_extern_name} {in_name} )" - end - - fun as_friendly_csignature : String - do - return "{to.friendly_extern_name} {as_friendly_extern_name}( {from.friendly_extern_name} {in_name} )" - end - - fun is_a_friendly_extern_name : String do - if is_about_nullable_only then - if is_not_null_to_nullable then # to null - abort # would always be true - else if is_nullable_to_not_null then # from null - # Object_is_null( nullable_Object o ) - # is opposite from others - return "{to.mangled_name}_is_null" - else - abort - end - else # inter types - # Object_is_a_String( Object o ) - return "{from.mangled_name}_is_a_{to.mangled_name}" - end - end - - fun is_a_local_cname( m : MMModule ) : String do - return "{m.to_s}_{is_a_friendly_extern_name}" - end - - # Signature of function to check if an object of the "from" type is of - # the "to" type. - fun is_a_local_csignature( m : MMModule ) : String - do - return "int {is_a_local_cname( m )}( {from.friendly_extern_name} {in_name} )" - end - - fun is_a_friendly_csignature : String - do - return "int {is_a_friendly_extern_name}( {from.friendly_extern_name} {in_name} )" - end - - redef fun hash - do - return from.hash+to.hash - end -end diff --git a/src/native_interface/ni_tools.nit b/src/native_interface/ni_tools.nit deleted file mode 100644 index cba01ca..0000000 --- a/src/native_interface/ni_tools.nit +++ /dev/null @@ -1,41 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# Copyright 2011 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. - -# Compiling tools used by the native interface -module ni_tools - -import compiling - -class FunctionCompiler - var signature : String - - var decls : Writer = new Writer - var exprs : Writer = new Writer - - fun to_writer : Writer - do - var w = new Writer - - w.add( "{signature}\n\{\n" ) - - w.append( decls ) - w.append( exprs ) - - w.add( "\}\n" ) - - return w - end -end