metagen_php/tpl/macro.twig

383 lines
8.1 KiB
Twig
Raw Permalink Normal View History

2022-12-05 18:21:32 +03:00
{% macro decl_units(meta) %}
{%- for u in meta.getunits ~%}
{%- if u.object is instanceof('\\mtgMetaStruct') -%}
{{ _self.decl_struct(u.object) }}
2022-12-06 13:36:09 +03:00
{%- elseif u.object is instanceof('\\mtgMetaEnum') -%}
{{ _self.decl_enum(u.object) }}
2022-12-05 18:21:32 +03:00
{%- endif ~%}
{%- endfor ~%}
{% endmacro %}
2022-12-06 13:36:09 +03:00
{% macro decl_struct(o) %}
2022-12-05 18:21:32 +03:00
class {{o.name}} {{o.parent ? 'extends ' ~ o.parent.name}}
{
const CLASS_ID = {{o.classid}};
{{ _self.struct_fields(o) }}
static function CLASS_PROPS()
{
static $props = {{o.tokens|var_export}};
return $props;
}
static function CLASS_FIELDS()
{
static $flds = null;
if($flds === null)
$flds = {{_self.fields_names(o)}};
return $flds;
}
static function CLASS_FIELDS_TYPES()
{
static $flds = null;
if($flds === null)
$flds = {{_self.fields_types(o)}};
return $flds;
}
static function CLASS_FIELDS_PROPS()
{
static $flds = null;
if($flds === null)
$flds = {{_self.fields_props(o)}};
return $flds;
}
function __construct(&$data = null, $assoc = false)
{
{{_self.fields_init(o)}}
if(!is_null($data))
$this->import($data, $assoc);
}
function getClassId()
{
return self::CLASS_ID;
}
function import(&$data, $assoc = false, $root = true)
{
$IDX = -1;
try
{
if(!is_array($data))
throw new Exception("Bad data: $data");
try
{
$IDX = 0;
{{_self.import_fields(o)}}
}
catch(Exception $e)
{
2023-08-16 14:18:21 +03:00
$FIELDS = self::CLASS_FIELDS();
throw new Exception($e->getMessage() . " < {$FIELDS[$IDX]}");
2022-12-05 18:21:32 +03:00
}
if($root && $assoc && sizeof($data) > 0)
throw new Exception("Junk fields: " . implode(',', array_keys($data)));
}
catch(Exception $e)
{
throw new Exception($e->getMessage() . " < ({{o.name}})");
}
return $IDX;
}
function export($assoc = false, $virtual = false)
{
$data = array();
$this->fill($data, $assoc, $virtual);
return $data;
}
function fill(&$data, $assoc = false, $virtual = false)
{
if($virtual)
2022-12-06 13:36:09 +03:00
\metagen_php\array_set_value($data, $assoc, 'vclass__', $this->getClassId());
2022-12-05 18:21:32 +03:00
try
{
$__last_var = null;
$__last_val = null;
{{_self.export_fields(o)}}
}
catch(Exception $e)
{
2022-12-06 13:36:09 +03:00
throw new Exception("[{{o.name}}]\n->$__last_var\n" . serialize($__last_val) . "\n\t" . $e->getMessage());
2022-12-05 18:21:32 +03:00
}
}
}
{% endmacro %}
{% macro struct_fields(o) %}
{%- for f in o.fields ~%}
{{ _self.decl_struct_field(o, f) }}
{%- endfor -%}
{% endmacro %}
{% macro decl_struct_field(o, f) ~%}
2023-08-16 14:18:21 +03:00
{%- if f.type is instanceof('\\mtgMetaStruct') ~%}
/** @var {{f.type}}|null*/
{%- endif -%}
2022-12-05 18:21:32 +03:00
{%- if f.type is instanceof('\\mtgBuiltinType') and f.type.isstring ~%}
public ${{f.name}} = '';
{%- elseif f.type is instanceof('\\mtgArrType') ~%}
public ${{f.name}} = [];
{%- else ~%}
public ${{f.name}};
{%- endif -%}
{% endmacro %}
{% macro fields_names(o) %}
{%- if o.parent -%}
array_merge(parent::CLASS_FIELDS(),
{%- endif -%}
[
{%- for f in o.fields -%}
'{{f.name}}' {{not loop.last ? ','}}
{%- endfor -%}
]
{%- if o.parent -%}
)
{%- endif -%}
{% endmacro %}
{% macro fields_types(o) %}
{%- if o.parent -%}
array_merge(parent::CLASS_FIELDS_TYPES(),
{%- endif -%}
[
{%- for f in o.fields -%}
'{{f.name}}' => '{{f.type}}' {{not loop.last ? ','}}
{%- endfor -%}
]
{%- if o.parent -%}
)
{%- endif -%}
{% endmacro %}
{% macro fields_props(o) %}
{%- if o.parent -%}
array_merge(parent::CLASS_FIELDS_PROPS(),
{%- endif -%}
[
{%- for f in o.fields -%}
'{{f.name}}' => {{f.tokens|var_export}} {{not loop.last ? ','}}
{%- endfor -%}
]
{%- if o.parent -%}
)
{%- endif -%}
{% endmacro %}
{% macro field_init_value(o, f) %}
{%- if f.type is instanceof('\\mtgMetaStruct') ~%}
{%- if has_token(f, 'default') and token(f, 'default') == 'null' -%}
null
{%- else -%}
2022-12-05 18:21:32 +03:00
new {{f.type}}()
{%- endif -%}
2022-12-05 18:21:32 +03:00
{%- elseif f.type is instanceof('\\mtgMetaEnum') ~%}
{%- if has_token(f, 'default') -%}
2022-12-06 13:36:09 +03:00
{{f.type}}::{{token(f, 'default')|replace({'"' : ''})|default_value}}
2022-12-05 18:21:32 +03:00
{%- else -%}
{{f.type}}::DEFAULT_VALUE
{%- endif -%}
{%- elseif f.type is instanceof('\\mtgArrType') ~%}
[]
{%- elseif f.type is instanceof('\\mtgBuiltinType') ~%}
{%- if has_token(f, 'default') -%}
2022-12-06 13:36:09 +03:00
\metagen_php\val_{{f.type}}({{apply_value_filters(f.name, f.tokens, token(f, 'default')|default_value, false)}})
2022-12-05 18:21:32 +03:00
{%- elseif f.type.isstring -%}
''
{%- else -%}
0
{%- endif -%}
{%- else -%}
{{Error("Uknown type: " ~ f.type)}}
{%- endif -%}
{% endmacro %}
{% macro field_init(o, f) %}
$this->{{f.name}} = {{_self.field_init_value(o, f)}};
{% endmacro %}
{% macro fields_init(o) %}
{%- if o.parent -%}
parent::__construct();
{%- endif -%}
{%- for f in o.fields ~%}
{{_self.field_init(o, f)}}
{%- endfor -%}
{% endmacro %}
{% macro import_fields(o) %}
{%- if o.parent -%}
$IDX = parent::import($data, $assoc, false);
{%- endif -%}
{%- for f in o.fields ~%}
{{data2value(f.name, f.type, '$data', '$this->', f.tokens)}}
++$IDX;
{%- endfor -%}
{% endmacro %}
{% macro export_fields(o) %}
{%- if o.parent -%}
$__last_var = 'parent';
$__last_val = '<<skipped>>';
parent::fill($data, $assoc, false);
{%- endif -%}
{%- for f in o.fields ~%}
{{value2data(f.name, f.type, '$data', '$this->', f.tokens)}}
{%- endfor -%}
{% endmacro %}
2022-12-06 13:36:09 +03:00
{% macro decl_enum(o) %}
class {{o.name}}
{
const CLASS_ID = {{o.classid}};
{{ _self.enum_values(o) }}
const DEFAULT_VALUE = {{o.values|length > 0 ? o.values | first : 0}};
2022-12-06 13:36:09 +03:00
function getClassId()
{
return self::CLASS_ID;
}
static function isValueValid($value)
{
$values_list = self::getValuesList();
return in_array($value, self::$values_list_);
}
static private $values_map_;
static function getValueByName($name)
{
if(!self::$values_map_)
{
self::$values_map_ = array(
{{ _self.enum_values_map(o) }}
);
}
if(!isset(self::$values_map_[$name]))
throw new Exception("Value with name '$name' isn't defined in enum {{o.name}}. Accepted: " . implode(',', self::getNamesList()));
return self::$values_map_[$name];
}
static private $names_map_;
static function getNameByValue($value)
{
if(!self::$names_map_)
{
self::$names_map_ = array(
{{ _self.enum_names_map(o) }}
);
}
if(!isset(self::$names_map_[$value]))
throw new Exception("Value $value isn't defined in enum {{o.name}}. Accepted: " . implode(',', self::getValuesList()));
return self::$names_map_[$value];
}
// throws exception if $value is not valid numeric enum value
static function checkValidity($value)
{
if(!is_numeric($value))
throw new Exception("Numeric expected but got $value");
if(!self::isValueValid($value))
throw new Exception("Numeric value '$value' isn't value from enum {{o.name}}. Accepted numerics are " . implode(',', self::getValuesList()) . " but better to use one of names instead: " . implode(',', self::getNamesList()));
}
static private $values_list_;
static function getValuesList()
{
if(!self::$values_list_)
{
self::$values_list_ = array(
{{ _self.enum_values_list(o) }}
);
}
return self::$values_list_;
}
static private $names_list_;
static function getNamesList()
{
if(!self::$names_list_)
{
self::$names_list_ = array(
{{ _self.enum_names_list(o) }}
);
}
return self::$names_list_;
}
}
{% endmacro %}
{% macro enum_values(o) %}
{%- for n,v in o.values ~%}
const {{n}} = {{v}};
{%- endfor ~%}
{% endmacro %}
{% macro enum_values_map(o) %}
{%- for n,v in o.values ~%}
'{{n}}' => {{v}},
{%- endfor ~%}
{% endmacro %}
{% macro enum_names_map(o) %}
{%- for n,v in o.values ~%}
{{v}} => '{{n}}',
{%- endfor ~%}
{% endmacro %}
{% macro enum_values_list(o) %}
{%- for v in o.values ~%}
{{v}},
{%- endfor ~%}
{% endmacro %}
{% macro enum_names_list(o) %}
{%- for n,v in o.values ~%}
'{{n}}',
{%- endfor ~%}
{% endmacro %}
{% macro class_map(meta) %}
{%- for u in meta.getunits ~%}
case {{u.object.classid}} : return "{{u.object.name}}";
{%- endfor ~%}
{% endmacro %}