292 lines
5.1 KiB
PHP
Executable File
292 lines
5.1 KiB
PHP
Executable File
<?php
|
|
|
|
class SeTMLRuntime {
|
|
|
|
public static function initState ($data) {
|
|
|
|
return array(
|
|
'data' => $data,
|
|
'alloc' => array(
|
|
'' => null,
|
|
),
|
|
);
|
|
|
|
}
|
|
|
|
/* execution environnement */
|
|
public
|
|
$engine = null,
|
|
|
|
$flow = null,
|
|
$alloc = null,
|
|
$frame = null,
|
|
$blocks = array(),
|
|
|
|
$stack = array();
|
|
|
|
public function __construct ( $data ) {
|
|
|
|
$this->frame = self::initState($data);
|
|
|
|
$this->flow = &$this->frame['alloc'][''];
|
|
$this->alloc = &$this->frame['alloc'];
|
|
|
|
}
|
|
|
|
public function run ( $code, Engine $engine = null, $file = false ) {
|
|
|
|
$en = $this->engine;
|
|
$this->engine = $engine;
|
|
|
|
$this->exec($this, $code, $file);
|
|
|
|
$this->engine = $en;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
private function exec ($runtime, $code, $file = false) {
|
|
|
|
if ( $file )
|
|
include($code);
|
|
|
|
else eval($code);
|
|
|
|
}
|
|
|
|
public function getData( $idx = false ) {
|
|
|
|
if ( $idx !== false )
|
|
return $this->frame['alloc'][$idx];
|
|
|
|
return $this->frame['alloc'];
|
|
|
|
}
|
|
|
|
public function appendContent ( $data ) {
|
|
|
|
if ( is_array($this->flow) ) {
|
|
|
|
if ( empty($this->flow['']) )
|
|
$this->flow[''] = $data;
|
|
else $this->flow[''] .= $data;
|
|
|
|
} else $this->flow .= $data;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
public function cpush ( &$pointer, $map = false ) {
|
|
|
|
$this->stack[] = array(
|
|
&$this->flow,
|
|
&$this->alloc,
|
|
);
|
|
|
|
$this->alloc = &$pointer;
|
|
|
|
if ( is_array($map) ) {
|
|
|
|
foreach ( $map as $k => $v )
|
|
$this->alloc[$k] = $v;
|
|
|
|
$this->flow = &$pointer[''];
|
|
|
|
} else $this->flow = &$pointer;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
public function cpop () {
|
|
|
|
$data = $this->frame['alloc'];
|
|
|
|
$alloc = array_pop($this->stack);
|
|
|
|
$this->flow = &$alloc[0];
|
|
$this->alloc = &$alloc[1];
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
public function lpush ( $data = array() ) {
|
|
|
|
$this->stack[] = array(
|
|
&$this->flow,
|
|
&$this->alloc,
|
|
$this->frame['alloc']
|
|
);
|
|
|
|
$this->frame['alloc'] = $data;
|
|
|
|
$this->flow = &$this->frame['alloc'][''];
|
|
$this->alloc = &$this->frame['alloc'];
|
|
|
|
}
|
|
|
|
public function lpop () {
|
|
|
|
$data = $this->frame['alloc'];
|
|
|
|
$alloc = array_pop($this->stack);
|
|
|
|
$this->flow = &$alloc[0];
|
|
$this->alloc = &$alloc[1];
|
|
$this->frame['alloc'] = $alloc[2];
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
public function mpush ( $data = array() ) {
|
|
|
|
$this->stack[] = array(
|
|
&$this->flow,
|
|
&$this->alloc,
|
|
$this->frame,
|
|
$this->blocks
|
|
);
|
|
|
|
$this->frame = self::initState($data);
|
|
|
|
}
|
|
|
|
public function mpop () {
|
|
|
|
$data = $this->frame;
|
|
|
|
$frame = array_pop($this->stack);
|
|
|
|
$this->flow = &$frame[0];
|
|
$this->alloc = &$frame[1];
|
|
$this->frame = $frame[2];
|
|
$this->blocks = array_merge($frame[3], array_diff_key($this->blocks, $frame[3]));
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
public function mergeFrame ( $frame ) {
|
|
|
|
foreach ( $frame['alloc'] as $k => $v )
|
|
if ( $k !== '' )
|
|
$this->frame['alloc'][$k] = $v;
|
|
|
|
$this->appendContent($frame['alloc']['']);
|
|
|
|
}
|
|
|
|
|
|
public function setBlock ( &$pointer, $block, $scope = array() ) {
|
|
|
|
$pointer = array(
|
|
$block,
|
|
$scope
|
|
);
|
|
|
|
}
|
|
|
|
public function callBlock ( $pointer, $data = array() ) {
|
|
|
|
if ( empty($pointer) )
|
|
throw new Exception(sprintf('RuntimeError block does not exists !'));
|
|
|
|
$block = $pointer[0];
|
|
|
|
$this->mpush(array_merge($pointer[1], $data));
|
|
|
|
$block($this);
|
|
|
|
$this->mergeFrame($this->mpop());
|
|
|
|
}
|
|
|
|
public function includeTemplate ( $file, $data, $asis = false ) {
|
|
|
|
$engine = $this->engine;
|
|
|
|
$file = Path::get(preg_replace('!//+!', '/', preg_match('!^/!', $file) ? $file : $this->engine->getDir() . '/' . $file));
|
|
|
|
try {
|
|
|
|
$tpl = Template::fromFile(
|
|
$file,
|
|
$this->engine->getRoot(),
|
|
$this->engine->getCache()
|
|
);
|
|
|
|
if ( $asis )
|
|
$this->appendContent($tpl->getSource());
|
|
|
|
else {
|
|
|
|
$this->mpush($data);
|
|
$tpl->run($this);
|
|
$this->mergeFrame($this->mpop());
|
|
|
|
}
|
|
|
|
} catch ( Exception $e ) {
|
|
|
|
throw new Exception(sprintf(
|
|
'RuntimeError during inclusion of file "%1$s" in root directory' . "\n" . '"%2$s"' . "\n" . 'specified in file "%3$s"!',
|
|
$file,
|
|
$engine->getRoot(),
|
|
$engine->getBasename()
|
|
), 0, $e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public function metaTemplate ( Closure $template, $cache = null ) {
|
|
|
|
$engine = $this->engine;
|
|
|
|
try {
|
|
|
|
$data = $template($this);
|
|
$this->mpush($data);
|
|
|
|
if ( !$cache ) {
|
|
|
|
Template::fromString(
|
|
$data[''],
|
|
$this->engine->getDir(),
|
|
$this->engine->getRoot(),
|
|
$this->engine->getCache()
|
|
)->run($this);
|
|
|
|
} else {
|
|
|
|
Template::fromFile(
|
|
Path::get($cache[0] === DIRECTORY_SEPARATOR ? $cache : $this->engine->getDir() . DIRECTORY_SEPARATOR . $cache),
|
|
$this->engine->getRoot(),
|
|
$this->engine->getCache(),
|
|
$data['']
|
|
)->run($this);
|
|
|
|
}
|
|
|
|
$this->mergeFrame($this->mpop());
|
|
|
|
} catch ( Exception $e ) {
|
|
|
|
throw new Exception(sprintf(
|
|
'RuntimeError during meta processing of file "%1$s" in root directory' . "\n" . '"%2$s"%3$s !',
|
|
$engine->getBasename(),
|
|
$engine->getRoot(),
|
|
$cache ? ".\nMeta template available in mirror file " . $cache : '.'
|
|
), 0, $e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
?>
|