From 3516ab494570f077df967bfe1222acc0dfcdf5da Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Fri, 28 Jul 2023 20:46:24 -0230 Subject: arithmetic operators --- calculator.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- ui.go | 6 ++++-- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/calculator.go b/calculator.go index 08193b4..d2371b7 100644 --- a/calculator.go +++ b/calculator.go @@ -1,6 +1,9 @@ package main -import "strconv" +import ( + "fmt" + "strconv" +) type Stack []float64 @@ -9,18 +12,61 @@ type Calculator struct { buf string } -// add performs addition when the user inputs the '+' operator. -func (c *Calculator) add() { +// performOp performs the specified arithmetic operation and returns nil or +// OpError if op is not a valid operator. +func (c *Calculator) performOp(op byte) error { if len(c.stack) < 1 { - return + return nil } + + fn, err := parseOp(op) + if err != nil { + return err + } + if con := parseConstant(c.buf); con != nil { - c.stack[len(c.stack)-1] += *con - } else if f, err := strconv.ParseFloat(c.buf, 64); err == nil { - c.stack[len(c.stack)-1] += f + fn(&c.stack[len(c.stack)-1], *con) + } else if fl, err := strconv.ParseFloat(c.buf, 64); err == nil { + fn(&c.stack[len(c.stack)-1], fl) } else if len(c.stack) > 1 { - c.stack[len(c.stack)-2] += c.stack[len(c.stack)-1] + fn(&c.stack[len(c.stack)-2], c.stack[len(c.stack)-1]) c.stack = c.stack[:len(c.stack)-1] } c.buf = "" + return nil +} + +// parseOp returns a closure that performs the specified arithmetic operation, +// or OpError if op is not a valid operator. +func parseOp(op byte) (func(lhs *float64, rhs float64), error) { + switch op { + case '+': + return func(lhs *float64, rhs float64) { *lhs += rhs }, nil + case '-': + return func(lhs *float64, rhs float64) { *lhs -= rhs }, nil + case '*': + return func(lhs *float64, rhs float64) { *lhs *= rhs }, nil + case '/': + return func(lhs *float64, rhs float64) { + if rhs != 0 { + *lhs /= rhs + } + }, nil + case '%': + return func(lhs *float64, rhs float64) { + if rhs != 0 { + *lhs = float64(int64(*lhs) % int64(rhs)) + } + }, nil + } + return nil, OpError{op} +} + +// OpError records an invalid arithmetic operator. +type OpError struct { + c byte +} + +func (e OpError) Error() string { + return fmt.Sprintf("invalid operator: %c", e.c) } diff --git a/ui.go b/ui.go index 931e8a5..5996a9c 100644 --- a/ui.go +++ b/ui.go @@ -37,8 +37,10 @@ func (ui UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg.String() { case "ctrl+c", "Q": return ui, tea.Quit - case "+": - ui.calc.add() + case "+", "-", "*", "/", "%": + if err := ui.calc.performOp(msg.String()[0]); err != nil { + panic(err) + } case "backspace": if len(ui.calc.buf) > 0 { ui.calc.buf = ui.calc.buf[:len(ui.calc.buf)-1] -- cgit v1.2.3