feat: 添加CLAUDE.md文件
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Build & Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build
|
||||||
|
cargo build
|
||||||
|
|
||||||
|
# Run REPL (interactive)
|
||||||
|
cargo run
|
||||||
|
|
||||||
|
# Execute a script file
|
||||||
|
cargo run -- examples/script.ast
|
||||||
|
|
||||||
|
# Run tests (none yet; the project has no test/ directory)
|
||||||
|
cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a pure-Rust project with no external dependencies (`edition = "2024"`).
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
**Aster** is a tree-walking interpreter for a custom dynamically-typed scripting language. The pipeline follows the classic compiler frontend pattern:
|
||||||
|
|
||||||
|
```
|
||||||
|
Source text → Lexer → Tokens → Parser → AST → Interpreter → Output
|
||||||
|
```
|
||||||
|
|
||||||
|
### Module map
|
||||||
|
|
||||||
|
| Module | Responsibility |
|
||||||
|
|---|---|
|
||||||
|
| `lexer/` | Tokenizer. `Lexer::tokenize()` takes `&str` and returns `(Vec<Token>, Vec<RuntimeError>)`. Tokens carry `line`/`column` for error reporting. Supports `//` single-line comments. |
|
||||||
|
| `parser/` | Recursive-descent parser (Pratt-style for expressions). `Parser::parse()` returns `(Vec<Stmt>, Vec<RuntimeError>)`. Uses `synchronize()` for error recovery — skips to the next statement boundary on parse failure. |
|
||||||
|
| `ast/` | AST node definitions. `Expr` (in `expr.rs`) covers literals, variables, assignment, property access/indexing, unary/binary/logical ops, calls, lambdas, and object/array literals. `Stmt` (in `stmt.rs`) covers let, expression stmts, blocks, if/while/for, functions, return/break/continue. |
|
||||||
|
| `interpreter/` | Tree-walking evaluator. `Interpreter` holds an `env: Rc<RefCell<Env>>`. `Env` is a linked-list of scopes for lexical nesting. The `Signal` enum propagates `Return`/`Break`/`Continue` through the call stack. `builtins/` registers native functions (`print`, `input`, `clock`) organized as `io` and `os` modules (also available as global functions). |
|
||||||
|
| `error/` | Three error variants: `LexError` (line+column), `ParseError` (token), `RuntimeError` (optional token). All implement `Display` and `std::error::Error`. |
|
||||||
|
| `main.rs` | Two modes: `run_file` (parse-then-execute, exits with code 65 on lex/parse errors, 70 on runtime errors) and `run_repl` (per-line evaluation with `:exit`/`:reset` commands). |
|
||||||
|
|
||||||
|
### Key design decisions
|
||||||
|
|
||||||
|
- **No external crate dependencies.** Everything is built on Rust's stdlib.
|
||||||
|
- **Rc<RefCell<>> for shared ownership.** `Env` chains, `Value::Object`, `Value::Array`, and `Value::Function` all use `Rc<RefCell<>>` for interior mutability — matching the dynamic, garbage-collected feel without a GC.
|
||||||
|
- **Error-tolerant parsing.** Both lexer and parser collect errors into a `Vec` rather than failing on the first error, so multiple diagnostics can be reported per run.
|
||||||
|
- **Closures capture by environment.** `Function` structs store the `Env` at definition time; lambda expressions (`fn(params) { body }`) work the same way.
|
||||||
|
- **Compound assignment operators** (`+=`, `-=`, `*=`, `/=`, `%=`) are parsed into `Expr::Assign`/`Set`/`IndexSet` with an `AssignOp` variant and evaluated by `apply_assign_op`.
|
||||||
|
|
||||||
|
### Language syntax overview
|
||||||
|
|
||||||
|
Variables: `let x = 42;`
|
||||||
|
Functions: `fn add(a, b) { return a + b; }`
|
||||||
|
Closures: `fn(x, y) { return x + y; }`
|
||||||
|
Control flow: `if`/`while`/`for` (C-style), `break`/`continue`, `return`
|
||||||
|
Data: objects `{ key: val }`, arrays `[1, 2, 3]`, indexing `arr[i]`, property access `obj.prop`
|
||||||
|
Operators: `+ - * / %`, `== != < > <= >=`, `&& || !`, `= += -= *= /= %=`
|
||||||
|
Builtins: `print(...)`, `input(prompt?)`, `os.clock()` (also `clock()` directly)
|
||||||
Reference in New Issue
Block a user