From d56e16dc85ff3efe7b5865bd27e4804423a6e463 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sat, 23 May 2026 23:04:11 +0300 Subject: feat: wire DeleteVariable to OperatorRegistry as 'd' operator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'd' token was previously a no-op error. Now it pops a value from the stack and deletes the variable with that name. Accepts Symbol (:x) or StringNum as the variable name. Added DeleteVariable to VariableOperator interface so the operator can call it through the Operator interface. Example: x 5 = :x d vars → No variables defined --- internal/rpn/operations_interfaces.go | 1 + internal/rpn/operator_registry.go | 16 +++++++++++++++- internal/rpn/rpn_test.go | 4 ++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/internal/rpn/operations_interfaces.go b/internal/rpn/operations_interfaces.go index b6c2baa..0f461f0 100644 --- a/internal/rpn/operations_interfaces.go +++ b/internal/rpn/operations_interfaces.go @@ -54,6 +54,7 @@ type VariableOperator interface { ClearVariables() AssignLeft(stack *Stack) error AssignRight(stack *Stack) error + DeleteVariable(name string) error } // ConstantOperator defines the interface for constant operations. diff --git a/internal/rpn/operator_registry.go b/internal/rpn/operator_registry.go index f2ea64f..9f8e9c8 100644 --- a/internal/rpn/operator_registry.go +++ b/internal/rpn/operator_registry.go @@ -54,7 +54,21 @@ func NewOperatorRegistry(op Operator) *OperatorRegistry { registry.registerStandardOperator("swap", func(stack *Stack) error { return op.Swap(stack) }) registry.registerStandardOperator("pop", func(stack *Stack) error { return op.Pop(stack) }) registry.registerStandardOperator("d", func(stack *Stack) error { - return fmt.Errorf("'d' command not supported as standalone token") + val, err := popStack(stack, "d") + if err != nil { + return err + } + // Extract variable name from the value + var name string + switch v := val.(type) { + case *Symbol: + name = v.Name() + case *StringNum: + name = v.String() + default: + return fmt.Errorf("delete expects a variable name, got %T", val) + } + return op.DeleteVariable(name) }) // Commands that return immediately diff --git a/internal/rpn/rpn_test.go b/internal/rpn/rpn_test.go index 494e377..6f7deee 100644 --- a/internal/rpn/rpn_test.go +++ b/internal/rpn/rpn_test.go @@ -522,9 +522,9 @@ func TestParseAndEvaluateEvaluateErrors(t *testing.T) { expectedError: "invalid assignment syntax", }, { - name: "'d' command not supported", + name: "'d' command without operand", input: "d", - expectedError: "'d' command not supported as standalone token", + expectedError: "insufficient operands for d", }, { name: "empty result after evaluation", -- cgit v1.2.3