import proxy.proxy; import ada.wrappers; import ada.transformations; ################################################################################ # w_TypeDeclProxy ################################################################################ template w_TypeDeclProxy extends w_TypeDecl do var type: text => (match origin (n: p_defining_name ()) pick n else pick ""); var type_access: text => type & "_Access"; var type_proxy: text => type & "_Proxy"; var type_proxy_access : text => type & "_Proxy_Access"; match origin () pick origin wrap null (w_TypeDecl); wrap wp_Class ( name => "\e" ); match origin (child (RecordTypeDef ())) do weave ( declaration => defer (i""" type \e is record Address : System.Address; Is_Proxy_Owned : Boolean; Is_Automatic : Boolean; end record; type \e is access all \e; type \e is access all \e; function Convert is new Ada.Unchecked_Conversion (System.Address, \e); """) ); then var proxy_type: object => it; pick parent (w_PackageDecl ()) do pick child (new ({ sb: w_SubpDeclCallProxy ( name => defer ("\e_Proxy_Allocate"), subp_kind => "function", memory_mode => "heap", is_proxy_owned => "True", call => defer ("\e'(new \e)") ) { w_TypeExprProxy (origin_type_decl => proxy_type.origin) }, sb: w_SubpDeclCallProxy ( name => defer ("\e_Proxy_Free"), subp_kind => "procedure", pre_call_decl => defer (@ & i""" procedure Free is new Ada.Unchecked_Deallocation (\e, \e); procedure Free is new Ada.Unchecked_Deallocation (\e, \e); """) ) { p: w_ParamSpecCallProxy ( name => "Proxy", memory_mode => "heap", call_stmt => defer (@ & i""" Free (\e); Free (\e); """)) { w_TypeExprProxy (origin_type_decl => proxy_type.origin) } } })); end; end; end; ################################################################################ # w_SubpDeclCallProxy ################################################################################ template w_SubpDeclCallProxy extends w_SubpDeclCall do var t1: text => origin.tmp ("t1"); var t2: text => origin.tmp ("t2"); var s: object => it (); var memory_mode: text => "stack"; var is_proxy_owned: text => defer ((match mode ("stack") pick "True" else pick "False")); wrap wp_Function ( name => (match origin (SubpDecl ()) pick origin.p_defining_name () else pick name), type => defer ((match subp_kind ("function") pick child (w_TypeExpr).wrapper (wp_TypeExpr).txt else pick "void")), symbol => defer (parent (w_Unit ()).tmp (name)) ); match origin (SubpDecl ()) do pick origin do wrap null (w_SubpDeclCall); match child (f_subp_kind ("function")) do pick s weave (subp_kind => "function"); else pick s weave (subp_kind => "procedure"); end; end; end; then pick child (new ({ w_Aspect ("Export => True"), w_Aspect ("Convention => C"), w_Aspect (defer ("""External_Name => "\e" """)) })); match subp_kind ("function") do defer ret: child (w_TypeExprProxy (type_computed (true))) match ret_proxy: ret.w_designated_type_decl () do match memory_mode ("stack") do weave ( result_type_expr => "System.Address", call_decl => defer ("""\e : aliased \e := \e;\n"""), call_stmt => "null;", return_stmt => defer ("""return \e.all'Address;"""), post_call_decl => defer (i""" \e : \e := new \e' (Is_Proxy_Owned => \e, Is_Automatic => False, Address => Allocate_Byte_Copy (\e'Address, \e'Size)); """)); else weave ( result_type_expr => "System.Address", call_decl => defer ("""\e : \e := \e (\e);\n"""), call_stmt => "null;", return_stmt => defer ("""return \e.all'Address;"""), post_call_decl => defer (i""" \e : \e := new \e' (Is_Proxy_Owned => \e, Is_Automatic => False, Address => Allocate_Byte_Copy (\e.all'Address, \e.all'Size)); """)); end; else weave ( result_type_expr => defer (ret.txt), call_decl => defer (@ & i""" \e : \e := \e (\e);"""), return_stmt => defer ("""return \e;""") ); end; end; end; ################################################################################ # w_ParamSpecCallProxy ################################################################################ template w_ParamSpecCallProxy extends w_ParamSpecCall do var retreived_val: text; var var_name: text => parent (w_SubpDecl ()).origin.tmp ("var"); var proxy_name: text => parent (w_SubpDecl()).origin.tmp ("proxy"); var memory_mode: text => "stack"; match origin () pick origin wrap null (w_ParamSpecCall); wrap wp_Parameter ( name => name, type => defer (child (w_TypeExpr).wrapper (wp_TypeExpr).txt)); defer ret: child (w_TypeExprProxy (type_computed (true))) match ret_proxy: ret.w_designated_type_decl () do match memory_mode ("stack") do weave ( type_expr => child (w_TypeExpr).txt, pre_call_decl => defer (@ & i""" \e : \e := Convert (\e); \e : \e with Address => \e.Address, Import; """), actual_value => defer (var_name)); else weave ( type_expr => child (w_TypeExpr).txt, pre_call_decl => defer (@ & i""" \e : \e := Convert (\e); \e : \e with Address => \e.Address'Address, Import; """), actual_value => defer (var_name)); end; else var original_type: text => (match ret.origin_type_expr (x".") pick ret.origin_type_expr else pick ret.origin_type_decl); weave ( type_expr => child (w_TypeExpr).txt, pre_call_decl => @ & defer (i""" \e : \e := \e (\e); """), actual_value => var_name); end; end; ################################################################################ # w_TypeExprProxy ################################################################################ template w_TypeExprProxy extends w_TypeExpr do # this value can come from: # - the original parameter itself # - another object from which the parameter is created (e.g. a field) # it can be coming either from a type expression or directly a type # declaration. var origin_type_expr: object; var origin_type_decl: object; var w_designated_type_decl : object; var type_computed: object => false; match origin pick origin wrap null (w_TypeExpr); end; # At the time w_TypeExprProxy is created, wp_TypeDecl may not be yet. Defer # the computation until the next cycle. match w_TypeExprProxy () do match o: origin_type_decl (w: wrapper (w_TypeDecl)) or o: origin_type_expr (p_designated_type_decl ().filter (w: wrapper (w_TypeDecl))) do weave (w_designated_type_decl => w, type_computed => true); else weave (type_computed => true); end; match origin_type_expr (p_designated_type_decl ().filter (f_type_def (SignedIntTypeDef ()))) do wrap wp_TypeExpr ("int32"); weave (txt => "Interfaces.C.int"); elsmatch o: origin_type_decl () or origin_type_expr (o: p_designated_type_decl ()) do wrap wp_TypeExpr (o.p_defining_name ()); weave ( txt => "System.Address"); else wrap wp_TypeExpr ("_anonymous_proxy_"); weave (txt => "System.Address"); end; end; ################################################################################ # generate_ada2proxy ################################################################################ template generate_ada2proxy pick origin do walk wrap_ada_specs (); match DefiningName (x"(.*)") wrap w_DefiningName ("Proxy_\1"); ######## # UNIT # ######## match d: w_PackageDecl () do pick p: parent (w_Unit ()) do wrap wp_Unit (name => d.origin.p_defining_name ()); pick p.child (new ({ w_WithClause ("Interfaces.C"), w_WithClause ("System"), w_WithClause ("Ada.Unchecked_Deallocation"), w_WithClause ("Ada.Unchecked_Conversion"), w_WithClause (d.origin.p_defining_name ()), w_UseClause (d.origin.p_defining_name ()) })); end; weave ( spec_content => @ & i""" function Allocate_Byte_Copy (Address : System.Address; Size : Integer) return System.Address; """, body_content => @ & i""" ------------------------ -- Allocate_Byte_Copy -- ------------------------ function Allocate_Byte_Copy (Address : System.Address; Size : Integer) return System.Address is type Byte_Array is array (Integer range 1 .. Size) of Boolean with Pack; type Byte_Array_Access is access all Byte_Array; Src : aliased Byte_Array with Address => Address; Dst : Byte_Array_Access := new Byte_Array'(Src); begin return Dst.all'Address; end Allocate_Byte_Copy; """ ); end; ############## # SUBPROGRAM # ############## match sb: SubpDecl () do wrap w: w_SubpDeclCallProxy (); then pick w weave build_subprogram (sb); end; ############# # PARAMETER # ############# match ParamSpec () wrap w_ParamSpecCallProxy (); ######## # TYPE # ######## match TypeDecl () wrap w_TypeDeclProxy (); match s: w_ComponentDecl () and parent (t: w_TypeDecl ()) and child (te: w_TypeExpr ()) do pick t.child (new ({ w: w_SubpDeclCallProxy ( name => defer ("Get_" & s.name), subp_kind => "function", call => defer ("\e.\e") #result_type_expr => te.txt, #return_stmt => defer (i""" # return \e.\e; # """) ) { w_TypeExprProxy (origin_type_expr => te.origin), w_ParamSpecCallProxy (name => "Proxy") { w_TypeExprProxy (origin_type_decl => t.origin) } }, w_SubpDeclCallProxy ( name => "Set_" & s.name, subp_kind => "procedure", result_type_expr => te.origin, call_stmt => defer (@ & i""" \e.\e := \e (Val); """) ) { w_ParamSpecCallProxy (name => "Proxy") { w_TypeExprProxy (origin_type_decl => t.origin) }, w_ParamSpecCallProxy (name => "Val") { w_TypeExprProxy (origin_type_expr => te.origin) } } })); end; ############# # TYPE_EXPR # ############# match TypeExpr () wrap w_TypeExprProxy (origin_type_expr => it); end;