+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
+ 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
+