Last active
August 1, 2019 02:44
-
-
Save Lachee/de832c924211145233e097beb8c272d7 to your computer and use it in GitHub Desktop.
XVE Argument Resolve.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function compileTemplate(Template $template, $tokens) | |
{ | |
return $template->evaluate($tokens); | |
} | |
/** | |
Resolves a input. Returns either a Literal or a string. | |
The strings are either a variable name or some compiled code. Either way they are safe to 'paste' in place. | |
*/ | |
function resolve($node, $output) | |
{ | |
$nodeDefinition = $node->getNodeDefinition(); | |
$isLiteral = false; | |
$arguments = array(); | |
$tokens = [ | |
'function' => $this->getNodeDefinition()->getFunction(), | |
'operator' => $this->getNodeDefinition()->getOperator(), | |
]; | |
for($i = 0; $i < count($node->inputs); $i++) | |
{ | |
//Prepare the value and link | |
$slot = $node->getSlotDefinition(Node::INPUT_SLOT, $i); //Returns the SlotDefinition of the INPUT side. | |
$link = $node->getInputLink($i); //Returns the Link for the input slot at index i. | |
$value = $node->getBinding($i); //Returns the Literal (or null) for the binding field. | |
//Connected, so override value. | |
if ($link->node != null) | |
$value = $this->resolve($link->node, $link->target); //Recursive call to itself. | |
//Store data | |
$tokens["in.{$i}"] = $value; | |
$arguments[$slot->getName()] = $value; | |
} | |
//Return the node dependent resolution. | |
// If we have overwritten the resolve in the definition of the type, then it will execute that (if able). | |
// otherwise it will resolve the output in a default manner. | |
// This means, for event based nodes it will return the variable name. | |
// For OOP and Operator based nodes, it will return an evaluated template that can be pasted in. | |
$resolution = $nodeDefinition->resolve($this, $node, $arguments, $output); | |
if ($resolution instanceof Template) | |
{ | |
//Async and Event type nodes CANNOT be compiled in this context. They must follow the flow so their results can be compiled. | |
// The NodeDefinition::resolve should account for this already. | |
if ($nodeDefinition->getStyle() == FUNCSTYLE_EVENT || $nodeDefinition->getStyle() == FUNCSTYLE_ASYNC) | |
throw new \Exception("Cannot compile EVENT or ASYNC nodes while resolving argument."); | |
//We are safe to compile. | |
return $this->compileTemplate($resolution, $tokens); | |
} | |
//Return the final resolution. This is either a variable, some compiled code, or a literal. | |
// Either way it can be just pasted in. | |
return $resolution; | |
} | |
class Link | |
{ | |
public $node //Node The node it is connected to. | |
public $target //int The slot the node is connected to | |
} | |
class Template | |
{ | |
public $text //string The template itself. | |
function evaluate($parameters) | |
{ | |
$eval = $this->text; | |
foreach($parameters as $key => $value) | |
{ | |
$token = '$' . strtolower($key) . '$'; | |
$eval = str_replace($token, $value, $eval); | |
} | |
return $eval; | |
} | |
} | |
class NodeDefinition | |
{ | |
function resolve($compiler, $node, $arguments, $output) | |
{ | |
//We have overwritten the resolution function, so lets use that instead. | |
if ($this->literal != null) | |
{ | |
//Prepare the value. | |
$val = null; | |
//Its not a callable (function) so it must be a raw literal itself. | |
if (!is_callable($this->literal)) | |
$val = $this->literal; | |
//Validate we can use the override | |
$canExecute = true; | |
foreach($arguments as $arg) | |
{ | |
if (!($arg instanceof Literal)) | |
{ | |
$canExecute = false; | |
break; | |
} | |
} | |
//If we can use it, call the function. | |
if ($canExecute) | |
$val = $this->literal($compiler, $arguments, $output); | |
//We have a val, so we can actually return it (otherwise fall through and find it the hard way). | |
if ($val != null) | |
{ | |
//Make sure the value is a Literal, otherwise something broke. | |
if (!($val instanceof Literal)) | |
throw new \Exception("The literal NodeDef override must return a object of type Literal."); | |
//Return the literal | |
return $val; | |
} | |
} | |
switch($this->style) | |
{ | |
//TODO: Make these resolve the template, not just return it. | |
// There might be an issue with infinite loops. | |
default: | |
case self::FUNCSTYLE_OPERATOR: | |
case self::FUNCSTYLE_OOP: | |
return $this->getCompileTemplate(); | |
//EVENT based ones are a special case. They cannot resolve early. | |
case self::FUNCSTYLE_ASYNC: | |
case self::FUNCSTYLE_EVENT: | |
return $compiler->getVariableName($node, $output); | |
} | |
} | |
/** Fetches the template. If it doesn't have one, a default one for the style will be returned. | |
OPERATOR: $in.0$ $operator$ $in.1$ $operator$ $in.2$ $operator$ ... | |
STATIC: $function$($in.0$, $in.1$, ...) | |
OOP: $in.0$.$function$($in.1$, $in.2$, ... ) | |
EVENT: $in.0$.$function$($in.1$, $in.2$, ... ); $next$ | |
ASYNC: $in.0$.$function$($in.1$, $in.2$, ... ).then(($out.0$, $out.1$, ...) => { $then$ }); $next | |
*/ | |
function getCompileTemplate() : Template | |
{ | |
//Get the template if it exists already. | |
// Note: When loading this template, it will put it into a Template object for us. | |
// It will also load any template strings that end in .js and use those instead. | |
if ($this->template != null) | |
return $this->template; | |
switch($this->stlye) | |
{ | |
//... | |
} | |
} | |
} | |
/* | |
Thoughts: | |
Binding needs to be able to load .js files too. Check that. | |
Templates are loaded into a Template object. If they end in .js, then load that | |
Maybe bring loaded definition files inline with templates by changing __prototype to $prototype$ | |
Are FUNCSTYLE_EVENT static or oop? Their async version FUNCSTYLE_ASYNC are oop, however since the FUNCSTYLE_EVENT are really only loading things like foreach and store, should they be static by default? | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment