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:
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
let name = io.input("Your name: ");
|
||||
io.print("Hello, " + name)
|
||||
@@ -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)
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fn add(a, b) { return a + b; }
|
||||
fn mul(a, b) { return a * b; }
|
||||
@@ -0,0 +1,4 @@
|
||||
let obj = { name: "aster", version: 1 }
|
||||
print(obj.name)
|
||||
obj.version = obj.version + 1
|
||||
print(obj.version)
|
||||
@@ -0,0 +1,5 @@
|
||||
let a = 7
|
||||
let b = a % 3
|
||||
print("b=", b)
|
||||
a %= 4
|
||||
print("a=", a)
|
||||
@@ -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"))
|
||||
@@ -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)
|
||||
@@ -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));
|
||||
Reference in New Issue
Block a user