From 197cbb161c803db9e0f61ce5365440514ace654e Mon Sep 17 00:00:00 2001 From: MatMoul Date: Sat, 25 Apr 2026 04:36:53 +0200 Subject: [PATCH] docs: refresh project rules and README for current engine API --- .continue/rules/project.md | 94 +++++++---- README.md | 326 +++++++++++++++++++++++++------------ 2 files changed, 288 insertions(+), 132 deletions(-) diff --git a/.continue/rules/project.md b/.continue/rules/project.md index 746f646..b056b97 100644 --- a/.continue/rules/project.md +++ b/.continue/rules/project.md @@ -1,20 +1,24 @@ # Project rules — RPN Virtual Calculator -- Build a browser-friendly RPN calculator as a JavaScript class, preferably in a single file. +- Build a browser-friendly RPN calculator as a JavaScript class, currently implemented in `src/rpn-calculator.js`. - Keep code names, categories, and API identifiers in English. -- Use only read-only / generic public API methods: `push`, `pop`, `clear`, `swap(index1, index2)`, `remove(index)`, `edit(index)`, `isValidIndex(index)`, `input(command)`, and `command(name, ...args)`. -- Expose `inputValue` as a string and `isEditing` as a boolean. -- Constructor options: +- Keep the public calculator API centered on the generic methods `push`, `pop`, `clear`, `swap(index1, index2)`, `remove(index)`, `edit(index)`, `isValidIndex(index)`, `input(command)`, and `command(name, ...args)`. +- `inputValue` must remain a string and `isEditing` must remain a boolean. +- Keep constructor options aligned with the current engine: - `maxSize` (default `2048`) - - `base` (default `10`) - - `angleMode` (`deg` default; also `rad` and `grad`) + - `base` (default `10`, accepted range `2..16`) + - `angleMode` (`deg` by default; also `rad` and `grad`) - `enabledCommands` -- Available constants: `pi`, `e`. -- Supported operations must be centralized in one dictionary containing at least: +- Available constants are `pi` and `e`. +- Supported operations must stay centralized in one dictionary containing at least: - `argCount` - `category` - `aliases` -- Allowed categories are limited to: `Stack`, `Arithmetic`, and `Trigonometry`. + - `execute` +- Allowed operation categories are limited to `Stack`, `Arithmetic`, and `Trigonometry`. +- The engine currently exposes static helpers for category discovery: `getOperationCategories()` and `getOperationsByCategory()`. +- The instance currently exposes `getOperationsByCategory()` and `getConstants()` helpers in addition to the generic API. +- Preserve browser and CommonJS exports for `RpnCalculator`. ## Supported commands @@ -22,42 +26,70 @@ - `add`, `sub`, `mul`, `div`, `mod`, `pow`, `sqr`, `neg`, `sqrt`, `recip`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `log`, `ln`, `dup`, `drop`, `swap`, `clear`, `enter` -- Aliases: +- Current aliases include: - `+`, `-`, `*`, `/`, `%`, `^`, `y^x`, `1/x` +- Existing extra alias also present in code: + - `sqrt(x)` for `sqrt` ## Behavior rules -- `mod` is the percentage operator: `a b % => (a * b) / 100` -- `sqrt`, `asin`, `acos`, `log`, and `ln` must throw clear, explicit domain errors -- `log` uses `Math.log10` -- `ln` uses `Math.log` -- Trigonometric functions must support `deg`, `rad`, and `grad` -- In the browser demo, degrees are the default angle mode -- `inputValue` must remain a string to preserve future hexadecimal input support +- `mod` is the percentage operator: `a b % => (a * b) / 100`. +- `div` and `recip` must throw `Division by zero` on zero divisors. +- `sqrt`, `asin`, `acos`, `log`, and `ln` must throw explicit domain errors. +- `log` uses `Math.log10`. +- `ln` uses `Math.log`. +- Trigonometric functions must support `deg`, `rad`, and `grad`. +- Direct trigonometric functions convert input angles with `toRadians(...)`. +- Inverse trigonometric functions convert results back using the current angle mode via `toDegrees(...)`. +- The engine rounds formatted numeric results to 12 decimal places and normalizes `-0` to `0`. +- `inputValue` must remain a string to preserve future hexadecimal-style input support. +- `parseInputValue(...)` currently uses `Number(...)` in base 10 and `parseInt(..., base)` for other bases. +- `input(command)` currently accepts single-character numeric editing input, including `0-9`, `A-F`, `a-f`, `+`, `-`, and `.`. +- `command(name, ...args)` currently resolves aliases, supports constants, commits pending input before execution, checks `enabledCommands`, and throws clear `Unknown command`, `Command disabled`, `Stack overflow`, `Stack underflow`, `Invalid stack index`, `Invalid number`, and `Invalid input value` errors where appropriate. ## Demo rules -- The browser demo lives under `samples/dev/` -- `samples/dev/index.html` is the demo entry page -- `samples/dev/index.css` contains the calculator visual theme -- `samples/dev/index.js` contains demo-side presentation helpers and UI logic -- The demo UI must expose: - - a stack display - - a main display +- The active browser demo lives under `samples/dev/`. +- `samples/dev/index.html` is the demo entry page. +- `samples/dev/index.css` contains the calculator visual theme. +- `samples/dev/index.js` contains demo-side presentation helpers and UI logic. +- The demo currently exposes: + - a stack display with four visible lines + - a main display/status area - a visible angle mode indicator - an angle mode selector for `deg`, `rad`, and `grad` -- The demo may present user-facing labels such as `+`, `−`, `×`, `÷`, `y^x`, `1/x`, and `x²` while still using English command identifiers internally -- The example HTML must group buttons by `Stack`, `Arithmetic`, and `Trigonometry` -- The example HTML must call `command(...)` for actions -- Keyboard support in the demo should remain consistent with the displayed help text + - status pills showing `inputValue` and `isEditing` + - grouped command panels for `Stack`, `Arithmetic`, `Trigonometry`, and `Constants` + - an error display area +- The demo may present user-facing labels such as `+`, `−`, `×`, `÷`, `y^x`, `1/x`, and `x²` while still using English command identifiers internally. +- The example HTML groups buttons by `Stack`, `Arithmetic`, and `Trigonometry`, plus a dedicated `Constants` section. +- Demo buttons are wired through demo helpers that eventually call `command(...)` for calculator commands. +- The demo default angle mode is degrees. +- Keyboard support in the demo must remain consistent with the displayed help text. +- The current demo keyboard behavior supports: + - digits and decimal point + - numpad digits and numpad arithmetic keys + - `Enter` to validate input or toggle stack-item move mode + - `Backspace` to edit input or drop from the stack + - `Delete` to clear + - `Escape` to cancel editing, cancel move mode, or clear selection + - `ArrowUp` / `ArrowDown` to navigate or move selected stack items + - `ArrowRight` for swap + - `+`, `-`, `*`, `/`, `%`, `^` + - `q`, `n`, `r`, `i`, `g`, `l`, `s`, `c`, `S`, `C` + - `x`, `y`, `z`, `t` to select visible stack registers +- The demo currently implements stack selection and stack-item move mode in its own UI logic using the public stack methods. +- The demo currently duplicates X on `enter` when not editing, matching classic RPN-style behavior in the UI layer. ## File references -- `samples/dev/index.html` references `src/rpn-calculator.js` as the calculator engine used by the demo -- Keep the demo aligned with the public calculator API exposed by `src/rpn-calculator.js` +- `samples/dev/index.html` references `../../src/rpn-calculator.js` as the calculator engine used by the demo. +- Keep the demo aligned with the public calculator API exposed by `src/rpn-calculator.js`. +- `README.md` is currently outdated and duplicated in places; if documentation work is done later, align it with the actual engine and demo behavior. ## Maintenance +- Re-read `src/rpn-calculator.js` and `samples/dev/` before updating these rules after project changes. - Keep this file updated after each project change using the provided editing tools. -- When changing the demo UI or calculator API, update these rules so they continue to match the current project behavior. +- When changing the demo UI, keyboard help, exported API, command metadata, or calculator behavior, update these rules so they continue to match the current project behavior. diff --git a/README.md b/README.md index 5d53e62..253b3c9 100644 --- a/README.md +++ b/README.md @@ -2,87 +2,122 @@ A browser-friendly RPN calculator built around a small, generic JavaScript API. -## Goal +## Overview -This project defines a reusable RPN calculator engine with: +This project provides: -- a simple stack-based public API -- configurable numeric and UI behavior -- centralized command metadata -- a browser demo that uses the same public API as any consumer code +- a reusable JavaScript RPN engine in `src/rpn-calculator.js` +- a browser demo in `samples/dev/` +- a command system centralized in a single operation dictionary +- a small public API focused on stack operations and generic command dispatch -# RPN Virtual Calculator - -A browser-friendly RPN calculator built around a small, generic JavaScript API. - -## Goal - -This project provides a reusable Reverse Polish Notation (RPN) calculator engine with: - -- a simple stack-based public API -- configurable numeric behavior -- centralized command metadata -- browser demos that use the same public API as any consumer code +The main class is `RpnCalculator`. ## Project structure - `src/rpn-calculator.js`: calculator engine -- `samples/dev/index.html`: browser demo -- `samples/calc-01/index.html`: browser demo -- `samples/calc-XX/index.html`: browser demo +- `samples/dev/index.html`: active browser demo entry point +- `samples/dev/index.css`: demo styles +- `samples/dev/index.js`: demo UI and keyboard logic +- `samples/calc-01/index.html`: active browser demo entry point +- `samples/calc-01/index.css`: demo styles +- `samples/calc-01/index.js`: demo UI and keyboard logic +- `samples/calc-XX/index.html`: active browser demo entry point +- `samples/calc-XX/index.css`: demo styles +- `samples/calc-XX/index.js`: demo UI and keyboard logic -## Main features +## Public API -- Single JavaScript class: `RpnCalculator` -- Configurable stack size via `maxSize` (default: `2048`) -- Configurable numeric base via `base` (default: `10`) -- Configurable angle mode via `angleMode`: - - `deg` (default) - - `rad` - - `grad` -- Optional command filtering through `enabledCommands` -- Public API limited to generic methods: - - `push(value)` - - `pop()` - - `clear()` - - `swap(index1, index2)` - - `remove(index)` - - `edit(index)` - - `isValidIndex(index)` - - `input(command)` - - `command(name, ...args)` -- `inputValue` is always stored as a string -- `isEditing` is exposed as a boolean -- Supported operations are centralized in one dictionary with metadata such as: - - `argCount` - - `category` - - `aliases` -- Supported categories are limited to: - - `Stack` - - `Arithmetic` - - `Trigonometry` -## Available constants +The calculator API is centered on these methods: + +- `push(value)` +- `pop()` +- `clear()` +- `swap(index1, index2)` +- `remove(index)` +- `edit(index)` +- `isValidIndex(index)` +- `input(command)` +- `command(name, ...args)` + +Instance helpers also available: + +- `getOperationsByCategory()` +- `getConstants()` + +Static helpers also available: + +- `RpnCalculator.getOperationCategories()` +- `RpnCalculator.getOperationsByCategory()` + +State exposed on instances: + +- `inputValue` as a string +- `isEditing` as a boolean +- `stack` as the current internal stack array used by the demo +- `angleMode` +- `base` +- `maxSize` + +## Constructor options + +```js README.md +const calc = new RpnCalculator({ + maxSize: 2048, + base: 10, + angleMode: 'deg', + enabledCommands: ['add', 'sub', 'mul', 'div'] +}); +``` + +Supported options: + +- `maxSize`: maximum stack size, default `2048` +- `base`: numeric base, default `10`, accepted range `2..16` +- `angleMode`: `deg`, `rad`, or `grad`, default `deg` +- `enabledCommands`: optional whitelist of enabled commands and aliases + +## Constants + +Available constants: - `pi` - `e` +They can be used through `command(...)`: + +```js README.md +calc.command('pi'); +calc.command('e'); +``` + ## Supported commands +### Stack + +- `enter` +- `dup` +- `drop` +- `swap` +- `clear` + ### Arithmetic -- `add` (`+`) -- `sub` (`-`) -- `mul` (`*`) -- `div` (`/`) -- `mod` (`%`) -- `pow` (`^`, `y^x`) + +- `add` alias: `+` +- `sub` alias: `-` +- `mul` alias: `*` +- `div` alias: `/` +- `mod` alias: `%` +- `pow` aliases: `^`, `y^x` - `sqr` - `neg` -- `sqrt` -- `recip` (`1/x`) +- `sqrt` alias: `sqrt(x)` +- `recip` alias: `1/x` - `log` - `ln` ### Trigonometry + - `sin` - `cos` - `tan` @@ -90,57 +125,146 @@ This project provides a reusable Reverse Polish Notation (RPN) calculator engine - `acos` - `atan` -### Stack -- `dup` -- `drop` -- `swap` -- `clear` -- `enter` - -## Behavior rules +## Behavior notes - `mod` is a percentage operator: - `a b % => (a * b) / 100` +- `div` and `recip` throw `Division by zero` when needed +- `sqrt` throws `Invalid input for sqrt` for negative values +- `asin` and `acos` throw explicit domain errors outside `[-1, 1]` +- `log` throws `Invalid input for log` for values `<= 0` +- `ln` throws `Invalid input for ln` for values `<= 0` - `log` uses `Math.log10` - `ln` uses `Math.log` -- `sqrt`, `asin`, `acos`, `log`, and `ln` throw explicit domain errors on invalid input -- Trigonometric behavior depends on `angleMode` -- In degree mode: - - `sin`, `cos`, `tan` convert degrees to radians internally - - `asin`, `acos`, `atan` return degrees -- `inputValue` remains a string to preserve future support for formats such as hexadecimal input +- direct trigonometric functions convert input using `toRadians(...)` +- inverse trigonometric functions convert results back using the current angle mode +- formatted numeric values are rounded to 12 decimal places +- `-0` is normalized to `0` +- `inputValue` remains a string to preserve future non-decimal input support +- base 10 input is parsed with `Number(...)` +- non-decimal input currently uses `parseInt(..., base)` + +## Input handling + +`input(command)` supports two modes: + +- single-character editing input +- command dispatch + +Accepted single-character editing input currently includes: + +- `0-9` +- `A-F` +- `a-f` +- `+` +- `-` +- `.` + +Everything else is forwarded to `command(...)`. ## Basic usage -### In a browser -- `rpn-calculator.js`: calculator engine -- `rpn-example.html`: example browser interface +### CommonJS -## Main features -- Single JavaScript class -- Configurable stack size (`maxSize`, default: `2048`) -- Configurable numeric base (`base`, default: `10`) -- Configurable angle mode (`angleMode`, default: `deg`) -- Optional command filtering through `enabledCommands` -- Generic public API centered on: - - `push` - - `pop` -- `clear` - - `swap(index1, index2)` - - `remove(index)` - - `edit(index)` - - `isValidIndex(index)` - - `input(command)` - - `command(name, ...args)` -- `inputValue` is kept as a string to preserve future input formats -- `isEditing` is exposed as a boolean state -- All supported commands are described in one centralized dictionary -- Supported categories are limited to: - - `Stack` - - `Arithmetic` - - `Trigonometry` +```js README.md +const RpnCalculator = require('./src/rpn-calculator'); -## Basic usage +const calc = new RpnCalculator(); +calc.push(2); +calc.push(3); +calc.command('add'); -### In a browser +console.log(calc.pop()); // 5 +``` +### Browser + +```html README.md + + +``` + +### Editing values through `input(...)` + +```js README.md +const calc = new RpnCalculator(); + +calc.input('1'); +calc.input('2'); +calc.input('.'); +calc.input('5'); +calc.command('enter'); + +console.log(calc.pop()); // 12.5 +``` + +### Aliases + +```js README.md +const calc = new RpnCalculator(); +calc.push(6); +calc.push(7); +calc.command('+'); +console.log(calc.pop()); // 13 +``` + +### Constants and trigonometry + +```js README.md +const calc = new RpnCalculator({ angleMode: 'deg' }); +calc.command('pi'); +console.log(calc.pop()); + +calc.push(30); +calc.command('sin'); +console.log(calc.pop()); // 0.5 +``` + +## Demo + +The active demo lives in `samples/dev/`. + +Main UI features: + +- four visible stack lines +- main display/status area +- visible angle mode indicator +- angle mode selector for `deg`, `rad`, and `grad` +- status pills for `inputValue` and `isEditing` +- grouped panels for `Stack`, `Arithmetic`, `Trigonometry`, and `Constants` +- error display area + +The demo loads the engine from: + +```html README.md + +``` + +### Demo keyboard support + +The current demo supports: + +- digits and decimal point +- numpad digits and numpad arithmetic keys +- `Enter` +- `Backspace` +- `Delete` +- `Escape` +- `ArrowUp`, `ArrowDown`, `ArrowRight` +- `+`, `-`, `*`, `/`, `%`, `^` +- `q`, `n`, `r`, `i`, `g`, `l`, `s`, `c`, `S`, `C` +- `x`, `y`, `z`, `t` + +The demo also implements stack selection and stack-item move mode in its UI layer using the public calculator methods. + +## Exports + +`RpnCalculator` is exposed in both environments: + +- browser: `window.RpnCalculator` +- CommonJS: `module.exports = RpnCalculator`