**Workspace 拆分** - aster-core: 纯库,zero-dependency,包含 lexer/parser/ast/interpreter/error/analysis - aster: REPL 二进制,薄封装 aster-core - aster-lsp: LSP 语言服务器 **VS Code 扩展 (vscode-ext/)** - TextMate 语法高亮 (.ast 文件) - 语言配置 (注释切换、括号配对、自动缩进) - LSP 客户端 (extension.js) **LSP 服务端功能** - Diagnostics: 实时显示 lex/parse 错误红色波浪线 - Completion: 关键字 + 内置函数 + 用户定义符号补全 - Hover: 悬停显示变量/函数信息 - Signature Help: 函数参数提示 - Goto Definition: Ctrl+Click 跳转到声明处 - Find References: 查找所有引用位置 - Rename: F2 重命名符号 **新增 analysis 模块** - collect_symbols: AST 遍历收集符号 - find_declaration/find_all_references: Token 扫描定位声明和引用
4.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Build & Run
# Build entire workspace
cargo build
# Run REPL (interactive)
cargo run --bin aster
# Execute a script file
cargo run --bin aster -- aster-core/examples/script.ast
# Run tests
cargo test
This is a Rust workspace. aster-core is a pure-Rust library with no external dependencies (edition = "2024").
Project structure
aster/
├── Cargo.toml # workspace root (aster-core, aster, aster-lsp)
├── aster-core/ # core library — lexer, parser, AST, interpreter
├── aster/ # REPL binary (thin wrapper around aster-core)
├── aster-lsp/ # LSP server (diagnostics, etc.)
└── vscode-ext/ # VS Code extension (syntax highlighting + LSP client)
VS Code Extension
The vscode-ext/ directory contains a VS Code extension that provides syntax highlighting and language server support for .ast files.
Install (development)
# 1. Build the LSP server
cargo build --bin aster-lsp
# 2. Install extension npm dependencies
npm --prefix vscode-ext install
# 3. Register the extension in VS Code
# Windows: create junction
powershell -Command "New-Item -ItemType Junction -Path '$env:USERPROFILE\.vscode\extensions\aster-lang' -Target '$PWD\vscode-ext' -Force"
# macOS / Linux: symlink
ln -s "$PWD/vscode-ext" "$HOME/.vscode/extensions/aster-lang"
After installation, reload VS Code (Ctrl+Shift+P → "Developer: Reload Window"). Open any .ast file — syntax errors will appear as red squiggly underlines.
Note: The LSP server binary must be built (cargo build --bin aster-lsp) before the extension will work. After making changes to aster-lsp, rebuild and reload the VS Code window.
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 (aster-core/src/)
| Module | Responsibility |
|---|---|
lexer/ |
Tokenizer. Lexer::tokenize() takes &str and returns (Vec<Token>, Vec<RuntimeError>). Tokens carry line/column for error reporting. Supports // single-line and /* */ block 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. |
lib.rs |
Crate root — declares public modules, re-exports key types, provides run_file() and run_repl() convenience functions. |
Key design decisions
aster-corehas no external crate dependencies. Everything is built on Rust's stdlib.aster-lspdepends onlsp-server+lsp-types.- Rc<RefCell<>> for shared ownership.
Envchains,Value::Object,Value::Array, andValue::Functionall useRc<RefCell<>>for interior mutability — matching the dynamic, garbage-collected feel without a GC. - Error-tolerant parsing. Both lexer and parser collect errors into a
Vecrather than failing on the first error, so multiple diagnostics can be reported per run. - Closures capture by environment.
Functionstructs store theEnvat definition time; lambda expressions (fn(params) { body }) work the same way. - Compound assignment operators (
+=,-=,*=,/=,%=) are parsed intoExpr::Assign/Set/IndexSetwith anAssignOpvariant and evaluated byapply_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)