<?PHP
NAMESPACE ILLI\Core\Type;
USE ILLI\Core\Spl\Fsm;
USE ILLI\Core\Std\Clsid;
USE ILLI\Core\Type\__flag_T;
USE ILLI\Core\Type\T\GC;
USE ILLI\Core\Type\T\Data;
USE ILLI\Core\Type\ILimitable;
USE ILLI\Core\Type\IListable;
USE ILLI\Core\Std\Exception;
USE ILLI\Core\Util\UUID;
ABSTRACT CLASS T
{
private static $__gc = [];
protected $__super = NULL;
protected $__context = NULL;
protected $__clsid = NULL;
protected $__prop = 0b00;
protected $__Definition = NULL;
private $__Data = NULL;
function __construct(array $__type, $__context = UUID::NIL, $__super = UUID::NIL)
{
$this->__context = UUID::normalize($__context);
$this->__super = UUID::normalize($__super);
$G = &self::$__gc[$this->__super][get_called_class()][$this->__context];
$this->__Definition = &$G[0x00];
$this->__clsid = &$G[0x01];
#+ create data matrix:
$this->__Data instanceOf Data ?: $this->__Data = new Data;
#+ load or create type declaration for this class
if(NULL === ($T = &$G[0x00]))
$T = new GC((array) $__type);
#+ set property flag by type declaration
switch(TRUE):
case 0x00 === $T->getSize(): $this->__prop |= __flag_T::T_VOID; break;
case 0x01 === $T->getSize(): $this->__prop |= __flag_T::T_SHALLOW; break;
case 0x02 === $T->getSize(): $this->__prop |= __flag_T::T_PAIR; break;
case 0x02 < $T->getSize(): $this->__prop |= __flag_T::T_ROW; break;
endswitch;
foreach(class_implements($this) as $interface)
switch($interface):
case IListable::class: $this->__prop |= __flag_T::T_LISTABLE; break;
case ILimitable::class: $this->__prop |= __flag_T::T_LIMITABLE; break;
endswitch;
#+ set matrix dimension
switch(TRUE):
case $this instanceOf IListable: $this->__Data->setSize($T->getSize()); break;
case 0x00 === $T->getSize(): $this->__Data->setDimension(0x00, 0x00); break;
case 0x00 < $T->getSize(): $this->__Data->setDimension($T->getSize(), 0x01); break;
endswitch;
#+ clsid
NULL !== ($C = &$G[0x01]) ?:
$C = (new Clsid(__CLASS__, get_called_class(), [
'definition' => $T->invoke('invoke', ['clsid']), // Fsc->Fsc->Define::clsid()
'prop' => $this->__prop
], $this->__context, $this->__super))->uuid();
}
/**
* add or remove lines in data FSM
*
* @param int $__length Lines : y range
* @throws Exception when interface T_LISTABLE is not implemented
* @throws Exception when interface T_LIMITABLE is implemented
*/
function setLength($__length)
{
if(__flag_T::T_LISTABLE !== ($this->__prop & __flag_T::T_LISTABLE)
|| __flag_T::T_LIMITABLE === ($this->__prop & __flag_T::T_LIMITABLE))
throw new Exception('Unable to add or remove lines (y offset): {:class} does not implement interface {:IListable} or implements {:ILimitable}.',
['class' => get_called_class(), 'ILimitable' => ILimitable::class, 'IListable' => IListable::class]);
$this->__Data->setLength($__length);
return $this;
}
function inRange($__field = 0x00, $__line = 0x00)
{
return $__field >= 0x00
&& $__line >= 0x00
&& $__field <= $this->__Data->getSize() - 1
&& $__line <= $this->__Data->getLength() - 1;
}
/**
* store value at specific offset in data FSM
*
* n = 0 ... defined fields - 1
* i = 0 ... infinite
* f = 0 ... finite
*
* T T<IListable> T<IListable:ILimited>
*
* & T_PAIR [0,0] [1,0] [0,i] [1,i] [0,f] [1,f]
* & T_ROW [n,0] [n,i] [n,f]
* & T_SHALLOW [0,0] [0,i] [0,f]
*
* @param mixed $__value expected type is defined in Field Declaration
* @param int $__field Field : offset x, default 0
* @param int $__line Line : offset y, default 0
*
* @internal this method should be protected
* @testing default address for $__prop
* @todo
*/
function set($__value, $__field = 0x00, $__line = 0x00)
{
if(FALSE === $this->inRange($__field, $__line))
throw new Exception('Unable to set data: address {:class}<x:{:field},y:{:line}> not found.',
['field' => $__field, 'line' => $__line, 'class' => get_called_class()]);
$this->__Data->offsetGet($__field)->offsetSet($__line, $__value);
}
Comments