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' ) ~ %}
2023-05-05 12:10:20 +03:00
{% - if has_token ( f , 'default' ) and token ( f , 'default' ) == 'null' -%}
null
{% - else -%}
2022-12-05 18:21:32 +03:00
new {{ f .type }} ()
2023-05-05 12:10:20 +03:00
{% - 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 -%}
{{ E rror ( "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 ) }}
2024-09-30 20:29:13 +03:00
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 %}