|
| 1 | +# AI_README |
| 2 | + |
| 3 | +A concise, high-signal guide for AI agents working on this repository. Focuses on structure, conventions, and safe extension points. Prefer small, verifiable changes with tests. |
| 4 | + |
| 5 | +## Project overview |
| 6 | +- Language/GUI: Rust + egui (eframe) |
| 7 | +- Purpose: A desktop utility with multiple pages (number conversion, text conversion, bit viewer, calculator). The calculator currently contains a "Radix" sub‑tool for evaluating expressions typed in a selected base (2/8/10/16), calculating in decimal via mathcore, then rendering results in multiple bases. |
| 8 | +- Key external crate: `mathcore` for expression evaluation (functions like `sin`, `cos`, `pow`, etc.). |
| 9 | + |
| 10 | +## Build and test |
| 11 | +- Build/check: `cargo check` |
| 12 | +- Run app: `cargo run` |
| 13 | +- Run tests: `cargo test -q` |
| 14 | +- Test policy: Keep test scope minimal and fast. Prefer targeted tests over entire suite when iterating. |
| 15 | + |
| 16 | +## Repository layout (relevant parts) |
| 17 | +- src/app/application.rs |
| 18 | + - App wiring: fonts, navigation bar, central panel routing. |
| 19 | +- src/ui/components/navigation.rs |
| 20 | + - Top bar navigation, `AppPage` enum. |
| 21 | +- src/ui/pages/mod.rs |
| 22 | + - Pages registry (number_conversion, text_conversion, bit_viewer, calculator). |
| 23 | +- src/ui/pages/calculator/mod.rs |
| 24 | + - Calculator page (Radix sub‑project) implementation. Contains UI, expression conversion, formatting, highlighting, and history. |
| 25 | + |
| 26 | +## Calculator: Radix sub‑project |
| 27 | +The Radix calculator lets users type expressions using digits of the selected base. It converts numbers to decimal, evaluates via `mathcore`, then renders results in bases 2/8/10/16. Calculation is automatic on input/base change. |
| 28 | + |
| 29 | +### State (struct RadixCalculator) |
| 30 | +- `radix: u32` chosen base (2/8/10/16) |
| 31 | +- `input: String` user expression (in chosen base) |
| 32 | +- `output: String` last formatted output in the current base (kept for history) |
| 33 | +- `last_error: Option<String>` most recent error message (not stored in history) |
| 34 | +- `last_value: Option<f64>` last successful decimal value (enables multi‑base display) |
| 35 | +- `history: VecDeque<HistoryEntry>` ring buffer; see History |
| 36 | + |
| 37 | +### Compute flow |
| 38 | +1) User input changes or base changes → `compute()` called. |
| 39 | +2) Convert input from `radix` to a decimal expression string. |
| 40 | + - Parses numbers (supports `_` separators) and operators `+ - * / % ^ ,` and parentheses. |
| 41 | + - Identifiers (letters/underscore followed by alphanumerics/underscore) are passed through unchanged. |
| 42 | + - Supports unary minus for numbers in appropriate positions. |
| 43 | + - Supports implicit multiplication (see below). |
| 44 | +3) Evaluate decimal expression with `mathcore::MathCore::calculate`. |
| 45 | +4) If result is finite: |
| 46 | + - Save `last_value`. |
| 47 | + - Format an output string in the currently selected base using `format_auto`. |
| 48 | + - Push a history entry with: selected radix, original input, decimal expression, and current‑base output. |
| 49 | +5) On error/non‑finite: set `last_error` and do not write history, clear `last_value`. |
| 50 | + |
| 51 | +### Implicit multiplication rules |
| 52 | +- Insert `*` automatically between adjacent tokens when mathematically implied: |
| 53 | + - Number/`)`/Identifier followed by Number/Identifier → insert `*`. |
| 54 | + - Number/`)` followed by `(` → insert `*`. |
| 55 | + - Identifier followed by `(`: |
| 56 | + - If identifier is a known function (e.g., `sin`, `cos`, `sqrt`, `pow`, `log`, `ln`, `min`, `max`, etc.), treat as a function call (no `*`). |
| 57 | + - Otherwise insert `*` (e.g., `pi(2)` becomes `pi*2`). |
| 58 | +- Note: In non‑decimal bases (e.g., base 16), `A..F` are digits, not identifiers. So `A(B+1)` means `10*(11+1)` in base‑16 semantics. |
| 59 | + |
| 60 | +### Formatting of results |
| 61 | +- `format_auto(f64, radix, frac_digits)`: |
| 62 | + - If the result is within a small tolerance of an integer (≈1e‑12 relative/absolute), format as an integer in the target base. |
| 63 | + - Otherwise format as a floating value. |
| 64 | +- For decimal (radix=10): prints a decimal float (12 digits), trimmed trailing zeros and trailing dot. |
| 65 | +- For non‑decimal: prints integer part in that base plus a fractional part approximated with repeated multiply‑and‑floor for up to `frac_digits` digits (default 16). Negative sign applied consistently. |
| 66 | +- The UI shows the computed value simultaneously in bases 2, 8, 10, 16. The history stores only the output string in the currently selected base, plus the decimal expression. |
| 67 | + |
| 68 | +### History |
| 69 | +- Type: `VecDeque<HistoryEntry>`; capacity bound via `MAX_HISTORY` (200). When over capacity, pop from front. |
| 70 | +- Contains: `radix`, `input` (original), `decimal_expr` (converted), `output` (formatted string), `error` (unused now; errors aren’t recorded). |
| 71 | +- UI offers a “清空历史” (clear) button and a “重用” button to restore a past input and radix. |
| 72 | + |
| 73 | +### Error highlighting (TextEdit) |
| 74 | +- A lightweight layouter marks invalid characters in red according to the chosen base. |
| 75 | +- Valid: whitespace, digits legal in the base (including `_`), operators `+ - * / % ^ ,`, parentheses, and ASCII alphabetic identifiers/underscore. |
| 76 | +- This is a visual aid; actual parsing and conversion enforce validity again. |
| 77 | + |
| 78 | +## Conventions and guardrails for agents |
| 79 | +- Prefer minimal, reversible edits. Keep changes scoped and run `cargo check` and relevant tests after changes. |
| 80 | +- Do not install or upgrade dependencies without explicit instruction. |
| 81 | +- When adding features to the calculator, be careful about base semantics: |
| 82 | + - Digits vs identifiers in bases 2/8/16 (A–F are digits in base‑16). |
| 83 | + - Implicit multiplication insertion can have side effects; update the rule set and tests together. |
| 84 | +- If changing formatting (precision, tolerance), keep constants centralized and document the user‑visible impact. |
| 85 | +- History must not record failures. Ensure `last_value` is `Some` only on success. |
| 86 | + |
| 87 | +## Typical extension tasks |
| 88 | +- Add more function names as “function‑like”: |
| 89 | + - Extend the `is_function_like` helper with additional names if mathcore supports them. |
| 90 | + - Keep it case‑insensitive. |
| 91 | +- Make fractional precision configurable: |
| 92 | + - Add a small UI control to set `FRACTION_DIGITS` at runtime. |
| 93 | +- Add angle unit toggle (degree/radian): |
| 94 | + - If implemented, apply a transform to trig function inputs in conversion or pre‑evaluation. |
| 95 | +- Improve highlighting to token‑aware styles (operators, numbers, identifiers in different colors). |
| 96 | +- Persist history: |
| 97 | + - Serialize to a file on exit and reload on startup (opt‑in setting). |
| 98 | + |
| 99 | +## Safe refactoring plan (if needed) |
| 100 | +- Split `src/ui/pages/calculator/mod.rs` into submodules: |
| 101 | + - format.rs: number/float formatting and helpers |
| 102 | + - convert.rs: base‑aware tokenization and decimal conversion (incl. implicit multiplication) |
| 103 | + - highlight.rs: layouter and input validation |
| 104 | + - history.rs: HistoryEntry and bounded deque utils |
| 105 | +- Introduce `fn eval_expr(expr:&str, radix:u32)->Result<(f64,String),String>` encapsulating conversion and evaluation; `compute()` only orchestrates state and history. |
| 106 | +- After splitting, add focused unit tests for each module. |
| 107 | + |
| 108 | +## Troubleshooting |
| 109 | +- `sin(10)` looked like `0`? Ensure no integer‑only formatting; current code supports floats. If regressions occur, re‑check `format_auto` and `format_float_in_radix`. |
| 110 | +- `sin(pi/2)` not equal to `1`? Confirm the “near‑integer” rounding is applied before non‑decimal formatting. Check tolerance constants. |
| 111 | +- Unexpected identifier behavior in base‑16: remember `A..F` are digits; adjust test expectations accordingly. |
| 112 | +- NaN/Inf results: these are treated as errors; they do not enter history. |
| 113 | + |
| 114 | +## Code style and testing guidance |
| 115 | +- Keep functions short and single‑purpose; prefer extracting helpers over long, nested blocks. |
| 116 | +- Document non‑obvious rules (e.g., implicit multiplication) with examples in comments and tests. |
| 117 | +- When adding behavior, add or update tests under the smallest scope that covers the change. |
| 118 | + |
| 119 | +## Glossary |
| 120 | +- Decimal expression: The ASCII expression string after converting base‑specific number tokens to decimal integers, with identifiers/operators/parentheses otherwise preserved. |
| 121 | +- Function‑like identifier: An identifier followed by `(` that should be considered a function call rather than implicit multiplication; managed by `is_function_like`. |
| 122 | + |
0 commit comments