summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-23 22:28:19 +0200
committerPaul Buetow <paul@buetow.org>2026-03-23 22:28:19 +0200
commitfb3ace9c0548906eff67504368a7a40ef2f980a8 (patch)
tree6a39b9aeab8eebda76da4f02d76997ae532b6046
parenta1cb1e1395c2e94d6b427213915c6d6ae5709d20 (diff)
Refactor rpn.go to reduce cognitive complexity
-rw-r--r--internal/rpn/rpn.go208
1 files changed, 122 insertions, 86 deletions
diff --git a/internal/rpn/rpn.go b/internal/rpn/rpn.go
index 16e68d0..9b9f4c5 100644
--- a/internal/rpn/rpn.go
+++ b/internal/rpn/rpn.go
@@ -224,93 +224,11 @@ func (r *RPN) evaluate(tokens []string) (string, error) {
continue
}
- // Check for operators and special commands
- switch token {
- case "+":
- if err := r.ops.Add(stack); err != nil {
- return "", fmt.Errorf("operator +: %w", err)
- }
- case "-":
- if err := r.ops.Subtract(stack); err != nil {
- return "", fmt.Errorf("operator -: %w", err)
- }
- case "*":
- if err := r.ops.Multiply(stack); err != nil {
- return "", fmt.Errorf("operator *: %w", err)
- }
- case "/":
- if err := r.ops.Divide(stack); err != nil {
- return "", fmt.Errorf("operator /: %w", err)
- }
- case "^":
- if err := r.ops.Power(stack); err != nil {
- return "", fmt.Errorf("operator ^: %w", err)
- }
- case "%":
- if err := r.ops.Modulo(stack); err != nil {
- return "", fmt.Errorf("operator %%: %w", err)
- }
- case "[+]":
- if err := r.ops.HyperAdd(stack); err != nil {
- return "", fmt.Errorf("hyperoperator [+]: %w", err)
- }
- case "[-]":
- if err := r.ops.HyperSubtract(stack); err != nil {
- return "", fmt.Errorf("hyperoperator [-]: %w", err)
- }
- case "[*]":
- if err := r.ops.HyperMultiply(stack); err != nil {
- return "", fmt.Errorf("hyperoperator [*]: %w", err)
- }
- case "[/]":
- if err := r.ops.HyperDivide(stack); err != nil {
- return "", fmt.Errorf("hyperoperator [/]: %w", err)
- }
- case "[^]":
- if err := r.ops.HyperPower(stack); err != nil {
- return "", fmt.Errorf("hyperoperator [^]: %w", err)
- }
- case "[%]":
- if err := r.ops.HyperModulo(stack); err != nil {
- return "", fmt.Errorf("hyperoperator [%%]: %w", err)
- }
- case "dup":
- if err := r.ops.Dup(stack); err != nil {
- return "", fmt.Errorf("dup: %w", err)
- }
- case "swap":
- if err := r.ops.Swap(stack); err != nil {
- return "", fmt.Errorf("swap: %w", err)
- }
- case "pop":
- if err := r.ops.Pop(stack); err != nil {
- return "", fmt.Errorf("pop: %w", err)
- }
- case "show", "showstack", "print":
- result, err := r.ops.Show(stack)
- if err != nil {
- return "", fmt.Errorf("show: %w", err)
- }
+ // Handle special operators and commands
+ if result, err := r.handleOperator(stack, token, i); err != nil {
+ return "", err
+ } else if result != "" {
return result, nil
- case "vars":
- result, err := r.ops.ListVariables()
- if err != nil {
- return "", fmt.Errorf("vars: %w", err)
- }
- return result, nil
- case "clear":
- r.ops.ClearVariables()
- return "All variables cleared", nil
- case "d":
- return "", fmt.Errorf("'d' command not supported as standalone token")
- default:
- // Check if it's a variable reference (push its value)
- val, exists := r.vars.GetVariable(token)
- if exists {
- stack.Push(val)
- } else {
- return "", fmt.Errorf("unknown token '%s' at position %d", token, i)
- }
}
}
@@ -341,6 +259,124 @@ func (r *RPN) evaluate(tokens []string) (string, error) {
return fmt.Sprintf("%.10g", val), nil
}
+// handleOperator handles operators and special commands
+func (r *RPN) handleOperator(stack *Stack, token string, tokenIndex int) (string, error) {
+ // Handle hyperoperators
+ if isHyperOperator(token) {
+ if err := r.handleHyperOperator(stack, token); err != nil {
+ return "", err
+ }
+ return "", nil
+ }
+
+ // Handle standard operators
+ switch token {
+ case "+":
+ if err := r.ops.Add(stack); err != nil {
+ return "", fmt.Errorf("operator +: %w", err)
+ }
+ case "-":
+ if err := r.ops.Subtract(stack); err != nil {
+ return "", fmt.Errorf("operator -: %w", err)
+ }
+ case "*":
+ if err := r.ops.Multiply(stack); err != nil {
+ return "", fmt.Errorf("operator *: %w", err)
+ }
+ case "/":
+ if err := r.ops.Divide(stack); err != nil {
+ return "", fmt.Errorf("operator /: %w", err)
+ }
+ case "^":
+ if err := r.ops.Power(stack); err != nil {
+ return "", fmt.Errorf("operator ^: %w", err)
+ }
+ case "%":
+ if err := r.ops.Modulo(stack); err != nil {
+ return "", fmt.Errorf("operator %%: %w", err)
+ }
+ case "dup":
+ if err := r.ops.Dup(stack); err != nil {
+ return "", fmt.Errorf("dup: %w", err)
+ }
+ case "swap":
+ if err := r.ops.Swap(stack); err != nil {
+ return "", fmt.Errorf("swap: %w", err)
+ }
+ case "pop":
+ if err := r.ops.Pop(stack); err != nil {
+ return "", fmt.Errorf("pop: %w", err)
+ }
+ case "show", "showstack", "print":
+ result, err := r.ops.Show(stack)
+ if err != nil {
+ return "", fmt.Errorf("show: %w", err)
+ }
+ return result, nil
+ case "vars":
+ result, err := r.ops.ListVariables()
+ if err != nil {
+ return "", fmt.Errorf("vars: %w", err)
+ }
+ return result, nil
+ case "clear":
+ r.ops.ClearVariables()
+ return "All variables cleared", nil
+ case "d":
+ return "", fmt.Errorf("'d' command not supported as standalone token")
+ default:
+ // Check if it's a variable reference (push its value)
+ val, exists := r.vars.GetVariable(token)
+ if exists {
+ stack.Push(val)
+ } else {
+ return "", fmt.Errorf("unknown token '%s' at position %d", token, tokenIndex)
+ }
+ }
+ return "", nil
+}
+
+// isHyperOperator checks if the token is a hyperoperator
+func isHyperOperator(token string) bool {
+ switch token {
+ case "[+]", "[-]", "[*]", "[/]", "[^]", "[%]":
+ return true
+ default:
+ return false
+ }
+}
+
+// handleHyperOperator handles hyperoperators
+func (r *RPN) handleHyperOperator(stack *Stack, token string) error {
+ switch token {
+ case "[+]":
+ if err := r.ops.HyperAdd(stack); err != nil {
+ return fmt.Errorf("hyperoperator [+]: %w", err)
+ }
+ case "[-]":
+ if err := r.ops.HyperSubtract(stack); err != nil {
+ return fmt.Errorf("hyperoperator [-]: %w", err)
+ }
+ case "[*]":
+ if err := r.ops.HyperMultiply(stack); err != nil {
+ return fmt.Errorf("hyperoperator [*]: %w", err)
+ }
+ case "[/]":
+ if err := r.ops.HyperDivide(stack); err != nil {
+ return fmt.Errorf("hyperoperator [/]: %w", err)
+ }
+ case "[^]":
+ if err := r.ops.HyperPower(stack); err != nil {
+ return fmt.Errorf("hyperoperator [^]: %w", err)
+ }
+ case "[%]":
+ if err := r.ops.HyperModulo(stack); err != nil {
+ return fmt.Errorf("hyperoperator [%%]: %w", err)
+ }
+ }
+ return nil
+}
+
// handleAssignment checks if the input is an assignment format and handles it.
// Returns (result string, isAssignment bool, error error).
func (r *RPN) handleAssignment(input string) (string, bool, error) {