diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-24 13:52:54 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-24 13:52:54 +0300 |
| commit | ecadd6b9e6b6691ae1d1ea7340b08a8fe7eff883 (patch) | |
| tree | 459d75e17aaaac9e33b8a4ba2221d027e8c11626 | |
| parent | 6d90062cb1b3f00f6fc1e5db942a153580b196ee (diff) | |
refactor(repl): extract evalWithStackRestore helper (task bj)
Factor out the repeated save-restore-evaluate pattern from
RPNHandler.Handle() into a single helper method so the stack
is always restored on parse errors, across all call sites.
| -rw-r--r-- | internal/repl/handlers.go | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/internal/repl/handlers.go b/internal/repl/handlers.go index b0e7ad6..c2f8af5 100644 --- a/internal/repl/handlers.go +++ b/internal/repl/handlers.go @@ -133,6 +133,18 @@ type RPNHandler struct { BaseHandler } +// evalWithStackRestore evaluates an RPN expression, restoring the stack on error +// so that a failed parse never corrupts the user's stack. +func (h *RPNHandler) evalWithStackRestore(repl *REPL, input string) (string, error) { + savedStack := repl.rpnState.rpnCalc.GetCurrentStack() + result, err := repl.rpnState.rpnCalc.ParseAndEvaluate(input) + if err != nil { + repl.rpnState.rpnCalc.SetCurrentStack(savedStack) + return "", err + } + return result, nil +} + // Handle processes RPN commands and expressions. // It handles: // - Commands with "rpn" or "calc" prefix @@ -153,12 +165,8 @@ func (h *RPNHandler) Handle(repl *REPL, input string) (output string, handled bo // Extract the expression after rpn/calc rest := strings.TrimSpace(strings.TrimPrefix(input, strings.SplitN(input, " ", 2)[0])) - // Save stack state so a failed expression doesn't corrupt it - savedStack := repl.rpnState.rpnCalc.GetCurrentStack() - - result, err := repl.rpnState.rpnCalc.ParseAndEvaluate(rest) + result, err := h.evalWithStackRestore(repl, rest) if err != nil { - repl.rpnState.rpnCalc.SetCurrentStack(savedStack) return "", true, err } return result, true, nil @@ -168,13 +176,8 @@ func (h *RPNHandler) Handle(repl *REPL, input string) (output string, handled bo if repl.rpnState != nil { // Check if input looks like RPN (contains spaces or is a single known operator) if strings.Contains(input, " ") { - // Save stack state so a failed expression doesn't corrupt it - savedStack := repl.rpnState.rpnCalc.GetCurrentStack() - - result, err := repl.rpnState.rpnCalc.ParseAndEvaluate(input) + result, err := h.evalWithStackRestore(repl, input) if err != nil { - // Restore the stack to its state before the failed expression - repl.rpnState.rpnCalc.SetCurrentStack(savedStack) return "", true, err } return result, true, nil @@ -194,14 +197,14 @@ func (h *RPNHandler) Handle(repl *REPL, input string) (output string, handled bo } // Numbers and symbols (:x) are handled by ParseAndEvaluate if _, err := strconv.ParseFloat(token, 64); err == nil { - result, err := repl.rpnState.rpnCalc.ParseAndEvaluate(token) + result, err := h.evalWithStackRestore(repl, token) if err != nil { return "", true, err } return result, true, nil } if len(token) > 0 && token[0] == ':' { - result, err := repl.rpnState.rpnCalc.ParseAndEvaluate(token) + result, err := h.evalWithStackRestore(repl, token) if err != nil { return "", true, err } |
