diff --git a/composer.json b/composer.json index 4aa1d05..a044ada 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,8 @@ }, "autoload": { "files": [ - "src/bind.inc.php" + "src/bind.inc.php", + "src/plugin.inc.php" ] } } diff --git a/src/bind.inc.php b/src/bind.inc.php index e1166c3..7e657ba 100644 --- a/src/bind.inc.php +++ b/src/bind.inc.php @@ -2,6 +2,55 @@ namespace bhl_bind; use Exception; +require_once(__DIR__ . '/plugin.inc.php'); + +function supported_tokens() +{ + return [ + 'POD', + 'default', + 'bhl_bind', + 'bhl_no_new', + 'bhl_coroutine', + 'bhl_static', + 'bhl_native_class', + 'bhl_native_class_params', + 'bhl_native_prefix', + 'bhl_custom_rw', + 'bhl_get', + 'bhl_set', + 'bhl_ref_arg', + 'bhl_bin_op' + ]; +} + +function codegen( + $tpl_cache_dir, + \mtgMetaInfo $meta, + array $options = array() +) +{ + $twig = get_twig(); + if($tpl_cache_dir) + $twig->setCache($tpl_cache_dir); + + $options['meta'] = $meta; + if(!isset($options['imports'])) + $options['imports'] = array(); + if(!isset($options['register_class'])) + $options['register_class'] = 'BHL_AutoBindings'; + + if(isset($options['plugins'])) + { + foreach($options['plugins'] as $plugin) + $plugin->init($meta, $twig); + + $twig->addGlobal('plugins', $options['plugins']); + } + + return $twig->render('codegen_autobind.twig', $options); +} + function get_twig(array $inc_path = []) { array_unshift($inc_path, __DIR__ . "/../tpl/"); @@ -19,29 +68,6 @@ function get_twig(array $inc_path = []) return $twig; } -function supported_tokens() -{ - return [ - 'POD', - 'default', - 'bhl_bind', - 'bhl_no_new', - 'bhl_ecs_component', - 'bhl_ecslite_component', - 'bhl_ecs_component_ref', - 'bhl_coroutine', - 'bhl_static', - 'bhl_native_class', - 'bhl_native_class_params', - 'bhl_native_prefix', - 'bhl_custom_rw', - 'bhl_get', - 'bhl_set', - 'bhl_ref_arg', - 'bhl_bin_op' - ]; -} - function prepare_meta(\mtgMetaInfo $orig) { //NOTE: making a deep clone @@ -50,7 +76,7 @@ function prepare_meta(\mtgMetaInfo $orig) $arr_proxies = array(); foreach($meta->getUnits() as $u) { - if($u->object instanceof \mtgMetaStruct && !$u->object->hasToken('bhl_ecs_component') && !$u->object->hasToken('bhl_ecslite_component')) + if($u->object instanceof \mtgMetaStruct) { $need_to_replace = false; $fields = $u->object->getFields(); @@ -91,8 +117,41 @@ function prepare_meta(\mtgMetaInfo $orig) return $meta; } +function find_struct_plugin(array $plugins, $unit) +{ + foreach($plugins as $plugin) + { + if($plugin instanceof BindStructOverridePlugin && + $plugin->supports($unit)) + return $plugin; + } + return null; +} + function add_twig_support(\Twig\Environment $twig) { + $twig->addFunction(new \Twig\TwigFunction('plugins_codegen_decls', + function() use ($twig) + { + $globals = $twig->getGlobals(); + $plugins = $globals['plugins']; + $code = ''; + foreach($plugins as $p) + $code .= $p->codegenDecls($twig); + return $code; + } + )); + $twig->addFunction(new \Twig\TwigFunction('plugins_codegen_register', + function() use ($twig) + { + $globals = $twig->getGlobals(); + $plugins = $globals['plugins']; + $code = ''; + foreach($plugins as $p) + $code .= $p->codegenRegister($twig); + return $code; + } + )); $twig->addTest(new \Twig\TwigTest('instanceof', function($obj, $class) { diff --git a/src/plugin.inc.php b/src/plugin.inc.php new file mode 100644 index 0000000..9aa17d6 --- /dev/null +++ b/src/plugin.inc.php @@ -0,0 +1,10 @@ +(); - - return null; - } - #else - null - #endif - , - new FuncArgSymbol("__self", types.T("ecs.Entity")) - ); - types.ns.Define(fn); - } - - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Del", Types.Void, - #if !BHL_FRONT - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - EcsEntity e = default; - stack.PopRelease().Decode(ref e); - - e.Del(); - - return null; - } - #else - null - #endif - , - new FuncArgSymbol("__self", types.T("ecs.Entity")) - ); - types.ns.Define(fn); - } - - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Exists", Types.Bool, - #if !BHL_FRONT - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - EcsEntity e = default; - stack.PopRelease().Decode(ref e); - - var dv = bhl.Val.New(frm.vm); - dv.SetBool(e.Has()); - stack.Push(dv); - - return null; - } - #else - null - #endif - , - new FuncArgSymbol("__self", types.T("ecs.Entity")) - ); - types.ns.Define(fn); - } - - {% for f in o.getfields %} - {{ _self.ecs_component_field(o, f) }} - {% endfor %} - - {% for m in o.getfuncs %} - {{ _self.ecs_component_func(o, m) }} - {% endfor %} - - {% if has_token(o, 'bhl_ecs_component_ref') %} - { - var cl = new ClassSymbolNative(new Origin(), "{{o.name}}__Ref"); - types.ns.Define(cl); - {% for f in o.getfields %} - {{ _self.ecs_component_field_ref(o, f) }} - {% endfor %} - cl.Setup(); - - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Ref", {{(o.name ~ '__Ref') | bhl_type_ref}}, - #if !BHL_FRONT - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - EcsEntity e = default; - var ev = stack.Pop(); - ev.Decode(ref e); - ev.Release(); - - ref var cmp = ref e.Ensure(); - var dv = bhl.Val.New(frm.vm); - dv._obj = e.GetInternalWorld(); - dv._num = e.GetInternalId(); - dv._num2 = e.GetInternalGen(); - dv.type = cl; - stack.Push(dv); - - return null; - } - #else - null - #endif - , - new FuncArgSymbol("__self", types.T("ecs.Entity")) - ); - types.ns.Define(fn); - } - } - - {% endif %} - -{%- endmacro -%} - -{%- macro ecs_component_field(o, f) ~%} - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_{{f.name}}", {{f.type|bhl_type_ref}}, - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - 1, - {%- endif ~%} - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - #if !BHL_FRONT - Val dv = null; - - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - if(args_info.CountArgs() > 1) - dv = stack.Pop(); - {%- endif ~%} - - EcsEntity e = default; - stack.PopRelease().Decode(ref e); - ref var cmp = ref e.Ensure(); - var v = cmp.{{f.name}}; - - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - if(dv != null) { - {{ _self.val2native(f.type, 'dv', 'v') }}; - cmp.{{f.name}} = v; - dv.Release(); - } - {%- endif ~%} - - dv = Val.New(frm.vm); - { - {{ _self.native2val(f.type, 'v', 'dv') }}; - } - stack.Push(dv); - #endif - return null; - }, - new FuncArgSymbol("e", types.T("ecs.Entity")) - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - , new FuncArgSymbol("v", {{f.type|bhl_type_ref}}) - {%- endif ~%} - ); - types.ns.Define(fn); - } -{%- endmacro -%} - -{%- macro ecs_component_func(o, m) ~%} - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_{{m.name}}", - {{m.returntype|bhl_type_ref}}, - {{ count_default_args(m) }}, - #if !BHL_FRONT - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - EcsEntity e = default; - - {{ _self.read_args2natives(m, '__') }} - - stack.PopRelease().Decode(ref e); - ref var cmp = ref e.Ensure(); - - {%~ if m.returntype %} - var return_val = - {%- endif ~%} - - cmp.{{m.name}}( - {%- for arg in m.args ~%} __{{arg.name}}{% if not loop.last %},{% endif %} {%- endfor ~%} - ); - - {{ _self.return_val(m, 'return_val') }} - - return null; - } - #else - null - #endif - , new FuncArgSymbol("__self", types.T("ecs.Entity")) - {%- if m.args %},{% endif ~%} - {{ _self.func_decl_args(m) }} - ); - types.ns.Define(fn); - } -{%- endmacro -%} - -{%- macro reg_ecslite_component(o) ~%} - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Ensure", Types.Void, - #if !BHL_FRONT - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - EcsPackedEntityWithWorld e = default; - stack.PopRelease().Decode(ref e); - - if (e.Unpack(out EcsWorld world, out int id) == false) - return null; - - ref var cmp = ref world.GetPool<{{o.name}}>().Ensure(id); - - return null; - } - #else - null - #endif - , - new FuncArgSymbol("__self", types.T("ecs.Entity")) - ); - types.ns.Define(fn); - } - - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Del", Types.Void, - #if !BHL_FRONT - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - EcsPackedEntityWithWorld e = default; - stack.PopRelease().Decode(ref e); - - if (e.Unpack(out EcsWorld world, out int id) == false) - return null; - - world.GetPool<{{o.name}}>().Del(id); - - return null; - } - #else - null - #endif - , - new FuncArgSymbol("__self", types.T("ecs.Entity")) - ); - types.ns.Define(fn); - } - - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_Exists", Types.Bool, - #if !BHL_FRONT - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - EcsPackedEntityWithWorld e = default; - stack.PopRelease().Decode(ref e); - - if (e.Unpack(out EcsWorld world, out int id) == false) - return null; - - var dv = bhl.Val.New(frm.vm); - dv.SetBool(world.GetPool<{{o.name}}>().Has(id)); - stack.Push(dv); - - return null; - } - #else - null - #endif - , - new FuncArgSymbol("__self", types.T("ecs.Entity")) - ); - types.ns.Define(fn); - } - - {% for f in o.getfields %} - {{ _self.ecslite_component_field(o, f) }} - {% endfor %} - - {% for m in o.getfuncs %} - {{ _self.ecslite_component_func(o, m) }} - {% endfor %} - -{%- endmacro -%} - -{%- macro ecslite_component_field(o, f) ~%} - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_{{f.name}}", {{f.type|bhl_type_ref}}, - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - 1, - {%- endif ~%} - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - #if !BHL_FRONT - Val dv = null; - - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - if(args_info.CountArgs() > 1) - dv = stack.Pop(); - {%- endif ~%} - - EcsPackedEntityWithWorld e = default; - stack.PopRelease().Decode(ref e); - - if (e.Unpack(out EcsWorld world, out int id) == false) - return null; - - ref var cmp = ref world.GetPool<{{o.name}}>().Ensure(id); - var v = cmp.{{f.name}}; - - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - if(dv != null) { - {{ _self.val2native(f.type, 'dv', 'v') }}; - cmp.{{f.name}} = v; - dv.Release(); - } - {%- endif ~%} - - dv = Val.New(frm.vm); - { - {{ _self.native2val(f.type, 'v', 'dv') }}; - } - stack.Push(dv); - #endif - return null; - }, - new FuncArgSymbol("e", types.T("ecs.Entity")) - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - , new FuncArgSymbol("v", {{f.type|bhl_type_ref}}) - {%- endif ~%} - ); - types.ns.Define(fn); - } -{%- endmacro -%} - -{%- macro ecslite_component_func(o, m) ~%} - { - var fn = new FuncSymbolNative(new Origin(), "{{o.name}}_{{m.name}}", - {{m.returntype|bhl_type_ref}}, - {{ count_default_args(m) }}, - #if !BHL_FRONT - delegate(VM.Frame frm, ValStack stack, FuncArgsInfo args_info, ref BHS status) { - EcsPackedEntityWithWorld e = default; - - {{ _self.read_args2natives(m, '__') }} - - stack.PopRelease().Decode(ref e); - - if (e.Unpack(out EcsWorld world, out int id) == false) - return null; - - ref var cmp = ref world.GetPool<{{o.name}}>().Ensure(id); - - {%~ if m.returntype %} - var return_val = - {%- endif ~%} - - cmp.{{m.name}}( - {%- for arg in m.args ~%} __{{arg.name}}{% if not loop.last %},{% endif %} {%- endfor ~%} - ); - - {{ _self.return_val(m, 'return_val') }} - - return null; - } - #else - null - #endif - , new FuncArgSymbol("__self", types.T("ecs.Entity")) - {%- if m.args %},{% endif ~%} - {{ _self.func_decl_args(m) }} - ); - types.ns.Define(fn); - } -{%- endmacro -%} - {%- macro return_val(f, return_var) -%} {%- if f.returntype -%} {%- if f.returntype is instanceof('\\mtgMultiType') -%} @@ -1134,50 +767,6 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack {%- endif ~%} {%- endmacro -%} -{%- macro ecs_component_field_ref(o, f) ~%} - { - cl.Define(new FieldSymbol(new Origin(), "{{f.name}}", {{f.type|bhl_type_ref}}, - {%- if token_or(f, 'bhl_get', 1) != 0 ~%} - //getter - delegate(VM.Frame frm, Val ctx, ref Val v, FieldSymbol fld) { - #if !BHL_FRONT - - var ent = ((EcsWorld)ctx._obj).RestoreEntityFromInternalId((int)ctx._num, (int)ctx._num2); - if(!ent.IsAlive() || !ent.Has()) - throw new System.Exception("Component '{{o.name}}' is no longer valid"); - ref var f = ref ent.Ensure(); - {{ _self.native2val(f.type, 'f.' ~ f.name, 'v') }}; - - #endif - } - {% else %} - //getter not allowed - null - {% endif %} - , - - {%- if token_or(f, 'bhl_set', 1) != 0 ~%} - //setter - delegate(VM.Frame frm, ref Val ctx, Val v, FieldSymbol fld) { - #if !BHL_FRONT - - var ent = ((EcsWorld)ctx._obj).RestoreEntityFromInternalId((int)ctx._num, (int)ctx._num2); - if(!ent.IsAlive() || !ent.Has()) - throw new System.Exception("Component '{{o.name}}' is no longer valid"); - ref var f = ref ent.Ensure(); - {{ _self.val2native(f.type, 'v', 'f.' ~ f.name) }}; - - #endif - } - {% else %} - //setter not allowed - null - {% endif %} - - )); - } -{%- endmacro -%} - {%- macro decl_units(units) ~%} {%- for u in units -%} @@ -1240,11 +829,7 @@ public partial class Script_{{u.object.name}} { {%- elseif u.object is instanceof('\\mtgMetaStruct') -%} - {%- if has_token(u.object, 'bhl_ecs_component') -%} - {{ _self.reg_ecs_component(u.object) }} - {%- elseif has_token(u.object, 'bhl_ecslite_component') -%} - {{ _self.reg_ecslite_component(u.object) }} - {%- elseif has_token(u.object, 'bhl_native_arr_proxy') -%} + {%- if has_token(u.object, 'bhl_native_arr_proxy') -%} {{ _self.reg_native_arr_proxy(u.object) }} {%- else -%} {{ _self.reg_class(u.object) }} @@ -1269,7 +854,6 @@ public partial class Script_{{u.object.name}} { //assign global static types {%- for u in units -%} {%- if u.object is instanceof('\\mtgMetaStruct') or u.object is instanceof('\\mtgMetaInterface') ~%} - {%- if not has_token(u.object, 'bhl_ecs_component') and not has_token(u.object, 'bhl_ecslite_component') ~%} { var tmp = types.T("{{u.object.name}}").Get(); if(tmp == null) @@ -1282,7 +866,6 @@ public partial class Script_{{u.object.name}} { {%- endif ~%} Types_{{u.object.name|norm_name}}.Value = tmp; } - {%~ endif ~%} {%- endif -%} {%- endfor -%} diff --git a/tpl/codegen_autobind.twig b/tpl/codegen_autobind.twig index fc35f38..e6fa4e8 100644 --- a/tpl/codegen_autobind.twig +++ b/tpl/codegen_autobind.twig @@ -7,10 +7,7 @@ using {{imp}}; {%- endfor ~%} #endif -{%- import "macro.twig" as macro -%} - -{% block extra %} -{% endblock %} +{% import "bhl_bind_macro.twig" as macro %} namespace bhl { @@ -23,7 +20,11 @@ static public class Types_{{u.object.name|norm_name}} { {%- endfor ~%} #if !BHL_FRONT + {{ macro.decl_units(meta.units) }} + +{{ plugins_codegen_decls() }} + #endif static public class {{register_class}} { @@ -36,6 +37,8 @@ public static void Register(Types types) { RegisterBegin(types); RegisterEnd(types); + + {{ plugins_codegen_register() }} } public static void RegisterBegin(Types types)