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?

5 Likes

Very cool from an HP fan.

2 Likes

11 posts were split to a new topic: RPN Calculators