rpn(1) - reverse polish notation #21

Closed
opened 2023-12-29 20:46:50 -07:00 by trinity · 14 comments
Owner
Usage: rpn (-i) (math...)

e.g.

$ rpn 2 1 -
1
$ rpn "$(wc -l </etc/motd)" 5 +
10
$ rpn 1 2 3 4 + - * # 1 + 2 - 3 * 4
-9
$ rpn 1 2 3 4 + * + # 1 + 2 * (3 + 4)
15

A reverse polish notation calculator. -i reads arguments from standard input.

``` Usage: rpn (-i) (math...) ``` e.g. ```sh $ rpn 2 1 - 1 $ rpn "$(wc -l </etc/motd)" 5 + 10 $ rpn 1 2 3 4 + - * # 1 + 2 - 3 * 4 -9 $ rpn 1 2 3 4 + * + # 1 + 2 * (3 + 4) 15 ``` A reverse polish notation calculator. `-i` reads arguments from standard input.
Author
Owner

Some questions regarding design:

  • How should numbers be represented internally? (float, fixed point, integer only)
  • What operations should be supported?
    • obviously +, -, *
    • %?
    • &, |, ^, ~?
    • Should / be division or floor division? (4 / 3 = 1.333... versus 4 / 3 = 1)
      • \?
    • Should multi-character tokens be allowed (e.g. ** for exponentiation)?
  • How should the stack be represented internally?
Some questions regarding design: - How should numbers be represented internally? (float, fixed point, integer only) - What operations should be supported? - obviously `+`, `-`, `*` - `%`? - `&`, `|`, `^`, `~`? - Should `/` be division or floor division? (4 / 3 = 1.333... versus 4 / 3 = 1) - `\`? - Should multi-character tokens be allowed (e.g. `**` for exponentiation)? - How should the stack be represented internally?
Owner

This is an option for a reverse polish notation library in Rust we could use/distribute:
https://github.com/lillycat332/dc-rs

This is an option for a reverse polish notation library in Rust we could use/distribute: https://github.com/lillycat332/dc-rs
Author
Owner

My idea for interaction is that by default, rpn(1) prints the closest value on the stack at the end of argument acceptance. If run in interactive mode, rpn(1) prints the closest value on the stack after every token:

$ rpn -i
3
3
4
4
+
7
5
5
+
12

This may be more clear presented like so:

$ printf '%s\n%s\n%s\n%s\n%s\n' 3 4 + 5 + | rpn -i
3
4
7
5
12

Whereas in arguments mode:

$ rpn 3 4 + 5 +
12

I'm not a big fan of dc(1p) or bc(1p) and needing to do stuff like

$ printf '5\n4\n+\np\n' | dc

Or whatever to get them to work; specifically the p command which should really be the default (why wouldn't you want to see the output of computation?).

My idea for interaction is that by default, rpn(1) prints the closest value on the stack at the end of argument acceptance. If run in interactive mode, rpn(1) prints the closest value on the stack after every token: ```sh $ rpn -i 3 3 4 4 + 7 5 5 + 12 ``` This may be more clear presented like so: ```sh $ printf '%s\n%s\n%s\n%s\n%s\n' 3 4 + 5 + | rpn -i 3 4 7 5 12 ``` Whereas in arguments mode: ```sh $ rpn 3 4 + 5 + 12 ``` I'm not a big fan of dc(1p) or bc(1p) and needing to do stuff like ```sh $ printf '5\n4\n+\np\n' | dc ``` Or whatever to get them to work; specifically the `p` command which should really be the default (why wouldn't you want to see the output of computation?).
trinity added the
enhancement
label 2023-12-30 09:00:17 -07:00
emma added the
help wanted
label 2023-12-30 14:40:53 -07:00
emma changed title from rpn(1) - reverse polish notation to `rpn(1)` - reverse polish notation 2024-01-23 15:08:11 -07:00
Author
Owner

I'm deciding, tentatively, with comments still desired:

  • integer-only; no decimals supported
  • +, - - addition and subtraction
  • *, ** - multiplication and exponentiation (see Python)
  • ^, |, &, ~ - bitwise operators (see C)
  • &&, ||, ! - boolean operators (see C)
  • //, % - floor division and modulus (see Python)
  • ? - flow control (see blang and below)
  • >, <, ==, >=, <= - comparisons (see C)
  • : - duplicate (see below)

? pops the stack and, if the value is 0, does nothing, otherwise discards the next token in the program.

: pops the stack and pushes the value twice.

There's no ability to return to any previous part of the program, by design; this is a calculator, not a language, and complex programs shouldn't be written in it.

Numbers are entered formatted 0xN for hexadecimal, 0oN for octal, 0bN for binary, and traditionally for decimal, and displayed as decimal only.

It's tempting to facilitate use of environment variables but I don't see an elegant way to do so and the functionality already exists in the shell. Program-local variables too, because they can't be implemented elegantly.

I'm deciding, tentatively, with comments still desired: - integer-only; no decimals supported - `+`, `-` - addition and subtraction - `*`, `**` - multiplication and exponentiation (see Python) - `^`, `|`, `&`, `~` - bitwise operators (see C) - `&&`, `||`, `!` - boolean operators (see C) - `//`, `%` - floor division and modulus (see Python) - `?` - flow control (see blang and below) - `>`, `<`, `==`, `>=`, `<=` - comparisons (see C) - `:` - duplicate (see below) `?` pops the stack and, if the value is 0, does nothing, otherwise discards the next token in the program. `:` pops the stack and pushes the value twice. There's no ability to return to any previous part of the program, by design; this is a calculator, not a language, and complex programs shouldn't be written in it. Numbers are entered formatted `0xN` for hexadecimal, `0oN` for octal, `0bN` for binary, and traditionally for decimal, and displayed as decimal only. It's tempting to facilitate use of environment variables but I don't see an elegant way to do so and the functionality already exists in the shell. Program-local variables too, because they can't be implemented elegantly.
emma self-assigned this 2024-01-31 23:15:18 -07:00
emma removed the
help wanted
label 2024-01-31 23:15:26 -07:00
Author
Owner

Emma is working on this in #36.

Emma is working on this in #36.
Owner

When writing npc 1 2 * the shell automatically takes the asterisk as a wildard and it must be quoted. Should we do anything about this (i.e. have x be the multiplication operator when parsing arguments instead of stdin)?

When writing `npc 1 2 *` the shell automatically takes the asterisk as a wildard and it must be quoted. Should we do anything about this (i.e. have `x` be the multiplication operator when parsing arguments instead of stdin)?
Owner
  • ^, |, &, ~ - bitwise operators (see C)
  • &&, ||, ! - boolean operators (see C)

What purpose would these serve here?

  • >, <, ==, >=, <= - comparisons (see C)

intcmp(1)?

> - `^`, `|`, `&`, `~` - bitwise operators (see C) > - `&&`, `||`, `!` - boolean operators (see C) What purpose would these serve here? > - `>`, `<`, `==`, `>=`, `<=` - comparisons (see C) `intcmp(1)`?
Author
Owner

When writing npc 1 2 * the shell automatically takes the asterisk as a wildard and it must be quoted. Should we do anything about this (i.e. have x be the multiplication operator when parsing arguments instead of stdin)?

Let's just make it need to be quoted. I know you made Unicode multiplication runes work too so that's an option.

> When writing `npc 1 2 *` the shell automatically takes the asterisk as a wildard and it must be quoted. Should we do anything about this (i.e. have `x` be the multiplication operator when parsing arguments instead of stdin)? Let's just make it need to be quoted. I know you made Unicode multiplication runes work too so that's an option.
Author
Owner
  • ^, |, &, ~ - bitwise operators (see C)
  • &&, ||, ! - boolean operators (see C)

What purpose would these serve here?

  • >, <, ==, >=, <= - comparisons (see C)

intcmp(1)?

Bitwise operators are very useful for programming and I've used bitwise operations in calculators in the past for making intcmp(1) and some UTF-8 implementation stuff.

Boolean operators might be useful for scripting. Not scripting in-calculator but for the scenario where someone wants the calc to print [zero] or [a valid answer] or something. Same with comparisons. These are all niceties though and not important.

> > - `^`, `|`, `&`, `~` - bitwise operators (see C) > > - `&&`, `||`, `!` - boolean operators (see C) > > What purpose would these serve here? > > > - `>`, `<`, `==`, `>=`, `<=` - comparisons (see C) > > `intcmp(1)`? Bitwise operators are very useful for programming and I've used bitwise operations in calculators in the past for making intcmp(1) and some UTF-8 implementation stuff. Boolean operators might be useful for scripting. Not scripting in-calculator but for the scenario where someone wants the calc to print [zero] or [a valid answer] or something. Same with comparisons. These are all niceties though and not important.
Owner

After a conversation with Trinity, we’ve decided rpn is feature-complete as it is. I’ll get it merged tomorrow.

After a conversation with Trinity, we’ve decided rpn is feature-complete as it is. I’ll get it merged tomorrow.
Owner

Actually, I wanted to implement comparisons and then I’ll merge it.

Actually, I wanted to implement comparisons and then I’ll merge it.
Author
Owner

Comparisons might be tricky because it's hard to compare floating point numbers. 0.3 doesn't always equal 0.3 bit-by-bit. Maybe it would be better to have a ~= for equality ± some value and then === for strict exact equality.

Comparisons might be tricky because it's hard to compare floating point numbers. 0.3 doesn't always equal 0.3 bit-by-bit. Maybe it would be better to have a `~=` for equality ± some value and then `===` for strict exact equality.
Author
Owner

We discussed bitwise operators not being useful for this calculator as it's floating point. I'm working on another RPN implementation (srpn(1) - simpler rpn) that might be nice for an Extras repository that will be fixed-point to support bitwise operations and non-decimal bases.

We discussed bitwise operators not being useful for this calculator as it's floating point. I'm working on another RPN implementation (srpn(1) - simpler rpn) that might be nice for an Extras repository that will be fixed-point to support bitwise operations and non-decimal bases.
Owner

I’ll leave out comparisons. I think it’s basically done, then.

I’ll leave out comparisons. I think it’s basically done, then.
emma closed this issue 2024-02-07 19:57:16 -07:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: bonsai/harakit#21
No description provided.