diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-23 22:28:19 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-23 22:28:19 +0200 |
| commit | fb3ace9c0548906eff67504368a7a40ef2f980a8 (patch) | |
| tree | 6a39b9aeab8eebda76da4f02d76997ae532b6046 | |
| parent | a1cb1e1395c2e94d6b427213915c6d6ae5709d20 (diff) | |
Refactor rpn.go to reduce cognitive complexity
| -rw-r--r-- | internal/rpn/rpn.go | 208 |
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) { |
