dc

Tiny reverse polish desk calculator
Log | Files | Refs | README | LICENSE

commit cbb5cc555b6dcaed9f5740c33ff3d309721dfd18
parent 44c38c222b23f23563dc9c9b2d9399d89e32621f
Author: Byron Torres <b@torresjrjr.com>
Date:   Tue, 23 Nov 2021 00:07:58 +0000

scan numbers

Diffstat:
Mdc.ha | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 60 insertions(+), 16 deletions(-)

diff --git a/dc.ha b/dc.ha @@ -1,3 +1,4 @@ +use ascii; use bufio; use encoding::utf8; use fmt; @@ -5,6 +6,7 @@ use getopt; use io; use os; use strconv; +use strings; let stack: []f64 = []; @@ -44,38 +46,36 @@ export fn main() void = { yield r; }; + if (ascii::isdigit(r)) { + bufio::unreadrune(os::stdin, r); + const el = scan_number(); + push(el); + continue; + }; + switch (r) { - case '1' => - const el = 1f64; - append(stack, el); case '+' => if (len(stack) < 2) { fmt::errorln("dc: stack has too few elements")?; continue; }; - const a = stack[len(stack) - 2]; - const b = stack[len(stack) - 1]; - const sum = a + b; - delete(stack[len(stack) - 1]); - delete(stack[len(stack) - 1]); - append(stack, sum); + const a = pop(); + const b = pop(); + push(a + b); case '-' => if (len(stack) < 2) { fmt::errorln("dc: stack has too few elements")?; continue; }; - const a = stack[len(stack) - 2]; - const b = stack[len(stack) - 1]; - const diff = a - b; - delete(stack[len(stack) - 1]); - delete(stack[len(stack) - 1]); - append(stack, diff); + const a = pop(); + const b = pop(); + push(a - b); case 'p' => if (len(stack) == 0) { fmt::errorln("dc: stack has no elements")?; continue; }; - const el = stack[len(stack) - 1]; + const el = peek(); fmt::println(el)?; case => continue; @@ -87,3 +87,47 @@ export fn main() void = { getopt::printusage(os::stderr, os::args[0], help); os::exit(1); }; + +fn scan_number() f64 = { + let num: []u8 = []; + defer free(num); + for (true) { + const r = match (bufio::scanrune(os::stdin)) { + case utf8::invalid => + fmt::fatal("dc: invalid utf8 input"); + case io::error => + fmt::fatal("dc: IO error"); + case io::EOF => + yield ' '; + case r: rune => + yield r; + }; + + if (ascii::isdigit(r)) { + append(num, r: u32: u8); + } else { + bufio::unreadrune(os::stdin, r); + match (strconv::stof64(strings::fromutf8(num))) { + case (strconv::invalid | strconv::overflow) => + abort("dc: invalid numerical input"); + case n: f64 => + return n; + }; + }; + }; + abort("Unreachable"); +}; + +fn pop() f64 = { + const a = stack[len(stack) - 1]; + delete(stack[len(stack) - 1]); + return a; +}; + +fn push(el: f64) void = { + append(stack, el); +}; + +fn peek() f64 = { + return stack[len(stack) - 1]; +};