Files
aster/README.md
T

168 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Aster
Aster 是一门使用 Rust 编写的动态类型脚本语言解释器,基于树遍历(tree-walker)实现。无外部依赖,纯标准库。
## 快速开始
```bash
# 构建
cargo build
# 启动 REPL(交互式)
cargo run
# 执行脚本文件
cargo run -- examples/script.ast
# 运行测试
cargo test
```
## 语言特性
### 变量与赋值
```js
let x = 42; // 可变绑定
const y = 100; // 不可变绑定(不能重新赋值)
let name = "aster";
x = x + 1;
x += 2; // 复合赋值:+= -= *= /= %=
// y = 200; // ✗ 运行时错误:不能对 const 重新赋值
```
`const` 阻止对绑定的重新赋值,但不阻止对象属性或数组元素的修改。
### 数据类型
```js
let n = 3.14; // 数字(f64
let s = "hello\nworld"; // 字符串(支持 \n \t \r \" \\ 转义)
let b = true; // 布尔值
let empty = nil; // nil
let arr = [1, 2, 3]; // 数组
let obj = { name: "aster", v:1 }; // 对象
```
### 运算符
```
算术: + - * / %
比较: == != < > <= >=
逻辑: && || !
```
- `+` 同时支持数字加法和字符串拼接
- `==``!=` 对数组和对象进行深度比较
- `&&``||` 短路求值
- 除零和取模零会产生运行时错误
### 控制流
```js
// if / else
if (x > 0) {
print("positive");
} else {
print("non-positive");
}
// while 循环
let i = 0;
while (i < 10) {
print(i);
i = i + 1;
}
// for 循环(C 风格)
for (let i = 0; i < 10; i = i + 1) {
print(i);
}
// break / continue
while (true) {
if (condition) { break; }
if (skip) { continue; }
}
```
### 函数与闭包
```js
// 函数声明
fn add(a, b) {
return a + b;
}
// 递归
fn fib(n) {
if (n <= 1) { return n; }
return fib(n - 1) + fib(n - 2);
}
// 闭包
fn make_adder(x) {
return fn(y) { return x + y; };
}
let add5 = make_adder(5);
print(add5(10)); // 15
```
### 数组与对象
```js
let arr = [10, 20, 30];
print(arr[0]); // 索引访问
arr[1] = 99; // 索引赋值
arr[0] += 5; // 复合索引赋值
let obj = { name: "aster", version: 1 };
print(obj.name); // 属性访问
obj.version = 2; // 属性赋值
```
### 内置函数
```js
// I/O
print("hello", 42); // 打印,自动换行
let name = input("name: "); // 读取输入(可选提示符)
let name = io.input("name:"); // 模块化调用
// 时间
let t = clock(); // Unix 时间戳(秒)
let t = os.clock(); // 模块化调用
```
## REPL 命令
| 命令 | 说明 |
|------|------|
| `:exit` | 退出 REPL |
| `:reset` | 重置解释器状态(清除所有变量和函数) |
## 架构
```
源码文本 → Lexer → Tokens → Parser → AST → Interpreter → 输出
```
| 模块 | 职责 |
|------|------|
| `lexer/` | 词法分析。`Lexer::tokenize()` 将源码转为 `(Vec<Token>, Vec<Error>)`,Token 记录行列号用于错误报告,支持 `//` 单行注释 |
| `parser/` | 递归下降 + Pratt 解析器。`Parser::parse()` 返回 `(Vec<Stmt>, Vec<Error>)`,遇到语法错误通过 `synchronize()` 跳过至下一条语句边界继续解析 |
| `ast/` | AST 节点定义。`Expr`(表达式)涵盖字面量、变量、赋值、属性/索引访问、一元/二元/逻辑运算、函数调用、lambda 和对象/数组字面量。`Stmt`(语句)涵盖 let、表达式语句、块、if/while/for、函数、return/break/continue |
| `interpreter/` | 树遍历求值器。`Env` 是基于 `Rc<RefCell<>>` 的链式作用域。`Signal` 枚举通过调用栈传播 `Return`/`Break`/`Continue``builtins/``io``os` 模块组织原生函数,同时注册为全局函数以方便使用 |
| `error/` | 三种错误:`LexError`(行列号)、`ParseError`Token)、`RuntimeError`(可选 Token |
### 关键设计决策
- **零外部依赖** — 全部基于 Rust 标准库构建
- **错误容忍解析** — 词法分析器和解析器均将错误收集到 `Vec` 中,单次运行可报告多个诊断信息,而非在第一个错误处就中止
- **`Rc<RefCell<>>` 共享所有权** — 用于 `Env` 链、`Value::Object``Value::Array``Value::Function`,提供动态可变语义
- **词法作用域闭包** — `Function` 在定义时捕获 `Env`lambda 表达式同理
## 许可证
MIT