/** * Apply processing to a single node * * @param Node $node */ public function applyToNode(Node $node) { $expression = $node->getInstruction($this); $ast = $this->getParser()->parse($expression); $variables = $node->getResult() ?: []; $arithmetic = new Hoa\Math\Visitor\Arithmetic(); foreach ($variables as $name => $value) { // Constants are upper case and variables lower case. We don't really care, so using a workaround. if (preg_match('/^[A-Z_][A-Z0-9_]*$/', $name)) { $arithmetic->addConstant($name, $value); } else { $arithmetic->addVariable($name, function () use($value) { return $value; }); } } $result = $arithmetic->visit($ast); $node->setResult($result); }
public function case_visitor_exhaustively() { $this->given($sampler = new Compiler\Llk\Sampler\BoundedExhaustive(Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Test/Unit/Arithmetic.pp')), new Regex\Visitor\Isotropic(new LUT\Sampler\Random()), 9), $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT())->executeOnFailure(function () use(&$expression) { echo 'Failed expression: ', $expression, '.', "\n"; })->when(function () use(&$sampler, &$compiler, &$visitor) { foreach ($sampler as $expression) { $dump = $expression; try { $x = (double) $visitor->visit($compiler->parse($expression)); } catch (\Exception $e) { continue; } eval('$y = (float) ' . $expression . ';'); if (is_nan($x) || is_nan($y)) { $this->boolean(true); continue; } $this->float($x)->isNearlyEqualTo($y); } }); }
/** * The entry method. * * @return int */ public function main() { while (false !== ($c = $this->getOption($v))) { switch ($c) { case 'h': case '?': return $this->usage(); case '__ambiguous': $this->resolveOptionAmbiguity($v); break; } } $this->parser->listInputs($expression); $compiler = Compiler\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')); $visitor = new Math\Visitor\Arithmetic(); $dump = new Compiler\Visitor\Dump(); if (null !== $expression) { $ast = $compiler->parse($expression); echo $expression . ' = ' . $visitor->visit($ast), "\n"; return; } $readline = new Console\Readline(); $readline->setAutocompleter(new Console\Readline\Autocompleter\Word(array_merge(array_keys($visitor->getConstants()->getArrayCopy()), array_keys($visitor->getFunctions()->getArrayCopy())))); $handle = null; $expression = 'h'; do { switch ($expression) { case 'h': case 'help': echo 'Usage:', "\n", ' h[elp] to print this help;', "\n", ' c[onstants] to print available constants;', "\n", ' f[unctions] to print available functions;', "\n", ' e[xpression] to print the current expression;', "\n", ' d[ump] to dump the tree of the expression;', "\n", ' q[uit] to quit.', "\n"; break; case 'c': case 'constants': echo implode(', ', array_keys($visitor->getConstants()->getArrayCopy())), "\n"; break; case 'f': case 'functions': echo implode(', ', array_keys($visitor->getFunctions()->getArrayCopy())), "\n"; break; case 'e': case 'expression': echo $handle, "\n"; break; case 'd': case 'dump': if (null === $handle) { echo 'Type a valid expression before (“> 39 + 3”).', "\n"; } else { echo $dump->visit($compiler->parse($handle)), "\n"; } break; case 'q': case 'quit': break 2; default: if (null === $expression) { break; } try { echo $visitor->visit($compiler->parse($expression)), "\n"; } catch (Compiler\Exception $e) { echo $e->getMessage(), "\n"; break; } $handle = $expression; break; } } while (false !== ($expression = $readline->readLine('> '))); return; }
public function case_change_default_context() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $context = new \Mock\Hoa\Math\Context(), $variableName = 'a_variable', $variableValue = 42)->when($context->addVariable($variableName, function () use($variableValue) { return $variableValue; }))->then->object($visitor->setContext($context))->isNotIdenticalTo($context)->object($visitor->getContext())->isIdenticalTo($context)->float($visitor->visit($compiler->parse('abs(' . $variableName . ' - PI)')))->isEqualTo(abs($variableValue - M_PI))->mock($context)->call('getFunction')->withArguments('abs')->once->call('getVariable')->withArguments($variableName)->once->call('getConstant')->withArguments('PI')->once; }