From 4af69254e4f73321929b07a91a44f971dfd618ea Mon Sep 17 00:00:00 2001 From: Pavel Shevaev Date: Tue, 13 Dec 2022 19:29:25 +0300 Subject: [PATCH] Starting to experiment with native array proxies --- src/bind.inc.php | 28 +++++++++++++- tpl/macro.twig | 96 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 97 insertions(+), 27 deletions(-) diff --git a/src/bind.inc.php b/src/bind.inc.php index 76729dd..c51c10e 100644 --- a/src/bind.inc.php +++ b/src/bind.inc.php @@ -45,6 +45,8 @@ function supported_tokens() function bhl_add_twig_support(\Twig\Environment $twig) { + $twig->addGlobal('native_array_types', array()); + $twig->addTest(new \Twig\TwigTest('instanceof', function($obj, $class) { @@ -81,6 +83,22 @@ function bhl_add_twig_support(\Twig\Environment $twig) return bhl_gen_native_type($type); } )); + $twig->addFilter(new \Twig\TwigFilter('native_arr_type', + function($type) use($twig) + { + if($type instanceof \mtgArrType) + { + //let's remember all native array proxies + $types = $twig->getGlobals()['native_array_types']; + $proxy_name = "List_{$type->getValue()->getName()}"; + $types[$proxy_name] = $type; + $twig->addGlobal('native_array_types', $types); + return $proxy_name; + } + else + return $type; + } + )); $twig->addFilter(new \Twig\TwigFilter('norm_name', function($name) { @@ -171,6 +189,12 @@ function bhl_add_twig_support(\Twig\Environment $twig) return $arr; } )); + $twig->addFunction(new \Twig\TwigFunction('get_native_arr_types', + function() use($twig) + { + return array_values($twig->getGlobals()['native_array_types']); + } + )); } function bhl_get_last_name($name) @@ -199,7 +223,7 @@ function bhl_get_ns_prefix($name) function bhl_type_ref($type_str) { - if(preg_match('~((\w|\.)+)\[\]~', $type_str, $ms)) + if(preg_match('~\[\]((\w|\.)+)~', $type_str, $ms)) return "types.TArr(\"{$ms[1]}\")"; else if(preg_match('~async\s+func\s+((\w|\.)+)\s*\(\)~', $type_str, $ms)) return "types.TFunc(true, \"{$ms[1]}\")"; @@ -245,7 +269,7 @@ function bhl_gen_type(\mtgType $type = null) return rtrim($str, ","); } else if($type instanceof \mtgArrType) - return bhl_gen_type($type->getValue()) . "[]"; + return "[]" . bhl_gen_type($type->getValue()); return ''.$type; } diff --git a/tpl/macro.twig b/tpl/macro.twig index 16a869a..9405050 100644 --- a/tpl/macro.twig +++ b/tpl/macro.twig @@ -1,4 +1,4 @@ -{%- macro func_native(o, scope = 'types.ns', this_prefix = '') ~%} +{%- macro reg_func_native(o, scope = 'types.ns', this_prefix = '') ~%} { var fn = new FuncSymbolNative("{{o.name|ns_last}}", @@ -44,7 +44,7 @@ } {%- endmacro -%} -{%- macro func_partial(o, scope = 'types.ns') ~%} +{%- macro reg_func_partial(o, scope = 'types.ns') ~%} { var fn = new FuncSymbolNative("{{o.name|ns_last}}", {%- if has_token(o, 'bhl_coroutine') -%} @@ -107,7 +107,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endif -%} {%- endmacro -%} -{%- macro func_partial_class(o, prefix, this_type = null) ~%} +{%- macro decl_func_partial_class(o, prefix, this_type = null) ~%} public partial class {{prefix}}{{o.name|norm_name}} {% if has_token(o, 'bhl_coroutine') %}: bhl.ICoroutine {% endif %} { @@ -495,7 +495,48 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endif -%} {%- endmacro -%} -{%- macro enum(o, scope = 'types.ns') ~%} +{%- macro reg_native_arr_type(o, scope = 'types.ns') ~%} + { + var cl = new ClassSymbolNative("List_{{o.value.name}}", + //constructor is not allowed + null + ); + { + var vs = new FieldSymbol("Count", Types.Int, + delegate(VM.Frame frame, Val ctx, ref Val v, FieldSymbol fld) + { +#if !BHL_FRONT + v.SetNum((ctx.obj as IList).Count); +#endif + }, + null); + cl.Define(vs); + } + { + var fn = new FuncSymbolNative("At", types.T("{{o.value.name}}"), + delegate(VM.Frame frame, ValStack stack, FuncArgsInfo args_info, ref BHS status) + { +#if !BHL_FRONT + var val_idx = stack.Pop(); + var val_lst = stack.Pop(); + + stack.Push(Val.NewObj(frm.vm, ((List<{{o.value.name}}>)val_lst.obj)[(int)val_idx._num], BHL_Types.Type_{{o.value.name}})); + + val_idx.Release(); + val_lst.Release(); +#endif + return null; + }, + new FuncArgSymbol("idx", Types.Int) + ); + cl.Define(fn); + } + cl.Setup(); + {{scope}}.Define(cl); + } +{%- endmacro -%} + +{%- macro reg_enum(o, scope = 'types.ns') ~%} { var en = new EnumSymbol("{{o.name|ns_last}}"); @@ -512,7 +553,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endmacro -%} -{%- macro class(o, scope = 'types.ns') ~%} +{%- macro reg_class(o, scope = 'types.ns') ~%} {# ignore special case any #} {% if o.name == 'any' %} @@ -555,7 +596,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {% for m in o.getfuncs %} {% if has_token(m, 'bhl_native_prefix') %} - {{ _self.func_native(m, 'cl', '(('~token_or(o, 'bhl_native_class', o.name)~')stack.Pop()._obj).') }} + {{ _self.reg_func_native(m, 'cl', '(('~token_or(o, 'bhl_native_class', o.name)~')stack.Pop()._obj).') }} {% else %} {{ _self.method_partial(o, m, 'cl') }} {% endif %} @@ -570,7 +611,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {% set class = token_or(o, 'bhl_native_class', o.name) %} { - cl.Define(new FieldSymbol("{{f.name}}", {{f.type|bhl_type_ref}}, + cl.Define(new FieldSymbol("{{f.name}}", {{f.type|native_arr_type|bhl_type_ref}}, {% if token_or(f, 'bhl_get', 1) != 0 ~%} //getter delegate(VM.Frame frm, Val ctx, ref Val v, FieldSymbol fld) { @@ -630,7 +671,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endmacro -%} -{%- macro interface(o, scope = 'types.ns') ~%} +{%- macro reg_interface(o, scope = 'types.ns') ~%} { var ifs = new InterfaceSymbolNative("{{o.name|ns_last}}", null @@ -646,7 +687,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endmacro -%} -{%- macro ecs_component(o) ~%} +{%- macro reg_ecs_component(o) ~%} { var fn = new FuncSymbolNative("{{o.name}}_Ensure", Types.Void, #if !BHL_FRONT @@ -901,7 +942,7 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- for u in units -%} {%- if u.object is instanceof('\\mtgMetaFunc') -%} {%- if not has_token(u.object, 'bhl_native_prefix') -%} - {{ _self.func_partial_class(u.object, 'Script_') }} + {{ _self.decl_func_partial_class(u.object, 'Script_') }} {%- endif -%} {%- endif -%} @@ -914,7 +955,7 @@ public partial class Script_{{u.object.name}} { {% for m in u.object.getfuncs %} {%- if not has_token(m, 'bhl_native_prefix') ~%} - {{ _self.func_partial_class(m, 'Method_', u.object) }} + {{ _self.decl_func_partial_class(m, 'Method_', u.object) }} {%- endif -%} {% endfor %} @@ -936,26 +977,26 @@ public partial class Script_{{u.object.name}} { {%- if u.object is instanceof('\\mtgMetaFunc') -%} {%- if has_token(u.object, 'bhl_native_prefix') -%} - {{ _self.func_native(u.object) }} + {{ _self.reg_func_native(u.object) }} {%- else -%} - {{ _self.func_partial(u.object) }} + {{ _self.reg_func_partial(u.object) }} {%- endif -%} {%- elseif u.object is instanceof('\\mtgMetaStruct') -%} {%- if has_token(u.object, 'bhl_ecs_component') -%} - {{ _self.ecs_component(u.object) }} + {{ _self.reg_ecs_component(u.object) }} {%- else -%} - {{ _self.class(u.object) }} + {{ _self.reg_class(u.object) }} {%- endif -%} {%- elseif u.object is instanceof('\\mtgMetaInterface') -%} - {{ _self.interface(u.object) }} + {{ _self.reg_interface(u.object) }} {%- elseif u.object is instanceof('\\mtgMetaEnum') -%} - {{ _self.enum(u.object) }} + {{ _self.reg_enum(u.object) }} {%- else -%} {{Error('Not supported type: ' ~ u.object)}} @@ -963,17 +1004,22 @@ public partial class Script_{{u.object.name}} { {%- endfor -%} + {%- for type in get_native_arr_types() -%} + {{ _self.reg_native_arr_type(type) }} + {%- endfor ~%} + + //assign global static types {%- for u in units -%} {%- if u.object is instanceof('\\mtgMetaStruct') ~%} {%- if not has_token(u.object, 'bhl_ecs_component') ~%} - { - var tmp = types.T("{{u.object.name}}").Get(); - if(tmp == null) - throw new System.Exception("Type '{{u.object.name}}' not resolved"); - if(tmp is ClassSymbol cs) - cs.Setup(); - BHL_Types.Type_{{u.object.name|norm_name}} = tmp; - } + { + var tmp = types.T("{{u.object.name}}").Get(); + if(tmp == null) + throw new System.Exception("Type '{{u.object.name}}' not resolved"); + if(tmp is ClassSymbol cs) + cs.Setup(); + BHL_Types.Type_{{u.object.name|norm_name}} = tmp; + } {%~ endif ~%} {%- endif -%}