|
|
@ -2,7 +2,7 @@ |
|
|
|
|
|
|
|
declare(strict_types=1); |
|
|
|
|
|
|
|
namespace App\Engine\Cfnpp; |
|
|
|
namespace App\Cfnpp; |
|
|
|
|
|
|
|
use App\Dom\Document; |
|
|
|
use App\Dom\Node; |
|
|
@ -171,8 +171,8 @@ class Compiler implements \App\Engine\ICompile |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Compiler Pass 1 - Grab all variables, build dependency graph of |
|
|
|
* dependencies between variable values, resolve variables values. Then |
|
|
|
* Compiler Pass 1 - Grab all variables and parameters, build dependency |
|
|
|
* graph of dependencies between values, resolve values. Then |
|
|
|
* set them on $options to include them in program state. |
|
|
|
* |
|
|
|
* @param Document $document |
|
|
@ -182,32 +182,61 @@ class Compiler implements \App\Engine\ICompile |
|
|
|
protected function pass_1(Document $document, IOptions $options): void |
|
|
|
{ |
|
|
|
$variables_node = $document->getChildByPath('cfnpp.variables'); |
|
|
|
// If there are no variables, we're done here. |
|
|
|
if (!isset($variables_node)) |
|
|
|
$parameters_node = $document->getChildByPath('cfnpp.parameters'); |
|
|
|
// If there are no variables or parameters, we're done here. |
|
|
|
if (!isset($variables_node) && !isset($parameters_node)) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
$variables_raw = []; |
|
|
|
$nodes = []; |
|
|
|
$graph = new DependencyGraph(); |
|
|
|
|
|
|
|
foreach ($variables_node as $variable_node) |
|
|
|
if (isset($parameters_node)) |
|
|
|
{ |
|
|
|
$variables_raw[$variable_node->getName()] = $variable_node; |
|
|
|
$graph->add($variable_node->getName(), $this->pass_1_getVariableDependencies($variable_node)); |
|
|
|
foreach ($parameters_node as $parameter_node) |
|
|
|
{ |
|
|
|
$nodes[$parameter_node->getName()] = $parameter_node; |
|
|
|
$graph->add($parameter_node->getName(), $this->pass_1_getDependencies($parameter_node)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (isset($variables_node)) |
|
|
|
{ |
|
|
|
foreach ($variables_node as $variable_node) |
|
|
|
{ |
|
|
|
if (isset($nodes[$variable_node->getName()])) |
|
|
|
{ |
|
|
|
throw new \Exception("Variables and parameters cannot share the same name."); |
|
|
|
} |
|
|
|
$nodes[$variable_node->getName()] = $variable_node; |
|
|
|
$graph->add($variable_node->getName(), $this->pass_1_getDependencies($variable_node)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
$variables_ordered = $graph->solve(); |
|
|
|
$nodes_ordered = $graph->solve(); |
|
|
|
|
|
|
|
foreach ($variables_ordered as $variable) |
|
|
|
foreach ($nodes_ordered as $node_name) |
|
|
|
{ |
|
|
|
$this->runFunctions($variables_raw[$variable]); |
|
|
|
$variable_node = $variables_node->getChildByName($variable); |
|
|
|
// By all accounts this _should_ still exist, but this accounts for the |
|
|
|
// case where, say, someone had used !unset on a variable for some reason. |
|
|
|
if (isset($variable_node)) |
|
|
|
$this->runFunctions($nodes[$node_name]); |
|
|
|
|
|
|
|
$type = $nodes[$node_name]->getParent()->getName(); |
|
|
|
|
|
|
|
if ($type == 'parameters') |
|
|
|
{ |
|
|
|
$parameter_node = $parameters_node->getChildByName($node_name); |
|
|
|
if (isset($parameter_node)) |
|
|
|
{ |
|
|
|
$options->setParameter($parameter_node->getName(), Node::toPhp($parameter_node)); |
|
|
|
} |
|
|
|
} |
|
|
|
else if ($type == 'variables') |
|
|
|
{ |
|
|
|
$options->setVariable($variable, Node::toPhp($variable_node)); |
|
|
|
$variable_node = $variables_node->getChildByName($node_name); |
|
|
|
if (isset($variable_node)) |
|
|
|
{ |
|
|
|
$options->setVariable($variable_node->getName(), Node::toPhp($variable_node)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -220,7 +249,7 @@ class Compiler implements \App\Engine\ICompile |
|
|
|
* @param Node $node |
|
|
|
* @return string[] |
|
|
|
*/ |
|
|
|
protected function pass_1_getVariableDependencies(Node $node): array |
|
|
|
protected function pass_1_getDependencies(Node $node): array |
|
|
|
{ |
|
|
|
$stack = [$node]; |
|
|
|
|
|
|
@ -240,10 +269,15 @@ class Compiler implements \App\Engine\ICompile |
|
|
|
{ |
|
|
|
$variables[] = $node->getValue(); |
|
|
|
} |
|
|
|
else if ($node instanceof NodeFunctionValue && |
|
|
|
$node->getName() == 'param') |
|
|
|
{ |
|
|
|
$variables[] = $node->getValue(); |
|
|
|
} |
|
|
|
elseif ($node instanceof NodeFunctionValue && |
|
|
|
$node->getName() == 'expr') |
|
|
|
{ |
|
|
|
$parser = new \App\Engine\Cfnpp\Expression\Parser(); |
|
|
|
$parser = new \App\Cfnpp\Expression\Parser(); |
|
|
|
$expression = $parser->parse($node->getValue()); |
|
|
|
$variables = array_merge($variables, $expression->getReferencedVariables()); |
|
|
|
} |