diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-24 18:50:00 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-24 18:50:00 +0300 |
| commit | dc89fa2bbcdea7c8847828f64be5e46ddded33fb (patch) | |
| tree | 67dd57478d39d9e75ccfcb576f5651bf53896379 | |
| parent | 4188db97bcb771c1c8790ddbac2db3f9ee8884c3 (diff) | |
fix(rpn): change variadic NewRPN/NewOperations to single optional MetricReader (task ok)
| -rw-r--r-- | cmd/gt/main.go | 2 | ||||
| -rw-r--r-- | internal/repl/concurrent_test.go | 10 | ||||
| -rw-r--r-- | internal/repl/repl.go | 2 | ||||
| -rw-r--r-- | internal/repl/repl_test.go | 24 | ||||
| -rw-r--r-- | internal/repl/rpnstate_test.go | 10 | ||||
| -rw-r--r-- | internal/rpn/assignment_test.go | 52 | ||||
| -rw-r--r-- | internal/rpn/boolean_test.go | 8 | ||||
| -rw-r--r-- | internal/rpn/compare_metric_test.go | 8 | ||||
| -rw-r--r-- | internal/rpn/constants_test.go | 26 | ||||
| -rw-r--r-- | internal/rpn/custom_metric_test.go | 24 | ||||
| -rw-r--r-- | internal/rpn/metric_test.go | 18 | ||||
| -rw-r--r-- | internal/rpn/operations.go | 6 | ||||
| -rw-r--r-- | internal/rpn/operations_fastpower_test.go | 2 | ||||
| -rw-r--r-- | internal/rpn/operations_hyper_test.go | 6 | ||||
| -rw-r--r-- | internal/rpn/operations_metric_cmd_test.go | 50 | ||||
| -rw-r--r-- | internal/rpn/operations_stack_test.go | 20 | ||||
| -rw-r--r-- | internal/rpn/operations_test.go | 96 | ||||
| -rw-r--r-- | internal/rpn/rpn_state.go | 4 | ||||
| -rw-r--r-- | internal/rpn/rpn_state_test.go | 16 | ||||
| -rw-r--r-- | internal/rpn/rpn_test.go | 62 |
20 files changed, 223 insertions, 223 deletions
diff --git a/cmd/gt/main.go b/cmd/gt/main.go index 85292fb..3203c34 100644 --- a/cmd/gt/main.go +++ b/cmd/gt/main.go @@ -170,7 +170,7 @@ func runREPL() error { // making it suitable for one-off calculations. func runRPN(input string) (string, error) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) // Strip "rpn " or "calc " prefix if present input = strings.TrimSpace(input) diff --git a/internal/repl/concurrent_test.go b/internal/repl/concurrent_test.go index 501b363..62bf7dc 100644 --- a/internal/repl/concurrent_test.go +++ b/internal/repl/concurrent_test.go @@ -15,7 +15,7 @@ func TestConcurrentExecutor(t *testing.T) { go func(id int) { defer wg.Done() vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -37,7 +37,7 @@ func TestConcurrentRPN(t *testing.T) { go func(id int) { defer wg.Done() vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) _, _ = rpnCalc.ParseAndEvaluate("3 4 +") }(i) } @@ -52,7 +52,7 @@ func TestConcurrentRatModeToggle(t *testing.T) { go func(id int) { defer wg.Done() vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -74,7 +74,7 @@ func TestConcurrentExecutorAndRPN(t *testing.T) { go func(id int) { defer wg.Done() vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -87,7 +87,7 @@ func TestConcurrentExecutorAndRPN(t *testing.T) { go func(id int) { defer wg.Done() vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) _, _ = rpnCalc.ParseAndEvaluate("3 4 +") }(i) } diff --git a/internal/repl/repl.go b/internal/repl/repl.go index 2ecd9ea..451b6c3 100644 --- a/internal/repl/repl.go +++ b/internal/repl/repl.go @@ -179,7 +179,7 @@ func NewREPL(executor func(string), completer func() []string, logWriter io.Writ fmt.Printf("Warning: Could not load saved variables: %v\n", err) } - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpnState := NewRPNState(vars, rpnCalc) repl := &REPL{ diff --git a/internal/repl/repl_test.go b/internal/repl/repl_test.go index f8e22a2..a7fd2f8 100644 --- a/internal/repl/repl_test.go +++ b/internal/repl/repl_test.go @@ -18,7 +18,7 @@ func createTestREPL() *REPL { historyMgr: NewHistoryManager(".gt_history"), signalHandler: NewSignalHandler(), commandChain: NewCommandChain(), - rpnState: &RPNState{vars: vars, rpnCalc: rpn.NewRPN(vars)}, + rpnState: &RPNState{vars: vars, rpnCalc: rpn.NewRPN(vars, nil)}, } } @@ -186,7 +186,7 @@ func TestRunRPN(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) input := strings.TrimSpace(tt.input) if strings.HasPrefix(input, "rpn ") { @@ -408,7 +408,7 @@ func TestExecutorWithCalcPrefixMixed(t *testing.T) { // TestExecutorWithRatModeOn tests that rat on works with fresh REPL func TestExecutorWithRatModeOn(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -425,7 +425,7 @@ func TestExecutorWithRatModeOn(t *testing.T) { // TestExecutorWithRatModeOff tests that rat off works with fresh REPL func TestExecutorWithRatModeOff(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -442,7 +442,7 @@ func TestExecutorWithRatModeOff(t *testing.T) { // TestExecutorWithRatModeToggle tests that rat toggle works with fresh REPL func TestExecutorWithRatModeToggle(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -487,7 +487,7 @@ func TestIsBuiltinCommandWithSubcommandHelp(t *testing.T) { // TestExecutorWithAssignmentRight tests := and =: operators func TestExecutorWithAssignmentRight(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -520,7 +520,7 @@ func TestExecutorWithAssignmentRight(t *testing.T) { // TestExecutorWithAssignmentAfterCalculation tests assignment after a calculation func TestExecutorWithAssignmentAfterCalculation(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -543,7 +543,7 @@ func TestExecutorWithAssignmentAfterCalculation(t *testing.T) { // TestExecutorWithIncrementalAssignment tests that assignment works after a calculation with separate commands func TestExecutorWithIncrementalAssignment(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -570,7 +570,7 @@ func TestExecutorWithIncrementalAssignment(t *testing.T) { // TestExecutorWithSimpleIncrementalAssignment tests x =: after 2 in REPL func TestExecutorWithSimpleIncrementalAssignment(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -596,7 +596,7 @@ func TestExecutorWithSimpleIncrementalAssignment(t *testing.T) { // TestExecutorWithExactUserScenario tests the exact user scenario: 2 then x =: func TestExecutorWithExactUserScenario(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -628,7 +628,7 @@ func TestExecutorWithExactUserScenario(t *testing.T) { // TestExecutorWithExactUserScenarioWithOutput tests that x =: assigns and shows result func TestExecutorWithExactUserScenarioWithOutput(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), @@ -660,7 +660,7 @@ func TestExecutorWithExactUserScenarioWithOutput(t *testing.T) { // TestExecutorWithExactUserScenarioDirect simulates REPL input flow func TestExecutorWithExactUserScenarioDirect(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) rpl := &REPL{ ttyChecker: &TTYChecker{}, historyMgr: NewHistoryManager(".gt_history"), diff --git a/internal/repl/rpnstate_test.go b/internal/repl/rpnstate_test.go index 1d54dea..80c7f65 100644 --- a/internal/repl/rpnstate_test.go +++ b/internal/repl/rpnstate_test.go @@ -14,7 +14,7 @@ import ( func TestNewRPNState(t *testing.T) { vars := rpn.NewVariables() - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) state := NewRPNState(vars, rpnCalc) if state == nil { t.Fatal("NewRPNState() returned nil") @@ -25,7 +25,7 @@ func TestRPNStateLoadVariablesEmpty(t *testing.T) { // When varStoreFile is empty, LoadVariables should return nil state := &RPNState{ vars: rpn.NewVariables(), - rpnCalc: rpn.NewRPN(rpn.NewVariables()), + rpnCalc: rpn.NewRPN(rpn.NewVariables(), nil), varStoreFile: "", } err := state.LoadVariables() @@ -37,7 +37,7 @@ func TestRPNStateLoadVariablesEmpty(t *testing.T) { func TestRPNStateSaveVariablesEmpty(t *testing.T) { state := &RPNState{ vars: rpn.NewVariables(), - rpnCalc: rpn.NewRPN(rpn.NewVariables()), + rpnCalc: rpn.NewRPN(rpn.NewVariables(), nil), varStoreFile: "", } err := state.SaveVariables() @@ -70,7 +70,7 @@ func TestRPNStateSaveLoadRoundTrip(t *testing.T) { vars.SetVariable("x", 42.0) vars.SetVariable("y", 3.14) - rpnCalc := rpn.NewRPN(vars) + rpnCalc := rpn.NewRPN(vars, nil) state := &RPNState{ vars: vars, rpnCalc: rpnCalc, @@ -91,7 +91,7 @@ func TestRPNStateSaveLoadRoundTrip(t *testing.T) { newVars := rpn.NewVariables() newState := &RPNState{ vars: newVars, - rpnCalc: rpn.NewRPN(newVars), + rpnCalc: rpn.NewRPN(newVars, nil), varStoreFile: varStorePath, } diff --git a/internal/rpn/assignment_test.go b/internal/rpn/assignment_test.go index 82d4a12..f9f4a3e 100644 --- a/internal/rpn/assignment_test.go +++ b/internal/rpn/assignment_test.go @@ -11,7 +11,7 @@ import ( // TestAssignmentStandard tests standard assignment 'x 5 =' func TestAssignmentStandard(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("x 5 =") if err != nil { @@ -33,7 +33,7 @@ func TestAssignmentStandard(t *testing.T) { // TestAssignmentRight tests right assignment '5 x :=' func TestAssignmentRight(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("5 x :=") if err != nil { @@ -55,7 +55,7 @@ func TestAssignmentRight(t *testing.T) { // TestAssignmentLeft tests left assignment '5 x =:' func TestAssignmentLeft(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("5 x =:") if err != nil { @@ -77,7 +77,7 @@ func TestAssignmentLeft(t *testing.T) { // TestAssignmentReassignment tests variable reassignment func TestAssignmentReassignment(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("x 5 =") if err != nil { @@ -104,7 +104,7 @@ func TestAssignmentReassignment(t *testing.T) { // TestAssignmentInExpression tests assignment used in an expression func TestAssignmentInExpression(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // 'x 5 = x 2 +' should assign x=5, then push x and 2, then add: 5 + 2 = 7 result, err := rpn.ParseAndEvaluate("x 5 = x 2 +") @@ -119,7 +119,7 @@ func TestAssignmentInExpression(t *testing.T) { // TestAssignmentMultipleVariables tests multiple variable assignments func TestAssignmentMultipleVariables(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, _ = rpn.ParseAndEvaluate("x 5 =") _, _ = rpn.ParseAndEvaluate("y 10 =") @@ -146,7 +146,7 @@ func TestAssignmentMultipleVariables(t *testing.T) { // TestAssignmentArithmeticWithVariable tests arithmetic using assigned variable func TestAssignmentArithmeticWithVariable(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, _ = rpn.ParseAndEvaluate("x 5 =") @@ -163,7 +163,7 @@ func TestAssignmentArithmeticWithVariable(t *testing.T) { // TestAssignmentNegativeValue tests assignment with negative value func TestAssignmentNegativeValue(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("x -5 =") if err != nil { @@ -182,7 +182,7 @@ func TestAssignmentNegativeValue(t *testing.T) { // TestAssignmentDecimalValue tests assignment with decimal value func TestAssignmentDecimalValue(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("x 3.14 =") if err != nil { @@ -201,7 +201,7 @@ func TestAssignmentDecimalValue(t *testing.T) { // TestAssignmentUnderscoreVariable tests assignment with underscore variable func TestAssignmentUnderscoreVariable(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("my_var 42 =") if err != nil { @@ -220,7 +220,7 @@ func TestAssignmentUnderscoreVariable(t *testing.T) { // TestAssignmentWithCalculationResult tests assigning result of calculation func TestAssignmentWithCalculationResult(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // 3 4 + x =: should push 3, 4, add (=7), then assign 7 to x _, err := rpn.ParseAndEvaluate("3 4 + x =:") @@ -240,7 +240,7 @@ func TestAssignmentWithCalculationResult(t *testing.T) { // TestAssignmentAllOperatorsInSequence tests all three assignment operators func TestAssignmentAllOperatorsInSequence(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, _ = rpn.ParseAndEvaluate("a 1 =") // standard _, _ = rpn.ParseAndEvaluate("2 b :=") // right @@ -260,7 +260,7 @@ func TestAssignmentAllOperatorsInSequence(t *testing.T) { // TestAssignmentOperatorRegistry verifies all assignment operators are registered func TestAssignmentOperatorRegistry(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) reg := NewOperatorRegistry(ops) // Verify assignment operators are registered as standard operators @@ -278,7 +278,7 @@ func TestAssignmentOperatorRegistry(t *testing.T) { // TestAssignmentNotTriggeredByEqualEqual ensures that == is not misparsed as an assignment. func TestAssignmentNotTriggeredByEqualEqual(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // "a == b" should NOT be treated as an assignment _, err := rpn.ParseAndEvaluate("a == b") @@ -297,7 +297,7 @@ func TestAssignmentNotTriggeredByEqualEqual(t *testing.T) { // TestAssignmentNotTriggeredByNotEqual ensures that != is not misparsed as an assignment. func TestAssignmentNotTriggeredByNotEqual(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // "a != b" should NOT be treated as an assignment _, err := rpn.ParseAndEvaluate("a != b") @@ -311,7 +311,7 @@ func TestAssignmentNotTriggeredByNotEqual(t *testing.T) { // TestAssignmentAfterEqualEqual ensures "x 5 =" still works even when == exists in the expression. func TestAssignmentAfterEqualEqual(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // A standalone assignment should work regardless of == elsewhere result, err := rpn.ParseAndEvaluate("x 5 =") @@ -342,7 +342,7 @@ func TestAssignRightOperator(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) result, err := r.ParseAndEvaluate(tt.expr) if err != nil { t.Fatalf("ParseAndEvaluate(%q) error = %v", tt.expr, err) @@ -367,7 +367,7 @@ func TestAssignLeftOperator(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) result, err := r.ParseAndEvaluate(tt.expr) if err != nil { t.Fatalf("ParseAndEvaluate(%q) error = %v", tt.expr, err) @@ -393,7 +393,7 @@ func TestStandardAssignOperator(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) result, err := r.ParseAndEvaluate(tt.expr) if err != nil { t.Fatalf("ParseAndEvaluate(%q) error = %v", tt.expr, err) @@ -421,7 +421,7 @@ func TestVariableInExpression(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) _, err := r.ParseAndEvaluate(tt.setup) if err != nil { t.Fatalf("Setup failed for %q: %v", tt.setup, err) @@ -439,7 +439,7 @@ func TestVariableInExpression(t *testing.T) { // TestChainedAssignments tests chaining multiple assignments in one expression. func TestChainedAssignments(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) result, err := r.ParseAndEvaluate("a 10 := b 3 := c 2 :=") if err != nil { t.Fatalf("Chained assignment failed: %v", err) @@ -472,7 +472,7 @@ func TestChainedAssignments(t *testing.T) { // TestVarsCommand tests the vars command. func TestVarsCommand(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) // Empty vars result, err := r.ParseAndEvaluate("vars") @@ -501,7 +501,7 @@ func TestVarsCommand(t *testing.T) { // TestClearCommand tests the clear command. func TestClearCommand(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) r.ParseAndEvaluate("x 5 :=") r.ParseAndEvaluate("y 10 :=") @@ -521,7 +521,7 @@ func TestClearCommand(t *testing.T) { // TestDeleteVariableOperator tests the d (delete) operator. func TestDeleteVariableOperator(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) // Create variable r.ParseAndEvaluate("x 5 :=") @@ -544,7 +544,7 @@ func TestDeleteVariableOperator(t *testing.T) { // TestDeleteNonExistentVariableOperator tests deleting a variable that doesn't exist. func TestDeleteNonExistentVariableOperator(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) _, err := r.ParseAndEvaluate(":nonexistent d") if err == nil { t.Error("Deleting non-existent variable should return error") @@ -554,7 +554,7 @@ func TestDeleteNonExistentVariableOperator(t *testing.T) { // TestVariablePersistenceAcrossExpressions tests that variables persist across // multiple ParseAndEvaluate calls on the same RPN instance. func TestVariablePersistenceAcrossExpressions(t *testing.T) { - r := NewRPN(NewVariables()) + r := NewRPN(NewVariables(), nil) r.ParseAndEvaluate("a 10 :=") r.ParseAndEvaluate("b 3 :=") diff --git a/internal/rpn/boolean_test.go b/internal/rpn/boolean_test.go index f0ced89..6eea269 100644 --- a/internal/rpn/boolean_test.go +++ b/internal/rpn/boolean_test.go @@ -98,7 +98,7 @@ func TestBooleanOperators(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) result, err := rpnCalc.ParseAndEvaluate(tt.expression) @@ -163,7 +163,7 @@ func TestBooleanToNumberCoercion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) result, err := rpnCalc.ParseAndEvaluate(tt.expression) @@ -221,7 +221,7 @@ func TestMixedBooleanNumericArithmetic(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) result, err := rpnCalc.ParseAndEvaluate(tt.expression) @@ -268,7 +268,7 @@ func TestBooleanShowFormat(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) result, err := rpnCalc.ParseAndEvaluate(tt.expression) diff --git a/internal/rpn/compare_metric_test.go b/internal/rpn/compare_metric_test.go index e1b5134..d32ac60 100644 --- a/internal/rpn/compare_metric_test.go +++ b/internal/rpn/compare_metric_test.go @@ -177,7 +177,7 @@ func TestMetricAwareComparisons(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) if tt.prefixMode == IEC { rpnCalc.SetPrefixMode(IEC) @@ -282,7 +282,7 @@ func TestShorthandComparisonOperators(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) result, err := rpnCalc.ParseAndEvaluate(tt.expression) @@ -356,7 +356,7 @@ func TestIncompatibleCategoryComparison(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) _, err := rpnCalc.ParseAndEvaluate(tt.expression) @@ -414,7 +414,7 @@ func TestMetricComparisonEdgeCases(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) if tt.prefixMode == IEC { rpnCalc.SetPrefixMode(IEC) diff --git a/internal/rpn/constants_test.go b/internal/rpn/constants_test.go index 68b79d1..4eb2129 100644 --- a/internal/rpn/constants_test.go +++ b/internal/rpn/constants_test.go @@ -213,7 +213,7 @@ func TestConstants_ThreadSafety(t *testing.T) { func TestConstants_RetrieveInRPN(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Test pi constant result, err := r.ParseAndEvaluate("pi") @@ -226,7 +226,7 @@ func TestConstants_RetrieveInRPN(t *testing.T) { // Create a new RPN instance for each test to avoid stack state conflicts v2 := NewVariables() - r2 := NewRPN(v2) + r2 := NewRPN(v2, nil) // Test e constant result, err = r2.ParseAndEvaluate("e") @@ -239,7 +239,7 @@ func TestConstants_RetrieveInRPN(t *testing.T) { // Create a new RPN instance for the next test v3 := NewVariables() - r3 := NewRPN(v3) + r3 := NewRPN(v3, nil) // Test pi in expression result, err = r3.ParseAndEvaluate("pi 2 *") @@ -252,7 +252,7 @@ func TestConstants_RetrieveInRPN(t *testing.T) { // Create a new RPN instance for phi test v4 := NewVariables() - r4 := NewRPN(v4) + r4 := NewRPN(v4, nil) // Test phi constant result, err = r4.ParseAndEvaluate("phi") @@ -266,7 +266,7 @@ func TestConstants_RetrieveInRPN(t *testing.T) { func TestConstants_RetrieveWithGreekLetters(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Test pi with Greek letter result, err := r.ParseAndEvaluate("π") @@ -279,7 +279,7 @@ func TestConstants_RetrieveWithGreekLetters(t *testing.T) { // Create a new RPN instance for phi test v2 := NewVariables() - r2 := NewRPN(v2) + r2 := NewRPN(v2, nil) // Test phi with Greek letter result, err = r2.ParseAndEvaluate("φ") @@ -293,7 +293,7 @@ func TestConstants_RetrieveWithGreekLetters(t *testing.T) { func TestConstants_ConflictWithVariables(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // First set a variable named pi result, err := r.ParseAndEvaluate("pi = 3.0") @@ -316,7 +316,7 @@ func TestConstants_ConflictWithVariables(t *testing.T) { func TestConstantsCommand(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) result, err := r.ParseAndEvaluate("constants") if err != nil { t.Fatalf("ParseAndEvaluate(\"constants\") returned error: %v", err) @@ -328,7 +328,7 @@ func TestConstantsCommand(t *testing.T) { func TestClearConstantsCommand(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // First add a custom constant result, err := r.ParseAndEvaluate("custom 42 =") @@ -409,7 +409,7 @@ func TestConstants_NewConstants(t *testing.T) { // TestConstants_ParseInRPN tests that new constants can be used in RPN expressions func TestConstants_ParseInRPN(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) tests := []struct { expression string @@ -532,7 +532,7 @@ func TestConstants_MoreInRPN(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) result, err := rpnCalc.ParseAndEvaluate(tt.expression) if err != nil { @@ -567,7 +567,7 @@ func TestConstants_ListConstantsIncludesUserDefined(t *testing.T) { // TestConstants_NegativeInfInRPN tests negative infinity constant in RPN func TestConstants_NegativeInfInRPN(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) result, err := rpnCalc.ParseAndEvaluate("-inf") if err != nil { @@ -581,7 +581,7 @@ func TestConstants_NegativeInfInRPN(t *testing.T) { // TestConstants_InfExpression tests infinity in RPN expressions func TestConstants_InfExpression(t *testing.T) { vars := NewVariables() - rpnCalc := NewRPN(vars) + rpnCalc := NewRPN(vars, nil) // inf 1 + should still be inf result, err := rpnCalc.ParseAndEvaluate("inf 1 +") diff --git a/internal/rpn/custom_metric_test.go b/internal/rpn/custom_metric_test.go index e555cee..47ece0f 100644 --- a/internal/rpn/custom_metric_test.go +++ b/internal/rpn/custom_metric_test.go @@ -20,7 +20,7 @@ func customCleanup(t *testing.T, rpn *RPN, name string) { // TestCustomDefineFactorZero tests defining a custom metric with factor=0 func TestCustomDefineFactorZero(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "zero") result, err := rpn.ParseAndEvaluate("custom define zero 0 Custom") @@ -42,7 +42,7 @@ func TestCustomDefineFactorZero(t *testing.T) { // TestCustomDefineNegativeFactor tests defining a custom metric with negative factor func TestCustomDefineNegativeFactor(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "negtest") result, err := rpn.ParseAndEvaluate("custom define negtest -5 Custom") @@ -64,7 +64,7 @@ func TestCustomDefineNegativeFactor(t *testing.T) { // TestCustomDefineMalformedInput tests that malformed custom define input func TestCustomDefineMalformedInput(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("custom define 1 Custom") // Double-space collapses: fields = ["custom", "define", "1", "Custom"] (metric "" already exists as alias or empty check) @@ -78,7 +78,7 @@ func TestCustomDefineMalformedInput(t *testing.T) { // that conflicts with an existing metric func TestCustomDefineConflictingAlias(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // Try to define a metric with a name that matches an existing one _, err := rpn.ParseAndEvaluate("custom define Mbps 1000 DataRate") @@ -90,7 +90,7 @@ func TestCustomDefineConflictingAlias(t *testing.T) { // TestCustomMetricArithmetic tests using a custom metric in arithmetic operations func TestCustomMetricArithmetic(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "arithmetic_test") _, err := rpn.ParseAndEvaluate("custom define arithmetic_test 42 Custom") @@ -109,7 +109,7 @@ func TestCustomMetricArithmetic(t *testing.T) { // TestCustomMetricHyperOperations tests using a custom metric in hyper operations func TestCustomMetricHyperOperations(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "hyper_test") _, err := rpn.ParseAndEvaluate("custom define hyper_test 100 Custom") @@ -128,7 +128,7 @@ func TestCustomMetricHyperOperations(t *testing.T) { // TestCustomMetricSubtraction tests subtraction with custom metrics func TestCustomMetricSubtraction(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "sub_test") _, err := rpn.ParseAndEvaluate("custom define sub_test 10 Custom") @@ -146,7 +146,7 @@ func TestCustomMetricSubtraction(t *testing.T) { // TestCustomMetricMultiplication tests multiplication with custom metrics func TestCustomMetricMultiplication(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "mul_test") _, err := rpn.ParseAndEvaluate("custom define mul_test 5 Custom") @@ -164,7 +164,7 @@ func TestCustomMetricMultiplication(t *testing.T) { // TestCustomMetricDivision tests division with custom metrics func TestCustomMetricDivision(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "div_test") _, err := rpn.ParseAndEvaluate("custom define div_test 10 Custom") @@ -183,7 +183,7 @@ func TestCustomMetricDivision(t *testing.T) { // between different categories func TestCustomMetricConversionFail(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "conv_test") _, err := rpn.ParseAndEvaluate("custom define conv_test 10 Custom") @@ -202,7 +202,7 @@ func TestCustomMetricConversionFail(t *testing.T) { // can't be mixed in operations func TestCustomMetricCrossCategory(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "cat_test1") defer customCleanup(t, rpn, "cat_test2") @@ -219,7 +219,7 @@ func TestCustomMetricCrossCategory(t *testing.T) { // TestCustomMetricShow tests that custom metrics display correctly in Show func TestCustomMetricShow(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) defer customCleanup(t, rpn, "show_test") _, err := rpn.ParseAndEvaluate("custom define show_test 100 Custom") diff --git a/internal/rpn/metric_test.go b/internal/rpn/metric_test.go index 69923cb..5a41f6f 100644 --- a/internal/rpn/metric_test.go +++ b/internal/rpn/metric_test.go @@ -832,7 +832,7 @@ func TestAtPrefixMetricParsing(t *testing.T) { func TestAtPrefixIntegration(t *testing.T) { // Test that @GB parses correctly through the full RPN pipeline vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // Parse a standalone @ metric result, err := rpn.ParseAndEvaluate("@GB") @@ -880,7 +880,7 @@ func TestMetricAwareArithmetic(t *testing.T) { for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate(tt.expr) if tt.wantErr { if err == nil { @@ -985,7 +985,7 @@ func TestMetricOperationsUnit(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) s := NewStack() tc.setup(s) @@ -1040,7 +1040,7 @@ func TestConvertSameCategory(t *testing.T) { for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate(tt.expr) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -1064,7 +1064,7 @@ func TestConvertSameCategory(t *testing.T) { func TestConvertCoolAbsorbing(t *testing.T) { reg := GetMetricRegistry() vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // Cool to metric: 100 @GB convert → 100 GB // With Cool absorption, 100 is treated as 100 in GB's space @@ -1086,7 +1086,7 @@ func TestConvertCoolAbsorbing(t *testing.T) { } // Metric to Cool: 1hr @Cool convert → 3600 Cool - rpn2 := NewRPN(NewVariables()) + rpn2 := NewRPN(NewVariables(), nil) result2, err := rpn2.ParseAndEvaluate("1hr @Cool convert") if err != nil { t.Fatalf("unexpected error: %v", err) @@ -1107,7 +1107,7 @@ func TestConvertCoolAbsorbing(t *testing.T) { func TestConvertIncompatible(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("100Mbps @hr convert") if err == nil { @@ -1121,7 +1121,7 @@ func TestConvertIncompatible(t *testing.T) { func TestConvertInsufficientOperands(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // Missing value (only target on stack) _, err := rpn.ParseAndEvaluate("@Gbps convert") @@ -1130,7 +1130,7 @@ func TestConvertInsufficientOperands(t *testing.T) { } // Missing target (only value on stack, no @X before convert) - rpn2 := NewRPN(NewVariables()) + rpn2 := NewRPN(NewVariables(), nil) _, err = rpn2.ParseAndEvaluate("100Mbps convert") if err == nil { t.Error("expected error for missing target metric operand") diff --git a/internal/rpn/operations.go b/internal/rpn/operations.go index 989ce87..3a85ee5 100644 --- a/internal/rpn/operations.go +++ b/internal/rpn/operations.go @@ -38,10 +38,10 @@ var ( // NewOperations creates a new Operations instance with the given variable store. // Does not create a ConstantsProvider internally; caller must use SetConstants. // If no registry is provided, defaults to the global MetricRegistry. -func NewOperations(vars VariableStore, reg ...MetricReader) *Operations { +func NewOperations(vars VariableStore, reg MetricReader) *Operations { r := MetricReader(GetMetricRegistry()) - if len(reg) > 0 && reg[0] != nil { - r = reg[0] + if reg != nil { + r = reg } return &Operations{ vars: vars, diff --git a/internal/rpn/operations_fastpower_test.go b/internal/rpn/operations_fastpower_test.go index 06a79e0..cdd4c04 100644 --- a/internal/rpn/operations_fastpower_test.go +++ b/internal/rpn/operations_fastpower_test.go @@ -70,7 +70,7 @@ func TestFastPower(t *testing.T) { stack := NewStack() tt.prepare(stack) - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) err := o.FastPower(stack) if tt.wantErr { diff --git a/internal/rpn/operations_hyper_test.go b/internal/rpn/operations_hyper_test.go index 352e503..2a1607a 100644 --- a/internal/rpn/operations_hyper_test.go +++ b/internal/rpn/operations_hyper_test.go @@ -81,7 +81,7 @@ func TestHyperMetricAwareOperations(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate(tc.expr) if tc.wantErr { if err == nil { @@ -162,7 +162,7 @@ func TestHyperCoolResultOperations(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate(tc.expr) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -198,7 +198,7 @@ func TestHyperErrorCases(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate(tc.expr) if err == nil { t.Fatal("expected error, got none") diff --git a/internal/rpn/operations_metric_cmd_test.go b/internal/rpn/operations_metric_cmd_test.go index e7307f7..ea9431d 100644 --- a/internal/rpn/operations_metric_cmd_test.go +++ b/internal/rpn/operations_metric_cmd_test.go @@ -11,7 +11,7 @@ import ( func TestMetricShow(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("100Mbps metric show") if err != nil { @@ -27,7 +27,7 @@ func TestMetricShow(t *testing.T) { func TestMetricShowUniversal(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("42 metric show") if err != nil { @@ -43,7 +43,7 @@ func TestMetricShowUniversal(t *testing.T) { func TestMetricShowEmptyStack(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("metric show") if err == nil { t.Error("expected error for empty stack") @@ -52,7 +52,7 @@ func TestMetricShowEmptyStack(t *testing.T) { func TestMetricList(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("metric list") if err != nil { t.Fatalf("unexpected error: %v", err) @@ -67,7 +67,7 @@ func TestMetricList(t *testing.T) { func TestMetricCategory(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("metric DataRate") if err != nil { t.Fatalf("unexpected error: %v", err) @@ -82,7 +82,7 @@ func TestMetricCategory(t *testing.T) { func TestMetricCategoryTime(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("metric Time") if err != nil { t.Fatalf("unexpected error: %v", err) @@ -97,7 +97,7 @@ func TestMetricCategoryTime(t *testing.T) { func TestMetricCategoryUnknown(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("metric Nope") if err == nil { t.Error("expected error for unknown category") @@ -106,7 +106,7 @@ func TestMetricCategoryUnknown(t *testing.T) { func TestMetricCategoryCustom(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // Custom category exists but has no built-in metrics, so result should be empty result, err := rpn.ParseAndEvaluate("metric Custom") if err != nil { @@ -118,7 +118,7 @@ func TestMetricCategoryCustom(t *testing.T) { func TestMetricSetModeDecimal(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("metric decimal set") if err != nil { @@ -134,7 +134,7 @@ func TestMetricSetModeDecimal(t *testing.T) { func TestMetricSetModeBinary(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("metric binary set") if err != nil { @@ -150,7 +150,7 @@ func TestMetricSetModeBinary(t *testing.T) { func TestMetricSetModeToggle(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // Default is SI if rpn.GetPrefixMode() != SI { @@ -172,7 +172,7 @@ func TestMetricSetModeToggle(t *testing.T) { func TestMetricSetModeBinaryIncomplete(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("metric binary") if err == nil { t.Error("expected error for incomplete 'metric binary'") @@ -181,7 +181,7 @@ func TestMetricSetModeBinaryIncomplete(t *testing.T) { func TestMetricSetModeDecimalIncomplete(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("metric decimal") if err == nil { t.Error("expected error for incomplete 'metric decimal'") @@ -190,7 +190,7 @@ func TestMetricSetModeDecimalIncomplete(t *testing.T) { func TestMetricCompatibleSameCategory(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("100Mbps 1Gbps metric compatible") if err != nil { t.Fatalf("unexpected error: %v", err) @@ -202,7 +202,7 @@ func TestMetricCompatibleSameCategory(t *testing.T) { func TestMetricCompatibleDifferentCategory(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("100Mbps 2hr metric compatible") if err != nil { t.Fatalf("unexpected error: %v", err) @@ -221,7 +221,7 @@ func TestMetricCompatibleDifferentCategory(t *testing.T) { func TestMetricCompatibleWithUniversal(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("100Mbps 42 metric compatible") if err != nil { t.Fatalf("unexpected error: %v", err) @@ -234,7 +234,7 @@ func TestMetricCompatibleWithUniversal(t *testing.T) { func TestMetricCompatibleNotEnoughValues(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("100 metric compatible") if err == nil { t.Error("expected error for insufficient stack values") @@ -243,7 +243,7 @@ func TestMetricCompatibleNotEnoughValues(t *testing.T) { func TestMetricCompatibleEmptyStack(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("metric compatible") if err == nil { t.Error("expected error for empty stack") @@ -349,7 +349,7 @@ func TestPrefixMode(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) if tc.setMode == "iec" { if _, err := rpn.ParseAndEvaluate("metric binary set"); err != nil { @@ -383,7 +383,7 @@ func TestPrefixMode(t *testing.T) { func TestCustomDefineAndList(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) // Define a custom metric result, err := rpn.ParseAndEvaluate("custom define foobar 42 Custom") @@ -421,7 +421,7 @@ func TestCustomDefineAndList(t *testing.T) { func TestCustomDefineDuplicate(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("custom define Cool 1 Universal") if err == nil { t.Error("expected error for duplicate metric name") @@ -430,7 +430,7 @@ func TestCustomDefineDuplicate(t *testing.T) { func TestCustomDefineInvalidCategory(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("custom define foo 1 Nope") if err == nil { t.Error("expected error for invalid category") @@ -439,7 +439,7 @@ func TestCustomDefineInvalidCategory(t *testing.T) { func TestCustomUndefineBuiltIn(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("custom undefine Cool") if err == nil { t.Error("expected error for undefining built-in metric") @@ -448,7 +448,7 @@ func TestCustomUndefineBuiltIn(t *testing.T) { func TestCustomUndefineNotFound(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) _, err := rpn.ParseAndEvaluate("custom undefine nonexistent") if err == nil { t.Error("expected error for undefining non-existent metric") @@ -457,7 +457,7 @@ func TestCustomUndefineNotFound(t *testing.T) { func TestCustomListEmpty(t *testing.T) { vars := NewVariables() - rpn := NewRPN(vars) + rpn := NewRPN(vars, nil) result, err := rpn.ParseAndEvaluate("custom list") if err != nil { t.Fatalf("unexpected error: %v", err) diff --git a/internal/rpn/operations_stack_test.go b/internal/rpn/operations_stack_test.go index 7c0252c..7d74558 100644 --- a/internal/rpn/operations_stack_test.go +++ b/internal/rpn/operations_stack_test.go @@ -11,7 +11,7 @@ import ( func TestShowWithMetrics(t *testing.T) { reg := GetMetricRegistry() vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() mbps, _ := reg.Find("Mbps") @@ -39,7 +39,7 @@ func TestShowWithMetrics(t *testing.T) { func TestShowEmptyStack(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() result, err := ops.Show(stack) @@ -53,7 +53,7 @@ func TestShowEmptyStack(t *testing.T) { func TestShowWithBooleanValues(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() stack.Push(NewFloatFromBool(true)) @@ -74,7 +74,7 @@ func TestShowWithBooleanValues(t *testing.T) { func TestShowWithSymbols(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() stack.Push(NewSymbol("x")) @@ -99,7 +99,7 @@ func TestShowWithSymbols(t *testing.T) { func TestShowWithStringNum(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() stack.Push(NewStringNum("hello")) @@ -120,7 +120,7 @@ func TestShowWithStringNum(t *testing.T) { func TestShowWithMixedTypes(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() reg := GetMetricRegistry() @@ -158,7 +158,7 @@ func TestShowWithMixedTypes(t *testing.T) { func TestShowWithMultipleMetrics(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() reg := GetMetricRegistry() @@ -187,7 +187,7 @@ func TestShowWithMultipleMetrics(t *testing.T) { func TestShowWithRat(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() // Rational numbers @@ -210,7 +210,7 @@ func TestShowWithRat(t *testing.T) { func TestShowWithRatFromBool(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() stack.Push(NewRatFromBool(true)) @@ -231,7 +231,7 @@ func TestShowWithRatFromBool(t *testing.T) { func TestShowValuesOrder(t *testing.T) { vars := NewVariables() - ops := NewOperations(vars) + ops := NewOperations(vars, nil) stack := NewStack() // Push in order: 1, 2, 3 diff --git a/internal/rpn/operations_test.go b/internal/rpn/operations_test.go index 155a53d..77d2f54 100644 --- a/internal/rpn/operations_test.go +++ b/internal/rpn/operations_test.go @@ -124,7 +124,7 @@ func TestStackClear(t *testing.T) { func TestOperationsAdd(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(3.0, FloatMode)) s.Push(NewNumber(4.0, FloatMode)) @@ -147,7 +147,7 @@ func TestOperationsAdd(t *testing.T) { func TestOperationsSubtract(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(10.0, FloatMode)) s.Push(NewNumber(4.0, FloatMode)) @@ -170,7 +170,7 @@ func TestOperationsSubtract(t *testing.T) { func TestOperationsMultiply(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(5.0, FloatMode)) s.Push(NewNumber(3.0, FloatMode)) @@ -193,7 +193,7 @@ func TestOperationsMultiply(t *testing.T) { func TestOperationsDivide(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(20.0, FloatMode)) s.Push(NewNumber(4.0, FloatMode)) @@ -216,7 +216,7 @@ func TestOperationsDivide(t *testing.T) { func TestOperationsDivideByZero(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(10.0, FloatMode)) s.Push(NewNumber(0.0, FloatMode)) @@ -232,7 +232,7 @@ func TestOperationsDivideByZero(t *testing.T) { func TestOperationsPower(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(2.0, FloatMode)) s.Push(NewNumber(3.0, FloatMode)) @@ -255,7 +255,7 @@ func TestOperationsPower(t *testing.T) { func TestOperationsPowerLargeExponent(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() // Test 2^10 = 1024 (large exponent) @@ -299,7 +299,7 @@ func TestOperationsPowerLargeExponent(t *testing.T) { func TestOperationsPowerNegativeExponent(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() // Test 2^-3 = 1/8 = 0.125 @@ -343,7 +343,7 @@ func TestOperationsPowerNegativeExponent(t *testing.T) { func TestOperationsPowInt(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() // Test PowInt(2, 10) = 1024 @@ -387,7 +387,7 @@ func TestOperationsPowInt(t *testing.T) { func TestOperationsPowIntRat(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() // Enable rational mode @@ -435,7 +435,7 @@ func TestOperationsPowIntRat(t *testing.T) { func TestOperationsModulo(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(10.0, FloatMode)) s.Push(NewNumber(3.0, FloatMode)) @@ -458,7 +458,7 @@ func TestOperationsModulo(t *testing.T) { func TestOperationsModuloByZero(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(10.0, FloatMode)) s.Push(NewNumber(0.0, FloatMode)) @@ -471,7 +471,7 @@ func TestOperationsModuloByZero(t *testing.T) { func TestOperationsInsufficientOperands(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(5.0, FloatMode)) @@ -484,7 +484,7 @@ func TestOperationsInsufficientOperands(t *testing.T) { func TestOperationsDup(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(7.0, FloatMode)) @@ -513,7 +513,7 @@ func TestOperationsDup(t *testing.T) { func TestOperationsSwap(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(1.0, FloatMode)) s.Push(NewNumber(2.0, FloatMode)) @@ -539,7 +539,7 @@ func TestOperationsSwap(t *testing.T) { func TestOperationsSwapInsufficient(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(5.0, FloatMode)) @@ -551,7 +551,7 @@ func TestOperationsSwapInsufficient(t *testing.T) { func TestOperationsPop(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(1.0, FloatMode)) s.Push(NewNumber(2.0, FloatMode)) @@ -569,7 +569,7 @@ func TestOperationsPop(t *testing.T) { func TestOperationsPopEmpty(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() err := o.Pop(s) @@ -580,7 +580,7 @@ func TestOperationsPopEmpty(t *testing.T) { func TestOperationsShow(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(1.0, FloatMode)) s.Push(NewNumber(2.0, FloatMode)) @@ -598,7 +598,7 @@ func TestOperationsShow(t *testing.T) { func TestOperationsShowEmpty(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() result, err := o.Show(s) @@ -613,7 +613,7 @@ func TestOperationsShowEmpty(t *testing.T) { func TestOperationsAssignVariable(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() s.Push(NewNumber(5.0, FloatMode)) @@ -638,7 +638,7 @@ func TestOperationsAssignVariable(t *testing.T) { func TestOperationsAssignVariableEmptyName(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() err := o.AssignVariable(s, "") @@ -649,7 +649,7 @@ func TestOperationsAssignVariableEmptyName(t *testing.T) { func TestOperationsUseVariable(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() if err := v.SetVariable("pi", 3.14159); err != nil { @@ -674,7 +674,7 @@ func TestOperationsUseVariable(t *testing.T) { func TestOperationsUseVariableUndefined(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() err := o.UseVariable(s, "undefined") @@ -688,7 +688,7 @@ func TestOperationsUseVariableUndefined(t *testing.T) { func TestOperationsDeleteVariable(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) if err := v.SetVariable("temp", 100.0); err != nil { t.Fatalf("SetVariable() returned error: %v", err) @@ -707,7 +707,7 @@ func TestOperationsDeleteVariable(t *testing.T) { func TestOperationsDeleteVariableUndefined(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) err := o.DeleteVariable("nonexistent") if err == nil { @@ -717,7 +717,7 @@ func TestOperationsDeleteVariableUndefined(t *testing.T) { func TestOperationsListVariables(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) if err := v.SetVariable("x", 1.0); err != nil { t.Fatalf("SetVariable() returned error: %v", err) @@ -741,7 +741,7 @@ func TestOperationsListVariables(t *testing.T) { func TestOperationsClearVariables(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) _, _ = v.SetVariable("x", 1.0), v.SetVariable("y", 2.0) @@ -754,7 +754,7 @@ func TestOperationsClearVariables(t *testing.T) { func TestOperationsConcurrent(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) // Test concurrent variable access // Each goroutine uses its own stack to avoid race conditions @@ -781,7 +781,7 @@ func TestOperationsConcurrent(t *testing.T) { } func TestLog2(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test log₂(8) = 3 @@ -825,7 +825,7 @@ func TestLog2(t *testing.T) { } func TestLog10(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test log₁₀(100) = 2 @@ -862,7 +862,7 @@ func TestLog10(t *testing.T) { } func TestLn(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test ln(e) ≈ 1 @@ -899,7 +899,7 @@ func TestLn(t *testing.T) { } func TestLog2WithBoolean(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test with boolean true (should be converted to 1, log₂(1) = 0) @@ -927,7 +927,7 @@ func TestLog2WithBoolean(t *testing.T) { } func TestLog10WithBoolean(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test with boolean true (should be converted to 1, log₁₀(1) = 0) @@ -955,7 +955,7 @@ func TestLog10WithBoolean(t *testing.T) { } func TestLnWithBoolean(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test with boolean true (should be converted to 1, ln(1) = 0) @@ -983,7 +983,7 @@ func TestLnWithBoolean(t *testing.T) { } func TestLnEdgeCases(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test ln(negative) should error @@ -1018,7 +1018,7 @@ func TestLnEdgeCases(t *testing.T) { } func TestHyperLog2WithBoolean(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test hyperlog₂(4, true) = log₂(4) + log₂(1) = 2 + 0 = 2 @@ -1050,7 +1050,7 @@ func TestHyperLog2WithBoolean(t *testing.T) { } func TestHyperLog10WithBoolean(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test hyperlog₁₀(10, true) = log₁₀(10) + log₁₀(1) = 1 + 0 = 1 @@ -1081,7 +1081,7 @@ func TestHyperLog10WithBoolean(t *testing.T) { } func TestHyperLnWithBoolean(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test hyperln(e, true) = ln(e) + ln(1) = 1 + 0 = 1 @@ -1112,7 +1112,7 @@ func TestHyperLnWithBoolean(t *testing.T) { } func TestHyperLog2(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test hyperlog₂(4, 16) = log₂(4) + log₂(16) = 2 + 4 = 6 @@ -1141,7 +1141,7 @@ func TestHyperLog2(t *testing.T) { } func TestHyperLog10(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test hyperlog₁₀(10, 100) = log₁₀(10) + log₁₀(100) = 1 + 2 = 3 @@ -1163,7 +1163,7 @@ func TestHyperLog10(t *testing.T) { } func TestHyperLn(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) stack := NewStack() // Test hyperln(e, e²) = ln(e) + ln(e²) = 1 + 2 = 3 @@ -1185,7 +1185,7 @@ func TestHyperLn(t *testing.T) { } func TestOperatorRegistry(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) registry := NewOperatorRegistry(o) // Test IsStandardOperator with valid operators @@ -1221,7 +1221,7 @@ func TestOperatorRegistry(t *testing.T) { } func TestOperatorRegistryHandleStandardOperator(t *testing.T) { - o := NewOperations(NewVariables()) + o := NewOperations(NewVariables(), nil) registry := NewOperatorRegistry(o) stack := NewStack() @@ -1266,7 +1266,7 @@ func TestOperatorRegistryHandleStandardOperator(t *testing.T) { func TestAssignLeft(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() // For "5 x =:": @@ -1297,7 +1297,7 @@ func TestAssignLeft(t *testing.T) { func TestAssignRight(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() // For "x 5 :=": @@ -1328,7 +1328,7 @@ func TestAssignRight(t *testing.T) { func TestAssignLeftErrorCases(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() err := o.AssignLeft(s) @@ -1339,7 +1339,7 @@ func TestAssignLeftErrorCases(t *testing.T) { func TestAssignRightErrorCases(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) s := NewStack() err := o.AssignRight(s) diff --git a/internal/rpn/rpn_state.go b/internal/rpn/rpn_state.go index f2cc4ed..2d5c1ab 100644 --- a/internal/rpn/rpn_state.go +++ b/internal/rpn/rpn_state.go @@ -22,9 +22,9 @@ type RPN struct { // NewRPN creates a new RPN parser and evaluator with the given variable store. // If no registry is provided, defaults to the global MetricRegistry. -func NewRPN(vars VariableStore, reg ...MetricReader) *RPN { +func NewRPN(vars VariableStore, reg MetricReader) *RPN { consts := NewConstants() - ops := NewOperations(vars, reg...) + ops := NewOperations(vars, reg) ops.SetMode(FloatMode) // Set default mode ops.SetConstants(consts) // Share the same constants provider return &RPN{ diff --git a/internal/rpn/rpn_state_test.go b/internal/rpn/rpn_state_test.go index 42e5b70..d756f7c 100644 --- a/internal/rpn/rpn_state_test.go +++ b/internal/rpn/rpn_state_test.go @@ -9,7 +9,7 @@ import ( func TestRPNGetConstants(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) consts := r.GetConstants() if consts == nil { t.Fatal("GetConstants() returned nil") @@ -26,7 +26,7 @@ func TestRPNGetConstants(t *testing.T) { func TestRPNGetModeAndSetMode(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Default should be FloatMode if r.GetMode() != FloatMode { @@ -48,7 +48,7 @@ func TestRPNGetModeAndSetMode(t *testing.T) { func TestRPNSetCurrentStack(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Start with empty stack if got := r.GetCurrentStack(); len(got) != 0 { @@ -76,7 +76,7 @@ func TestRPNSetCurrentStack(t *testing.T) { func TestRPNStack(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) values := []StackValue{ NewNumber(42.0, FloatMode), @@ -94,7 +94,7 @@ func TestRPNStack(t *testing.T) { func TestRPNIsStandardOperator(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) tests := []struct { token string @@ -125,7 +125,7 @@ func TestRPNIsStandardOperator(t *testing.T) { func TestRPNIsHyperOperator(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) tests := []struct { token string @@ -155,7 +155,7 @@ func TestRPNIsHyperOperator(t *testing.T) { func TestOperationsMetricRegistry(t *testing.T) { v := NewVariables() - o := NewOperations(v) + o := NewOperations(v, nil) reg := o.MetricRegistry() if reg == nil { @@ -174,7 +174,7 @@ func TestOperationsMetricRegistry(t *testing.T) { func TestRPNSetPrefixMode(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Default should be SI if r.GetPrefixMode() != SI { diff --git a/internal/rpn/rpn_test.go b/internal/rpn/rpn_test.go index bd8e0fa..085eb1c 100644 --- a/internal/rpn/rpn_test.go +++ b/internal/rpn/rpn_test.go @@ -11,7 +11,7 @@ import ( func TestNewRPN(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) if r == nil { t.Fatal("NewRPN() returned nil") } @@ -102,7 +102,7 @@ func TestParseAndEvaluateSimple(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) result, err := r.ParseAndEvaluate(tt.input) if err != nil { t.Fatalf("ParseAndEvaluate(%q) returned error: %v", tt.input, err) @@ -140,7 +140,7 @@ func TestParseAndEvaluateChain(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) result, err := r.ParseAndEvaluate(tt.input) if err != nil { t.Fatalf("ParseAndEvaluate(%q) returned error: %v", tt.input, err) @@ -178,7 +178,7 @@ func TestParseAndEvaluateStackOps(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) result, err := r.ParseAndEvaluate(tt.input) if err != nil { t.Fatalf("ParseAndEvaluate(%q) returned error: %v", tt.input, err) @@ -192,7 +192,7 @@ func TestParseAndEvaluateStackOps(t *testing.T) { func TestParseAndEvaluateVariables(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Test variable assignment and reuse // First assign a variable @@ -216,7 +216,7 @@ func TestParseAndEvaluateVariables(t *testing.T) { func TestParseAndEvaluateEmpty(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) _, err := r.ParseAndEvaluate("") if err == nil { @@ -249,7 +249,7 @@ func TestParseAndEvaluateAssignment(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) result, err := r.ParseAndEvaluate(tt.input) if err != nil { t.Fatalf("ParseAndEvaluate(%q) returned error: %v", tt.input, err) @@ -263,7 +263,7 @@ func TestParseAndEvaluateAssignment(t *testing.T) { func TestParseAndEvaluateDivisionByZero(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) _, err := r.ParseAndEvaluate("5 0 /") if err == nil { @@ -276,7 +276,7 @@ func TestParseAndEvaluateDivisionByZero(t *testing.T) { func TestParseAndEvaluateUndefinedVariable(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) _, err := r.ParseAndEvaluate("undefined +") if err == nil { @@ -290,7 +290,7 @@ func TestParseAndEvaluateUndefinedVariable(t *testing.T) { func TestParseAndEvaluateUnknownToken(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) _, err := r.ParseAndEvaluate("1 2 + hello") if err == nil { @@ -314,7 +314,7 @@ func TestParseAndEvaluateInsufficientOperands(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) _, err := r.ParseAndEvaluate(tt.input) if err == nil { t.Errorf("%q should return error for insufficient operands", tt.input) @@ -325,7 +325,7 @@ func TestParseAndEvaluateInsufficientOperands(t *testing.T) { func TestParseAndEvaluateShow(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) result, err := r.ParseAndEvaluate("1 2 3 show") if err != nil { @@ -338,7 +338,7 @@ func TestParseAndEvaluateShow(t *testing.T) { func TestParseAndEvaluateVars(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Set some variables using new format: "name = value" if _, err := r.ParseAndEvaluate("x = 5"); err != nil { @@ -359,7 +359,7 @@ func TestParseAndEvaluateVars(t *testing.T) { func TestParseAndEvaluateClear(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Set and clear if _, err := r.ParseAndEvaluate("x 5 ="); err != nil { @@ -376,7 +376,7 @@ func TestParseAndEvaluateClear(t *testing.T) { func TestRPNConcurrency(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) done := make(chan bool, 10) for i := 0; i < 5; i++ { @@ -399,7 +399,7 @@ func TestRPNConcurrency(t *testing.T) { func TestResultStack(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) tokens := []string{"1", "2", "3", "+"} result, err := r.ResultStack(tokens) @@ -413,7 +413,7 @@ func TestResultStack(t *testing.T) { func TestResultStackEmpty(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) tokens := []string{} result, err := r.ResultStack(tokens) @@ -452,7 +452,7 @@ func TestParseAndEvaluateAssignmentExpression(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) result, err := r.ParseAndEvaluate(tt.input) if err != nil { t.Fatalf("ParseAndEvaluate(%q) returned error: %v", tt.input, err) @@ -496,7 +496,7 @@ func TestParseAndEvaluateAssignmentErrors(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) _, err := r.ParseAndEvaluate(tt.input) if err == nil { t.Errorf("ParseAndEvaluate(%q) expected error, got nil", tt.input) @@ -546,7 +546,7 @@ func TestParseAndEvaluateEvaluateErrors(t *testing.T) { } t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) _, err := r.ParseAndEvaluate(tt.input) if err == nil { t.Errorf("ParseAndEvaluate(%q) expected error, got nil", tt.input) @@ -561,7 +561,7 @@ func TestParseAndEvaluateEvaluateErrors(t *testing.T) { func TestResultStackErrors(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Test error cases in ResultStack function tests := []struct { @@ -612,7 +612,7 @@ func TestResultStackErrors(t *testing.T) { func TestResultStackMultipleValues(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Test Case where stack has multiple values at the end tests := []struct { @@ -659,7 +659,7 @@ func TestResultStackMultipleValues(t *testing.T) { func TestRPNIncrementalOperations(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // Test: 1 2 3 + then + // First evaluate "1 2 3 +" @@ -684,7 +684,7 @@ func TestRPNIncrementalOperations(t *testing.T) { // TestIncrementalAssignmentRPN tests x =: with value on stack in ParseAndEvaluate func TestIncrementalAssignmentRPN(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) // First, put 2 on the stack result, err := r.ParseAndEvaluate("2") @@ -753,7 +753,7 @@ func TestParseAndEvaluateAssignmentLeftRight(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { v := NewVariables() - r := NewRPN(v) + r := NewRPN(v, nil) _, err := r.ParseAndEvaluate(tt.input) if err != nil { @@ -775,7 +775,7 @@ func TestParseAndEvaluateAssignmentLeftRight(t *testing.T) { // TestSymbolPush verifies that :x syntax pushes a symbol func TestSymbolPush(t *testing.T) { vars := NewVariables() - r := NewRPN(vars) + r := NewRPN(vars, nil) // Test :x syntax result, err := r.ParseAndEvaluate(":x") @@ -807,7 +807,7 @@ func TestSymbolPush(t *testing.T) { // TestUnboundIdentifierAsSymbol verifies that unbound identifiers push symbols func TestUnboundIdentifierAsSymbol(t *testing.T) { vars := NewVariables() - r := NewRPN(vars) + r := NewRPN(vars, nil) // Use bare identifier x (unbound) result, err := r.ParseAndEvaluate("x") @@ -824,7 +824,7 @@ func TestUnboundIdentifierAsSymbol(t *testing.T) { // TestBoundIdentifierPushesValue verifies that bound identifiers push values func TestBoundIdentifierPushesValue(t *testing.T) { vars := NewVariables() - r := NewRPN(vars) + r := NewRPN(vars, nil) // First bind x to 5 if _, err := r.ParseAndEvaluate("x = 5"); err != nil { @@ -847,7 +847,7 @@ func TestBoundIdentifierPushesValue(t *testing.T) { func TestSymbolWithAssignment(t *testing.T) { // Test :x 10 := (symbol then value with right assignment) vars := NewVariables() - r := NewRPN(vars) + r := NewRPN(vars, nil) _, err := r.ParseAndEvaluate(":x 10 :=") if err != nil { @@ -865,7 +865,7 @@ func TestSymbolWithAssignment(t *testing.T) { // Test 10 :x =: (value then symbol with left assignment) vars2 := NewVariables() - r2 := NewRPN(vars2) + r2 := NewRPN(vars2, nil) _, err = r2.ParseAndEvaluate("10 :x =:") if err != nil { @@ -884,7 +884,7 @@ func TestSymbolWithAssignment(t *testing.T) { // TestStackBasedAssignmentWithSymbol verifies stack-based assignment with symbol func TestStackBasedAssignmentWithSymbol(t *testing.T) { vars := NewVariables() - r := NewRPN(vars) + r := NewRPN(vars, nil) // Push 42 onto stack _, err := r.ParseAndEvaluate("42") |
