Initial introduction of plugins, removing ECS related stuff

This commit is contained in:
Pavel Shevaev 2023-10-23 11:21:35 +03:00
parent a5685a99a1
commit bcacb192d7
5 changed files with 103 additions and 447 deletions

View File

@ -9,7 +9,8 @@
},
"autoload": {
"files": [
"src/bind.inc.php"
"src/bind.inc.php",
"src/plugin.inc.php"
]
}
}

View File

@ -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)
{

10
src/plugin.inc.php Normal file
View File

@ -0,0 +1,10 @@
<?php
namespace bhl_bind;
use Exception;
interface BindPlugin
{
function init(\mtgMetaInfo $meta, \Twig\Environment $twig);
function codegenDecls(\Twig\Environment $twig);
function codegenRegister(\Twig\Environment $twig);
}

View File

@ -753,373 +753,6 @@ Script_{{o.name|norm_name}}.Method_{{m.name}}.ReturnValue(frm, stack
{%- endmacro -%}
{%- macro reg_ecs_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) {
EcsEntity e = default;
stack.PopRelease().Decode(ref e);
ref var cmp = ref e.Ensure<ecs.{{o.name}}>();
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<ecs.{{o.name}}>();
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<ecs.{{o.name}}>());
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<ecs.{{o.name}}>();
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<ecs.{{o.name}}>();
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<ecs.{{o.name}}>();
{%~ 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<ecs.{{o.name}}>())
throw new System.Exception("Component '{{o.name}}' is no longer valid");
ref var f = ref ent.Ensure<ecs.{{o.name}}>();
{{ _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<ecs.{{o.name}}>())
throw new System.Exception("Component '{{o.name}}' is no longer valid");
ref var f = ref ent.Ensure<ecs.{{o.name}}>();
{{ _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 -%}

View File

@ -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)