public function testFunctionDefinitionWithOptionalParams() { $context = new Context(); $context->def('func', function ($param1, $param2 = 100) { return $param1 + $param2; }); $actual = $context->fn('func', array(3)); $this->assertEquals(103.0, $actual); $actual = $context->fn('func', array(3, 200)); $this->assertEquals(203.0, $actual); }
public function reduce(Context $ctx) { $this->stack = array(); $len = 0; // While there are input tokens left // Read the next token from input. while ($t = array_shift($this->queue)) { switch ($t->type) { case Token::T_NUMBER: case Token::T_IDENT: // wert einer konstanten ermitteln if ($t->type === Token::T_IDENT) { $t = new Token(Token::T_NUMBER, $ctx->cs($t->value)); } // If the token is a value or identifier // Push it onto the stack. $this->stack[] = $t; ++$len; break; case Token::T_PLUS: case Token::T_MINUS: case Token::T_UNARY_PLUS: case Token::T_UNARY_MINUS: case Token::T_TIMES: case Token::T_DIV: case Token::T_MOD: case Token::T_POW: case Token::T_NOT: // It is known a priori that the operator takes n arguments. $na = $this->argc($t); // If there are fewer than n values on the stack if ($len < $na) { throw new RuntimeError('laufzeit fehler: zu wenig paramter für operator "' . $t->value . '" (' . $na . ' -> ' . $len . ')'); } $rhs = array_pop($this->stack); $lhs = null; if ($na > 1) { $lhs = array_pop($this->stack); } // if ($lhs) print "{$lhs->value} {$t->value} {$rhs->value}\n"; // else print "{$t->value} {$rhs->value}\n"; $len -= $na - 1; // Push the returned results, if any, back onto the stack. $this->stack[] = new Token(Token::T_NUMBER, $this->op($t->type, $lhs, $rhs)); break; case Token::T_FUNCTION: // function $argc = $t->argc; $argv = array(); $len -= $argc - 1; for (; $argc > 0; --$argc) { array_unshift($argv, array_pop($this->stack)->value); } // Push the returned results, if any, back onto the stack. $this->stack[] = new Token(Token::T_NUMBER, $ctx->fn($t->value, $argv)); break; default: throw new RuntimeError('laufzeit fehler: unerwarteter token `' . $t->value . '`'); } } // If there is only one value in the stack // That value is the result of the calculation. if (count($this->stack) === 1) { return array_pop($this->stack)->value; } // If there are more values in the stack // (Error) The user input has too many values. throw new RuntimeError('laufzeit fehler: zu viele werte im stack'); }