Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception: Empty argument in Evaluator->addArgument() when custom function without arguments #20

Open
koosvanderkolk opened this issue Feb 3, 2021 · 4 comments

Comments

@koosvanderkolk
Copy link

I have and EvalMathFunctions class, holding a 'random' function without arguments.

class EvalMathFunctions {
  static public function random() {
    return rand();
  }
}

I register this in matex:

$this->evaluator->functions = [
  'random' => ['ref' => '\\EvalMathFunctions::random', 'arc' => 0]
];

I then call the function:

$this->evaluator->execute('random()');

And get the error.

@koosvanderkolk
Copy link
Author

This seems to fix it (see changes in bold)

private function getFunction(string $name) {
$routine = $this->functions[$name] ?? null;
$arguments = array();
if (!isset($routine) && isset($this->onFunction)) {
call_user_func_array($this->onFunction, [$name, &$routine]);
$this->functions[$name] = $routine;
}
if (!isset($routine))
throw new Exception('Unknown function: ' . $name, 6);
if (isset($routine['arc']) && $routine['arc'] > 0 && !$this->getArguments($arguments))
throw new Exception('Syntax error', 1);
if (isset($routine['arc']) && ($routine['arc'] != count($arguments)))
throw new Exception('Invalid argument count', 3);
return call_user_func_array($routine['ref'], $this->proArguments($arguments));
}

@madorin
Copy link
Owner

madorin commented Feb 3, 2021

yup, seems functions without arguments not tested yet )
thanks i'll look on it

@mszyca
Copy link

mszyca commented Aug 15, 2021

Hi @madorin, great, simple (not so simple xd) and efficient code for Evaluator !
If i understand correctly arc parameter
* $routine['arc'] = null - any number of arguments
* $routine['arc'] = 0 - function without arguments
* $routine['arc'] > 1 - specified number of arguments
So in addition to condition that wrote @koosvanderkolk

 private function getFunction(string $name)
    {
        $routine = $this->functions[$name] ?? null;
        $arguments = [];
        if (!isset($routine) && isset($this->onFunction)) {
            call_user_func_array($this->onFunction, [$name, &$routine]);
            $this->functions[$name] = $routine;
        }
        if (!isset($routine))
            throw new Exception('Unknown function: ' . $name, 6);
// +++++
        if (((isset($routine['arc']) && $routine['arc'] > 0) || is_null($routine['arc']) ) &&
            !$this->getArguments($arguments))
            throw new Exception('Syntax error', 1);
// +++++
        if (isset($routine['arc']) && ($routine['arc'] != count($arguments)))
            throw new Exception('Invalid argument count', 3);
        return call_user_func_array($routine['ref'], $this->proArguments($arguments));
}

Thanks very much for sharing.

@mszyca
Copy link

mszyca commented Aug 23, 2021

It works only for single function formula - formula without arguments.
Example: "DATENOW()" but for 'bigger' formulas not working Example: ""some text "+ DATENOW() + "text ""

For it to work proArguments() method needs:

    private function proArguments($arguments): array
    {
// +++++
        if (empty($arguments)) {
            $this->pos += 2;
            return [];
        }
// +++++
        $ops = $this->pos;
        $otx = $this->text;
        $result = [];
        foreach ($arguments as $argument)
            $result[] = $this->perform($argument);
        $this->pos = $ops;
        $this->text = $otx;
        return $result;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants