From ae057fecec6d2575497cce71b6c3a369794fa7b1 Mon Sep 17 00:00:00 2001 From: Pavel Shevaev Date: Thu, 14 Nov 2024 20:23:30 +0300 Subject: [PATCH] Migrating to IList instead of HList for arguments as it is more versatile; Adding codegen for disposal of arguments --- src/bind.inc.php | 2 +- tpl/bhl_bind_macro.twig | 133 ++++++++++++++++++++++++++++------------ 2 files changed, 95 insertions(+), 40 deletions(-) diff --git a/src/bind.inc.php b/src/bind.inc.php index 518ec8d..0b165fc 100644 --- a/src/bind.inc.php +++ b/src/bind.inc.php @@ -511,7 +511,7 @@ function native_type(\mtgType $type) if($type->getValue()->getName() == "any") return "bhl.ValList"; else - return "HList<".native_type($type->getValue()).">"; + return "IList<".native_type($type->getValue()).">"; } //func special case diff --git a/tpl/bhl_bind_macro.twig b/tpl/bhl_bind_macro.twig index 2e8e392..59c10eb 100644 --- a/tpl/bhl_bind_macro.twig +++ b/tpl/bhl_bind_macro.twig @@ -39,13 +39,15 @@ {# pass back and release ref args #} {%- for arg in o.args -%} {%- if has_token(arg, 'bhl_ref_arg') ~%} - {{ _self.native2val(arg.type, '__ref_' ~ arg.name, '__' ~ arg.name) }}; + {{ _self.native2val(arg.type, '__ref_' ~ arg.name, '__' ~ arg.name, true) }}; __{{arg.name}}.Release(); {%- endif -%} {%- endfor -%} {{ _self.return_val(o, 'return_val') }} + {{ _self.dispose_args(o, '__') }} + return null; } #else @@ -75,6 +77,7 @@ {%- if o.args -%} var args = Script_{{o.name|norm_name}}.ReadArgs(frm, stack, args_info); Script_{{o.name|norm_name}}.Exec(frm, args {{_self.out_results(o)}}); + args.Dispose(); {%- else ~%} Script_{{o.name|norm_name}}.Exec(frm {{_self.out_results(o)}}); {%- endif ~%} @@ -232,6 +235,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack public override void Cleanup(VM.Frame frm, bhl.VM.ExecState exec) { Cleanup(frm); {% if o.args or this_type ~%} + args.Dispose(); args = default; {% endif %} } @@ -239,7 +243,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endmacro -%} {%- macro Args(o, this_type) ~%} - public struct Args { + public struct Args : IDisposable { {% if this_type and not has_token(o, 'bhl_static') ~%} public {{this_type|native_type}} self; {% endif %} @@ -248,19 +252,17 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack public {% if has_token(arg, 'bhl_ref_arg') %} bhl.Val {% else %} {{arg.type|native_type}} {% endif %} {{arg.name}}; {% endfor %} + + public void Dispose() + { + {{ _self.dispose_args(o) }} + } } {%- endmacro -%} {%- macro Args_ReadArgs(o, this_type) -%} static public Args ReadArgs(VM.Frame frm, ValStack stack, FuncArgsInfo args_info) { var args = new Args(); - {#any array special handling#} - {% for arg in o.args %} - {% if arg.type is instanceof('\\mtgArrType') and arg.type.value.name == 'any' %} - args.{{arg.name}} = ValList.New(frm.vm); - {% endif %} - {% endfor %} - {{ _self.read_args2natives(o, 'args.', this_type, false) }} return args; } @@ -292,7 +294,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {% endif %} {%- endmacro -%} -{%- macro local_native_vars(vars, prefix, this_type) -%} +{%- macro local_native_arg_vars(vars, prefix, this_type) -%} {%- if this_type ~%} {{this_type|native_type}} {{prefix}}self = default; {%- endif -%} @@ -302,7 +304,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack bhl.Val {{prefix}}{{v.name}} = default; {{v.type|native_type}} {{prefix}}ref_{{v.name}} = default; {%- else -%} - {{v.type|native_type}} {{prefix}}{{v.name}} = default; + {{v.type|native_type(true)}} {{prefix}}{{v.name}} = default; {%- endif -%} {%- endfor ~%} {%- endmacro -%} @@ -310,7 +312,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- macro read_args2natives(o, arg_prefix, this_type = null, declare_locals = true) -%} {%- if declare_locals -%} - {{ _self.local_native_vars(o.args, arg_prefix, this_type) }} + {{ _self.local_native_arg_vars(o.args, arg_prefix, this_type) }} {%- endif -%} {# traversing args in reverse order #} @@ -331,11 +333,11 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack var dv = stack.Pop(); {{arg_prefix}}{{arg.name}} = dv; {%- if not has_token(arg.type, 'bhl_custom_rw') -%} - {{ _self.val2native(arg.type, 'dv', arg_prefix ~ 'ref_' ~ arg.name) }}; + {{ _self.val2native(arg.type, 'dv', arg_prefix ~ 'ref_' ~ arg.name, true) }}; {%- endif ~%} {%- else ~%} var dv = stack.Pop(); - {{ _self.val2native(arg.type, 'dv', arg_prefix ~ arg.name) }}; + {{ _self.val2native(arg.type, 'dv', arg_prefix ~ arg.name, true) }}; dv.Release(); {%- endif ~%} } @@ -351,12 +353,38 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- if this_type and not has_token(o, 'bhl_static') ~%} { var dv = stack.Pop(); - {{ _self.val2native(this_type, 'dv', arg_prefix ~ 'self') }}; + {{ _self.val2native(this_type, 'dv', arg_prefix ~ 'self', true) }}; dv.Release(); } {%- endif ~%} {%- endmacro -%} +{%- macro dispose_args(o, arg_prefix = '') -%} + {%- for arg in o.args -%} + {% if arg.type is instanceof('\\mtgArrType') %} + {% if arg.type.value.name == 'any' %} + { + {{arg_prefix}}{{arg.name}}?.Release(); + {{arg_prefix}}{{arg.name}} = null; + } + {% else %} + { + if({{arg_prefix}}{{arg.name}} is IDisposable dsp) + { + dsp.Dispose(); + {{arg_prefix}}{{arg.name}} = default; + } + } + {% endif %} + {% endif %} + + {% if arg.type.name == 'any' %} + {{arg_prefix}}{{arg.name}}?.Release(); + {% endif %} + + {%- endfor ~%} +{%- endmacro -%} + {%- macro default_value(dst, value) -%} {{dst}} = {{value|replace({'%self%': dst})}} {%- endmacro -%} @@ -393,7 +421,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endfor -%} {%- endmacro -%} -{%- macro val2native(type, value, native) -%} +{%- macro val2native(type, value, native, is_arg = false) -%} {# any special case #} {%- if type == 'any' -%} {{native}} = {{value}} @@ -407,36 +435,58 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endif -%} {%- if type is instanceof('\\mtgArrType') -%} - var _src_arr_type = (ArrayTypeSymbol){{value}}.type; - int _dst_before_count = 0; - int _src_arr_count = _src_arr_type.ArrCount({{value}}); + + {%- if is_arg -%} {%~ if type == 'any[]'-%} - {{native}} = ValList.New(frm.vm); + + {{native}} = (ValList){{value}}._obj; + {{native}}.Retain(); + {%~ else ~%} - try + + if({{value}}._obj is ValList vl) { - _dst_before_count = {{native}}.Count; - } - catch(NullReferenceException) - { - {{native}} = new(); + vl.Retain(); + {{native}} = ValList<{{type.value|native_type}}>.New(vl, + ((NativeListTypeSymbol<{{type.value|native_type}}>)Types_List_{{type.value|norm_name}}.Value).Val2Native); } + else if({{value}}._obj != null) + {{native}} = (IList<{{type.value|native_type}}>){{value}}._obj; + else + throw new Exception("Null value"); + {%~ endif -%} + {%- else -%} - for(int i=0;i<_src_arr_count;++i) - { - var _arr_item = _src_arr_type.ArrGetAt({{value}}, i); - {#TODO: get rid of replace hack below#} - {{('var ' ~ _self.val2native(type.value, '_arr_item', 'tmp'))|replace({'tmp = tmp' : '', 'var var' : 'var'})}}; - if(i < _dst_before_count) - {{native}}[i] = tmp; - else - {{native}}.Add(tmp); - } - while({{native}}.Count > _src_arr_count) - {{native}}.RemoveAt({{native}}.Count-1); + var _src_arr_type = (ArrayTypeSymbol){{value}}.type; + int _dst_before_count = 0; + int _src_arr_count = _src_arr_type.ArrCount({{value}}); + + try + { + _dst_before_count = {{native}}.Count; + } + catch(NullReferenceException) + { + {{native}} = new(); + } + + for(int i=0;i<_src_arr_count;++i) + { + var _arr_item = _src_arr_type.ArrGetAt({{value}}, i); + {#TODO: get rid of replace hack below#} + {{('var ' ~ _self.val2native(type.value, '_arr_item', 'tmp'))|replace({'tmp = tmp' : '', 'var var' : 'var'})}}; + if(i < _dst_before_count) + {{native}}[i] = tmp; + else + {{native}}.Add(tmp); + } + while({{native}}.Count > _src_arr_count) + {{native}}.RemoveAt({{native}}.Count-1); + + {%- endif -%} {%- endif -%} {%- if type is instanceof('\\mtgBuiltinType') -%} @@ -476,7 +526,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endif -%} {%- endmacro -%} -{%- macro native2val(type, native, value) -%} +{%- macro native2val(type, native, value, is_arg = false) -%} {# any special case #} {%- if type == 'any' -%} {{value}}.SetObj({{native}}, Types.Any) @@ -490,7 +540,12 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endif -%} {%- if type is instanceof('\\mtgArrType') -%} + {%- if is_arg -%} + //TODO: get rid of this hack + {{value}}.Release();{{value}} = {{native}}.Val + {%- else -%} {{value}}.SetObj({{native}}, Types_List_{{type.value.name|norm_name}}.Value) + {%- endif -%} {%- endif -%} {%- if type is instanceof('\\mtgBuiltinType') -%}