Some reverse Polish notation fun

Since arithmetic with Dialog is a bit clunky, I wondered if it would be possible to make it simpler with some clever use of access predicates. So here’s a way to use reverse Polish notation!

(intro)
    ($Result <- [4 1 2 + x 3 :]) %% i.e. 4 * (1 + 2) / 3
    $Result %% = 4.

%% The arguments of the predicate are (RPN $Input $Stack $Result)

@(RPN [] [$Final] $Result)
    ($Result = $Final)

@(RPN [:] [$B $A] $Result)
    ($A divided by $B into $Result)

@(RPN [: | $Rest] [$B $A | $Stack] $Result)
    ($A divided by $B into $Quotient)
    (RPN $Rest [$Quotient | $Stack] $Result)

@(RPN [x] [$B $A] $Result)
    ($A times $B into $Result)

@(RPN [x | $Rest] [$B $A | $Stack] $Result)
    ($A times $B into $Product)
    (RPN $Rest [$Product | $Stack] $Result)

@(RPN [+] [$B $A] $Result)
    ($A plus $B into $Result)

@(RPN [+ | $Rest] [$B $A | $Stack] $Result)
    ($A plus $B into $Sum)
    (RPN $Rest [$Sum | $Stack] $Result)

@(RPN [-] [$B $A] $Result)
    ($A minus $B into $Result)

@(RPN [- | $Rest] [$B $A | $Stack] $Result)
    ($A minus $B into $Diff)
    (RPN $Rest [$Diff | $Stack] $Result)

@(RPN [$Value | $Rest] $Stack $Result)
    (RPN $Rest [$Value | $Stack] $Result)

@($Result <- $Operation)
    (RPN $Operation [] $Result)

It’s easy to expand to add operators and other functions. In fact it’s a stack machine so I guess we could do even wilder things.

Some notes:

  • There is no runtime cost since everything is made at compile time.
  • Malformed operations will be caught since Dialog won’t find an access predicate that match.
  • @(RPN [+] [$B $A] $Result) and the like are a small optimisation to skip the ($Result = $Final) part, although I’m not sure it’s necessary: it’s possible the compiler would optimise it away anyway.
  • You can’t have dynamic operators, i.e. [2 1 $Op] where $Op could be @+ or @-. Dialog cannot know at compile time if a variable will be an operator or a value, so it treats all variables as values.
  • Multiplication uses x instead of * and division : instead of / because * and / are special characters that would need escaping.
  • Very long operations will cause a compilation error (too many nested access predicates).

The next logical step would be to allow infix notation by using the shunting-yard algorithm. Though I haven’t found a way to easily specify the operator precedence without writing a rule for each combination of operator, so it’s a bit of a pain. But who doesn’t love reverse Polish notation anyway? :slightly_smiling_face:

5 Likes

Very cool from an HP fan.

2 Likes

11 posts were split to a new topic: RPN Calculators