<?php
namespace Tlf\Lexer2\StdLib;
/**
* The standard library for a Lexer program
*/
class Main {
public function __construct(
protected \Tlf\Lexer2\Program $program
){
}
public function hook(string $hook_name, ...$command): void {
switch ($hook_name){
case "end_execute_commands":
$parser = new \Tlf\Lexer2\Parser();
$command = $parser->parse_command_string(implode(" ",$command),null)->toArray();
$this->program->end_execute_commands_hooks[] = $command;
break;
default:
throw new \Exception("Hook '$hook_name' does not exist");
}
}
/**
* Create a new object & return it.
* If the new object is an AST, then set it as the head ast.
*
* @param $object_name string like 'Ast\Type'
* @param $params array<string key, mixed value>
*/
public function new(string $object_name, array $params): object {
$parts = explode("\\", $object_name);
if ($parts[0]!='Ast'){
throw new \Exception("Currently, only Ast Objects are supported by the 'new' method");
}
$type = $parts[1];
$tree = [];
foreach ($params as $name=>$value){
if ($this->program->is_command($value)){
$real_value = $this->program->execute_command($value,4);
//var_dump($value);
//var_dump($real_value);
//exit;
$tree[$name] = $real_value;
} else {
$tree[$name] = $value;
}
}
$ast = new \Tlf\Lexer\Ast($type, $tree);
$this->program->ast_stack[] = $ast;
return $ast;
}
/**
* Return a local variable from the program.
*/
public function get_arg(string $arg_name){
//echo "\n\n\n\n\n";
//var_dump($arg_name);
//var_dump($this->program->local_vars);
//echo "\n\n\n\n\n";
//var_dump($this->program->local_vars[$arg_name]);
//exit;
return $this->program->local_vars[$arg_name];
}
public function set_arg(string $arg_name, $value){
$this->program->local_vars[$arg_name] = $value;
}
/**
* Remove the current directive from the 'unstarted' list of the current directive layer, and add it to the 'started' list
*/
public function start(){
$active_directive = $this->program->active_directive;
$stack_index = count($this->program->directive_stack) - 1;
$this->program->directive_stack[$stack_index]['started'][] = $active_directive;
$directive_index = array_search($active_directive, $this->program->directive_stack[$stack_index]['unstarted']);
unset($this->program->directive_stack[$stack_index]['unstarted'][$directive_index]);
$this->program->directive_stack[$stack_index]['unstarted'] = array_values($this->program->directive_stack[$stack_index]['unstarted']);
}
/**
* Remove the current directive from the 'started' list of the current directive layer, and add it to the 'unstarted' list
*/
public function stop(){
$active_directive = $this->program->active_directive;
$stack_index = count($this->program->directive_stack) - 1;
$this->program->directive_stack[$stack_index]['unstarted'][] = $active_directive;
$directive_index = array_search($active_directive, $this->program->directive_stack[$stack_index]['started']);
unset($this->program->directive_stack[$stack_index]['started'][$directive_index]);
$this->program->directive_stack[$stack_index]['started'] = array_values($this->program->directive_stack[$stack_index]['started']);
}
public function add_directive_layer(){
$this->program->directive_stack[] = ['unstarted'=>[], 'started'=>[]];
}
/**
* array_pop() a Program array, such as ast_stack or directive_stack
*/
public function pop(string $program_param_name){
if (!isset($this->program->$program_param_name)){
throw new \Exception("The Program does not have a property named $program_param_name");
} else if (!is_array($this->program->$program_param_name)){
throw new \Exception("The Program's property $program_param_name MUST be an array. It is a ".gettype($this->program->$program_param_name));
}
array_pop($this->program->$program_param_name);
}
//public function rewind(int $amount=1){
//$this->program->call('buffer.
//}
public function activateDirective(?string $namespace, string $directive_name){
if ($namespace == null){
$active_directive = $this->program->active_directive;
$namespace = $active_directive['--context--']['namespace'];
}
if (!isset($this->program->directives[$namespace][$directive_name])){
$this->program->error("Directive $namespace:$directive_name is not available");
echo "\n\n";
exit;
}
$directive = $this->program->directives[$namespace][$directive_name];
$this->program->addUnstartedDirectiveToStack($namespace.':'.$directive_name, $directive);
}
}