units[$unit->object->getName()])) throw new Exception("Meta info unit '{$unit->object->getName()}' already defined in file '{$this->units[$unit->object->getName()]->file}'"); $this->units[$unit->object->getName()] = $unit; if($unit->object instanceof mtgMetaStruct) $this->_registerFactoryStruct($unit->object); else if($unit->object instanceof mtgMetaService) { foreach($unit->object->getUserTypes() as $user_type) if($user_type instanceof mtgMetaStruct) $this->_registerFactoryStruct($user_type); } } function delUnit(mtgMetaInfoUnit $unit) { unset($this->units[$unit->object->getName()]); if($unit->object instanceof mtgMetaStruct) $this->_unregisterFactoryStruct($unit->object); else if($unit->object instanceof mtgMetaService) { foreach($unit->object->getUserTypes() as $user_type) if($user_type instanceof mtgMetaStruct) $this->_unregisterFactoryStruct($user_type); } } function getUnits() : array { return $this->units; } function findUnit($id) : ?mtgMetaInfoUnit { if(isset($this->units[$id])) return $this->units[$id]; return null; } function getUnit($id) : mtgMetaInfoUnit { $unit = $this->findUnit($id); if(!$unit) throw new Exception("Unit '$id' not found"); return $unit; } private function _registerFactoryStruct(mtgMetaStruct $struct) { if(isset($this->factory_types[$struct->getClassId()])) throw new Exception("Factory user type with id '{$struct->getClassId()}' already defined for type '{$this->factory_types[$struct->getClassId()]->getName()}'"); $this->factory_types[$struct->getClassId()] = $struct; } private function _unregisterFactoryStruct(mtgMetaStruct $struct) { unset($this->factory_types[$struct->getClassId()]); } function getFactoryTypes() : array { return $this->factory_types; } function validate() { foreach($this->units as $u) $u->object->validate($this); } } class mtgMetaInfoUnit { public ?mtgMetaParsedModule $module = null; public string $file; public mtgMetaUnit $object; function __construct(mtgMetaParsedModule|string $file_or_module, mtgMetaUnit $obj) { if($file_or_module instanceof mtgMetaParsedModule) { $this->module = $file_or_module; $this->file = $file_or_module->file; } else { $this->module = null; $this->file = $file_or_module; } $this->object = $obj; } } //NOTE: represents a meta symbol abstract class mtgMetaUnit { protected ?mtgScope $scope = null; protected ?mtgOrigin $origin; protected $tokens = array(); abstract function getName() : string; function setScope(mtgScope $scope) { $this->scope = $scope; } function getScope() : ?mtgScope { return $this->scope; } function setOrigin(mtgOrigin $origin) { $this->origin = $origin; } function getOrigin() : ?mtgOrigin { return $this->origin; } function getTokens() : array { return $this->tokens; } function setTokens(array $tokens) { $this->tokens = $tokens; } function setToken(string $name, mixed $val) { $this->tokens[$name] = $val; } function delToken(string $name) { unset($this->tokens[$name]); } function getToken(string $name) : mixed { return $this->hasToken($name) ? $this->tokens[$name] : null; } function hasToken(string $name) : bool { return array_key_exists($name, $this->tokens); } abstract function validate(mtgMetaInfo $meta); } class mtgOrigin { public $file; public $line; function __construct($file = '', $line = 0) { $this->file = $file; $this->line = $line; } function __toString() { return "{$this->file}@{$this->line}"; } }