summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2026-05-24fix(rpn): change variadic NewRPN/NewOperations to single optional ↵Paul Buetow
MetricReader (task ok)
2026-05-24fix(rpn): define OperatorRegistryProvider interface to fix DIP violation ↵Paul Buetow
(task nk)
2026-05-24fix(rpn): delegate Modulo to binaryMetricOp (task gk)Paul Buetow
2026-05-24fix(rpn): embed existing interfaces in VariableOpProvider and ↵Paul Buetow
CommandOpProvider (task fk)
2026-05-24fix(rpn): complete DIP for MetricRegistry — use MetricReader/MetricWriter ↵Paul Buetow
interfaces (task ek)
2026-05-24docs: update README.mdPaul Buetow
2026-05-24fix(rpn): extract setVariableResult helper for assignment paths (task bk)Paul Buetow
2026-05-24fix(rpn): use correct subcommand name in metric error messages (task ak)Paul Buetow
2026-05-24fix(rpn): remove unused IsBool/IsString/IsSymbol from StackValue (task 8k)Paul Buetow
2026-05-24fix(rpn): introduce MetricReader interface for testability (task 7k)Paul Buetow
2026-05-24fix(rpn): consolidate extractVarName into rpn_parse.go (task 6k)Paul Buetow
2026-05-24fix(rpn): replace assignmentHandler strategy pattern with if/else chain ↵Paul Buetow
(task 5k)
2026-05-24fix(repl): add looksLikeRPN guard to prevent swallowing non-RPN input (task 4k)Paul Buetow
2026-05-24fix(rpn): narrow OperatorProvider with focused registration interfaces (task 3k)Paul Buetow
2026-05-24fix(rpn): restrict isValidIdentifier to letters and underscore only (task 2k)Paul Buetow
2026-05-24fix(rpn): remove dead number-parse check from handleOperator (task 1k)Paul Buetow
2026-05-24fix(rpn): remove SetConstants from OperationsProvider (ISP violation, task 0k)Paul Buetow
2026-05-24fix(rpn): replace parseCategory iota loop with O(1) map lookup (task zj)Paul Buetow
2026-05-24fix(rpn): widen RPN.consts to ConstantsProvider, remove unsafe type ↵Paul Buetow
assertion (task yj)
2026-05-24repl: remove redundant ToLower on single-token operator lookup (gj)Paul Buetow
All operator registry keys are lowercase, so strings.ToLower(token) was a no-op. Removing the unnecessary lowercasing and the unused op variable, passing the original token directly to IsStandardOperator/IsHyperOperator/EvalOperator.
2026-05-24fix(rpn): extract var-name type switch into helper (tj)Paul Buetow
Extract the duplicated type switch on StackValue in AssignLeft() and AssignRight() into a single extractVarName() helper, closing the OCP violation — adding a new StackValue subtype as a valid variable name now only requires editing one function.
2026-05-24refactor(rpn): delegate Divide() to binaryMetricOp via preCheck (oj)Paul Buetow
Add variadic preChecks parameter to binaryMetricOp, allowing callers to run a validation on the right operand before metric resolution. This eliminates the full pipeline duplication in Divide() — it now delegates to binaryMetricOp with a preCheck that guards against division by zero.
2026-05-24Add compile-time interface satisfaction checks (xj)Paul Buetow
Add var _ Interface assertions to verify implementations at compile time: - internal/rpn/variables.go: assert *Variables against VariableReader, VariableWriter, VariablePersistence, and VariableStore - internal/repl/handlers.go: assert *BuiltInCommandHandler, *RPNHandler, *PercentageHandler, and *ErrorHandler against CommandHandler (BaseHandler intentionally excluded as it lacks a Handle method and is only meant for embedding) - internal/repl/completer.go: assert *AutoCompleteAdapter against readline.AutoCompleter (adds readline import) Note: internal/rpn/constants.go already had assertions in place.
2026-05-24refactor: split runCommand() into focused helpers (mj)Paul Buetow
Extract runCommand() in cmd/gt/main.go into separate helpers following SRP: - parseFlags(): extract --log flag parsing - dispatchInput(): route by arg count/content (version, stdin, args) - handleNoInput(): TTY→REPL or stdin→parse path - startREPL(): REPL launch with optional log file - tryParse(): RPN-first with percentage fallback runCommand() is now a 3-line orchestrator delegating to parseFlags() and dispatchInput(). No behavioral change; all tests pass.
2026-05-24refactor(repl): extract RPN prefixes to data-driven slice (task uj)Paul Buetow
Replace the hardcoded strings.HasPrefix check for "rpn " and "calc " with a loop over a package-level rpnPrefixes slice. Adding a new prefix now only requires appending to the slice, satisfying the Open/Closed Principle.
2026-05-24fix(rpn): extract builtInConstants map, eliminate loadBuiltInConstants dual ↵Paul Buetow
responsibility (sj) Move built-in constants into a package-level builtInConstants map so loadBuiltInConstants() only copies from it (no return value). Reload and Clear now simply clear and copy from the source map, removing the maps.DeleteFunc dance and the unused maps import.
2026-05-24fix: replace Category.String() switch with data-driven slice (qj)Paul Buetow
OCP violation: adding a new Category required editing the String() method. Use a parallel categoryNames slice indexed by Category value instead, so adding a new category only requires appending to the slice. _sentinel already bounds the range.
2026-05-24refactor(rpn): extract 'd' operator into Delete method (pj)Paul Buetow
Move the inline logic for the 'd' (delete variable) operator into a proper Operations.Delete method, following the same registration pattern as all other operators. Adds Delete to the StackOperator interface.
2026-05-24fix(rpn): DIP violation — NewOperatorRegistry accepts OperatorProvider ↵Paul Buetow
interface (nj) Accept the OperatorProvider interface instead of concrete *Operations in NewOperatorRegistry() and all register* methods. OperatorProvider embeds ArithmeticOperator, PowerIntOperator, LogarithmicOperator, BooleanOperator, StackOperator, VariableOperator, ConstantOperator, MetricOperator, and HyperOperator, allowing mocking or alternative implementations.
2026-05-24refactor(rpn): split ConstantsProvider into Reader/Writer/Admin ↵Paul Buetow
sub-interfaces (#wj) Follows the same ISP-compliant pattern as VariableStore (VariableReader, VariableWriter, VariablePersistence). The fat 7-method ConstantsProvider is now split into: - ConstantsReader: GetConstant, ListConstants, Count, HasConstant - ConstantsWriter: SetConstant - ConstantsAdmin: ClearConstants, ReloadBuiltInConstants - ConstantsProvider: embeds all three for convenience RPN.consts narrowed to ConstantsReader since RPN only reads constants; GetConstants() asserts to ConstantsProvider for callers that need full access. Added compile-time satisfaction checks for all sub-interfaces.
2026-05-24fix(rpn): restore stack values in popAll on partial failure (lj)Paul Buetow
If stack.Pop() errors midway through the loop, already-popped values are pushed back in reverse order before returning the error, preventing stack corruption from concurrent modification or unexpected failures.
2026-05-24fix(rpn): extract metric inference rules into data-driven maps (task kj)Paul Buetow
Replace hardcoded switch statements in resultMetricForMul and resultMetricForDiv with package-level maps (multiplicationInference, divisionInference). Adding new category pairs now only requires appending to the maps instead of editing control flow, satisfying OCP.
2026-05-24refactor(repl): introduce RPNCalculator interface to fix DIP violation (task rj)Paul Buetow
Handlers accessed repl.rpnState.rpnCalc — three levels of concrete types violating DIP and Law of Demeter. Define an RPNCalculator interface capturing only the methods handlers actually need, and expose it via REPL.RpnCalculator() so handlers depend on the interface, not the concrete chain of *rpn.RPN.
2026-05-24fix: remove dead "=" entry from operator registry (fj)Paul Buetow
The dispatchToken guard for standalone "=" always fires before the registry lookup, making the "=" registration in operator_registry.go dead code. Assignment with "=" is handled at the expression level by handleStandardAssign, not via the stack-level operator registry. Also update related tests: - TestAssignmentOperatorRegistry: remove "=" from registered operators - TestResultStackErrors: "=" is no longer an operator, expects "unknown token" instead of "insufficient operands"
2026-05-24refactor(rpn): split NewOperatorRegistry() into focused helpers (task ej)Paul Buetow
NewOperatorRegistry() was 60+ lines of registration calls. Split into six category-specific helpers: registerArithmeticOperators, registerComparisonOperators, registerStackOperators, registerVariableOperators, registerCommandOperators, and registerHyperOperators. NewOperatorRegistry() is now a thin ~13-line orchestrator.
2026-05-24fix(rpn): optimize Swap from O(n) to O(1) (task dj)Paul Buetow
Replace stack.Values() with direct Pop() calls in Swap(). Previously created a full stack copy just to read the top two values. Behavior is unchanged — ensureStackLength guard guarantees pops succeed.
2026-05-24refactor(rpn): extract sortVariableInfos helper (task cj)Paul Buetow
Deduplicate identical VariableInfo sorting logic across ListVariables(), formatVariablesUnsafe(), and Save(). All three callers now use a single unexported sortVariableInfos helper.
2026-05-24refactor(repl): extract evalWithStackRestore helper (task bj)Paul Buetow
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.
2026-05-24rpn: decouple RPN from concrete *Operations type (task aj)Paul Buetow
Define OperationsProvider interface composed of focused sub-interfaces (ModeController, MetricCommander, CustomMetricManager) plus the existing StackOperator. Change RPN.ops from *Operations to OperationsProvider so the high-level RPN module depends on abstractions, not the concrete type (DIP). Add compile-time assertions for the new interfaces in operations.go.
2026-05-24refactor(rpn): split ArithmeticOperator into 3 interfaces (task 9j)Paul Buetow
The ArithmeticOperator interface bundled basic arithmetic (+, -, *, /, ^, %), logarithmic operations (Log2, Log10, Ln), and metric conversion (Convert) into a single interface, violating ISP and LSP. Split into: - ArithmeticOperator — Add, Subtract, Multiply, Divide, Power, Modulo - LogarithmicOperator — Log2, Log10, Ln - MetricOperator — Convert Updated compile-time interface checks in operations.go and the trailing comment in operations_interfaces.go. No behavioral change.
2026-05-24refactor(rpn): split large functions in rpn_parse.go (task 6j)Paul Buetow
Extract inline helper methods to bring dispatchToken, handleMetricCommand, and handleCustomCommand under 50 lines: - handleInlineAssignment: extracts := / =: stack assignment logic - handleMetricPrefix: handles metric binary/decimal prefix mode switching - handleCustomDefine: handles 'custom define' subcommand - handleCustomUndefine: handles 'custom undefine' subcommand dispatchToken: 55 -> 47 lines handleMetricCommand: 40 -> 38 lines handleCustomCommand: 43 -> 31 lines
2026-05-24refactor(rpn): simplify isValidIdentifier(), removing dead multi-char loop ↵Paul Buetow
(task 5j) The loop checking remaining characters was dead code — the final check meant any token longer than 1 char was rejected regardless of what the loop found. Replace the entire function with a simple single-char check.
2026-05-24fix(rpn): remove duplicate ConstantsProvider initialization (task 4j)Paul Buetow
NewOperations() no longer creates a ConstantsProvider internally since NewRPN() always calls SetConstants() immediately after. Eliminates a wasted allocation with no behavioral change.
2026-05-24refactor(rpn): extract checkStackOverflow helper in pushLiteral (#3j)Paul Buetow
Deduplicate the repeated stack overflow check in pushLiteral() by extracting it into a checkStackOverflow() helper method. Replaces three identical inline checks with calls to the new helper.
2026-05-24rpn: remove unused stack parameter from shouldPushName (task 2j)Paul Buetow
2026-05-24docs: add CLI usage guide (task di)Paul Buetow
Document all invocation modes (single-expression, REPL, pipe, stdin), boolean coercion rules, version/help behavior, exit codes, and practical use cases for scripts and CI pipelines.
2026-05-24docs: add symbols.md — document :x syntax and symbol behavior (task ci)Paul Buetow
2026-05-24docs: add repl-mode.md documentation (task bi)Paul Buetow
2026-05-24docs: add rational-mode.md documentation (task ai)Paul Buetow
Test and document rational number mode: - rat on/off/toggle commands (REPL only) - How big.Rat integration works internally - Precision comparison examples with actual output - Known limitation: +, -, % fail for non-dyadic decimals (0.1, 0.2) due to Rat.Float64() rejecting lossy conversions - Performance trade-offs vs float64 mode - Edge cases including metrics, constants, and variables - When to use rational mode and when to stick with float mode
2026-05-24docs: add custom-metrics.md (task 9i)Paul Buetow
Document custom metric commands (define/undefine/list/show) with syntax, REPL workflow examples, arithmetic usage, practical use cases, and edge cases including duplicate names, invalid categories, and factor zero behavior.