Recursion

Our current language can either add or multiply two numbers. However, the result of an addition can not be used in a multiplication and vice-versa, since the arguments of both functions are primitive numbers. We also can't add or multiply using Pi.

> add pi 1
Error: Unexpected token "pi" at index 1 for type <p.number>

We can change this by changing the arguments of add and mul to value, making them recursive.

  Func("add")
    .arg(value)
    .arg(value)
    .setExec((left, right) => left + right),

However, we now have a new problem, as we can only use recursion.

> add 1 2
Error: Unexpected token "1" at index 1 for type <t.value>
> add pi pi
6.28

We could solve this problem using a separate function, for example im for immediate, but this is annoying to use.

  Func("im")
    .arg(primitives.number)
    .setExec((val) => val),
> add im 5 im 10
15

Instead, value has an optional default expression, which will be parsed if none of its functions matched the input.

value.setDefault(primitives.number);

This gives the desired functionality:

> add 5 mul 6 7
47
> 5
5

Notice that a single number is now also a valid program. We can see this in the updated grammar.

l.calc:
 | <t.value> EOI

t.value:
 | "add"      <t.value> <t.value>
 | "mul"      <t.value> <t.value>
 | "pi"      
 | <p.number>