+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2011 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.
-
-# 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 <nit_common.h>\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
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2011 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.
-
-# 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