feat: IDE支持 — workspace拆分、LSP服务器、VS Code扩展

**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 扫描定位声明和引用
This commit is contained in:
2026-06-25 00:28:13 +08:00
parent 99c9e9c9bd
commit bdffe9e3c5
65 changed files with 1709 additions and 47 deletions
+39
View File
@@ -0,0 +1,39 @@
let arr = [10, 20, 30, 40, 50]
print(arr)
print(arr[0] + arr[4])
let i = 1
while(i < 4) {
print(arr[i])
i = i + 1
}
arr[0] = 99
print(arr)
for (let j = 0; j < 3; j = j + 1) {
arr[j] = arr[j] * 2
}
print(arr)
let nested = [[1, 2], [3, 4], [5, 6]]
print(nested[1][0])
let empty = []
print(empty)
let mixed = [1, "hello", true, nil]
print(mixed)
print(mixed[1][0])
let same = [1, 2, 3]
let other = [1, 2, 3]
print(same == other)
print(same != [3, 2, 1])
let item = { name: "sword", price: 100 }
let items = [item, { name: "shield", price: 50 }]
print(items[0].name)
items[1].price = 75
print(items[1].price)
+23
View File
@@ -0,0 +1,23 @@
let a = 1
a += 2
print("a=", a)
let b = 2
b -= 1
print("b=", b)
let c = 5
c *= 5
print("c=", c)
let d = 10
c /= 5
print("d=", d)
let arr = [1, 2, 3]
arr[0] += 2
print(arr)
let obj = { name: "elmma", age: 26 }
obj.age -= 2
print(obj)
+27
View File
@@ -0,0 +1,27 @@
// test break
let i = 0
while (i < 10) {
if (i == 5) { break }
i = i + 1
}
print("break (expect 5):", i)
// test continue
let sum = 0
let j = 0
while (j < 10) {
j = j + 1
if (j == 5) { continue }
sum = sum + j
}
print("continue (expect 50):", sum)
// test for + break
let found = -1
for (let k = 0; k < 100; k = k + 1) {
if (k * k > 50) {
found = k
break
}
}
print("for break (expect 8):", found)
+21
View File
@@ -0,0 +1,21 @@
// Quick smoke test for new builtins
print("--- len ---")
print(len("hello"))
print(len([1, 2, 3]))
print(len({a: 1, b: 2, c: 3}))
print("--- typeof ---")
print(typeof(42))
print(typeof("hi"))
print(typeof(true))
print(typeof(nil))
print(typeof([1, 2]))
print(typeof({a: 1}))
print(typeof(print))
print("--- push/pop ---")
let arr = [1, 2]
print("push:", push(arr, 3))
print("arr:", arr)
print("pop:", pop(arr))
print("arr:", arr)
+23
View File
@@ -0,0 +1,23 @@
// for-in loop demo
print("=== array ===")
let arr = [10, 20, 30]
for (x in arr) {
print(x)
}
print("=== object keys + values ===")
let obj = {name: "Aster", year: 2025}
for (k in obj) {
print(k + ": " + obj[k])
}
print("=== string chars ===")
for (c in "Hi") {
print(c)
}
print("=== break ===")
for (x in [1, 2, 3, 4, 5]) {
if (x == 3) { break }
print(x)
}
+2
View File
@@ -0,0 +1,2 @@
let name = io.input("Your name: ");
io.print("Hello, " + name)
+9
View File
@@ -0,0 +1,9 @@
let i = 0;
while(i < 10) {
print(i);
i = i + 1;
}
for (let i = 0; i < 10; i = i + 1) {
print(i)
}
+2
View File
@@ -0,0 +1,2 @@
fn add(a, b) { return a + b; }
fn mul(a, b) { return a * b; }
+4
View File
@@ -0,0 +1,4 @@
let obj = { name: "aster", version: 1 }
print(obj.name)
obj.version = obj.version + 1
print(obj.version)
+5
View File
@@ -0,0 +1,5 @@
let a = 7
let b = a % 3
print("b=", b)
a %= 4
print("a=", a)
+209
View File
@@ -0,0 +1,209 @@
// ============================================================================
// 实用脚本集合:文本统计、数组工具、排序、数据转换
// 运行: cargo run -- examples/practical.ast
// ============================================================================
// ============================================================================
// 1. 文本统计工具
// ============================================================================
fn count_chars(s) {
return len(s)
}
fn count_words(s) {
let count = 0
let in_word = false
for (c in s) {
if (c == " " || c == "\n" || c == "\t") {
in_word = false
} else if (!in_word) {
count = count + 1
in_word = true
}
}
return count
}
fn text_stats(text) {
print("=== Text Stats ===")
print("chars:", count_chars(text))
print("words:", count_words(text))
}
let sample = "hello world from Aster scripting language"
text_stats(sample)
// ============================================================================
// 2. 数组工具函数 (map / filter / reduce)
// ============================================================================
fn map(arr, func) {
let result = []
for (x in arr) {
push(result, func(x))
}
return result
}
fn filter(arr, pred) {
let result = []
for (x in arr) {
if (pred(x)) {
push(result, x)
}
}
return result
}
fn reduce(arr, func, init) {
let acc = init
for (x in arr) {
acc = func(acc, x)
}
return acc
}
let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let doubled = map(nums, fn(x) { return x * 2 })
print("map (*2):", doubled)
let evens = filter(nums, fn(x) { return x % 2 == 0 })
print("filter (even):", evens)
let sum = reduce(nums, fn(a, b) { return a + b }, 0)
print("reduce (sum):", sum)
// 链式: 偶数平方和
let even_squares = map(
filter(nums, fn(x) { return x % 2 == 0 }),
fn(x) { return x * x }
)
let sum_squares = reduce(even_squares, fn(a, b) { return a + b }, 0)
print("sum of even squares:", sum_squares)
// ============================================================================
// 3. 冒泡排序
// ============================================================================
fn sort(arr) {
let n = len(arr)
let i = 0
while (i < n - 1) {
let j = 0
while (j < n - i - 1) {
if (arr[j] > arr[j + 1]) {
let tmp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = tmp
}
j = j + 1
}
i = i + 1
}
return arr
}
let unsorted = [42, 17, 8, 99, 3, 56]
print("unsorted:", unsorted)
print("sorted:", sort(unsorted))
// ============================================================================
// 4. 数据转换 (类 JSON 处理)
// ============================================================================
let users = [
{ name: "Alice", age: 28, active: true },
{ name: "Bob", age: 35, active: false },
{ name: "Carol", age: 22, active: true },
{ name: "Dave", age: 40, active: true },
]
// 找出活跃用户的名字,按年龄排序
let active = filter(users, fn(u) { return u["active"] })
print("active users:", len(active))
// 计算平均年龄
let total_age = reduce(users, fn(acc, u) { return acc + u["age"] }, 0)
print("avg age:", total_age / len(users))
// 生成名字列表
let names = map(users, fn(u) { return u["name"] })
print("names:", names)
// ============================================================================
// 5. 斐波那契 (递归 + 迭代 + 缓存对比)
// ============================================================================
fn fib_rec(n) {
if (n <= 1) { return n }
return fib_rec(n - 1) + fib_rec(n - 2)
}
fn fib_iter(n) {
if (n <= 1) { return n }
let a = 0
let b = 1
let i = 2
while (i <= n) {
let tmp = a + b
a = b
b = tmp
i = i + 1
}
return b
}
print("fib_rec(20):", fib_rec(20))
print("fib_iter(20):", fib_iter(20))
// ============================================================================
// 6. 回文检测
// ============================================================================
fn is_palindrome(s) {
let n = len(s)
let i = 0
while (i < n / 2) {
if (s[i] != s[n - 1 - i]) {
return false
}
i = i + 1
}
return true
}
print("is_palindrome('radar'):", is_palindrome("radar"))
print("is_palindrome('hello'):", is_palindrome("hello"))
// ============================================================================
// 7. 字符串工具(split / trim / substring / replace
// ============================================================================
print("=== string utils ===")
let csv = "Alice,Bob,Carol,Dave"
let parts = split(csv, ",")
print("split CSV:", parts)
print("names count:", len(parts))
let padded = " hello "
print("trim:", "'" + trim(padded) + "'")
print("substring('hello', 1, 3):", substring("hello", 1, 3))
let template = "Hello, NAME!"
let greeting = replace(template, "NAME", "Aster")
print("replace:", greeting)
print("contains('hello', 'ell'):", contains("hello", "ell"))
print("upper:", upper("hello"))
print("lower:", lower("HELLO"))
print("starts_with('hello', 'he'):", starts_with("hello", "he"))
print("ends_with('hello', 'lo'):", ends_with("hello", "lo"))
+40
View File
@@ -0,0 +1,40 @@
// 压测:循环、递归、闭包
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 t0 = clock()
// 1. 循环压测:100万次算术
let sum = 0
let i = 0
while (i < 1000000) {
sum = sum + i
i = i + 1
}
print("loop 1M:", sum)
// 2. 递归压测:fib(25)
let f = fib(25)
print("fib(25):", f)
// 3. 闭包压测:100万次调用
let add10 = make_adder(10)
let j = 0
let total = 0
while (j < 1000000) {
total = add10(j)
j = j + 1
}
print("closure 1M calls:", total)
let t1 = clock()
print("total time (s):", t1 - t0)
+4
View File
@@ -0,0 +1,4 @@
let math = require("math_mod.ast");
print(math.add(10, 32));
print(math.mul(6, 7));
print(math.add(math.mul(2, 3), 1));