diff --git a/SPL.md b/SPL.md index dcb0c5d..d762776 100644 --- a/SPL.md +++ b/SPL.md @@ -1,13 +1,13 @@ -# SPL — Self-bootstrapping/System Programming Language +# SPL - Self-bootstrapping/System Programming Language ## 项目概述 SPL是一个从零构建的自举编译器项目。引导链: ``` -stage0/spl_vm.c — SIR 虚拟机 (C 语言实现) -stage1/splc0.c — SPL->SIR 编译器 (C 语言实现,引导用) -stage1/splc1.spl — SPL->SIR 编译器 (SPL 语言实现,自举第一版) +stage0/spl_vm.c - SIR 虚拟机 (C 语言实现) +stage1/splc0.c - SPL->SIR 编译器 (C 语言实现,引导用) +stage1/splc1.spl - SPL->SIR 编译器 (SPL 语言实现,自举第一版) ...将来... ``` @@ -56,7 +56,7 @@ DirectiveBlock <- DirectiveHead Block (* @init { } / #test { } *) # ================================================================ -# comptime — 编译期执行 / 断言 (仅容器层) +# comptime - 编译期执行 / 断言 (仅容器层) # ================================================================ ComptimeStmt @@ -88,6 +88,7 @@ TypeDecl MemberDecl <- IDENTIFIER (COLON TypeExpr)? (COMMA / SEMICOLON)? + (* 聚合成员分隔: `,` 与 `;` 均可。当前 `;` 路径不稳定,测试以 `,` 为准,`;` 仅作兼容验证。 *) # ================================================================ # 类型表达式 (Type Expression, LL(1), 无左递归) @@ -98,6 +99,7 @@ TypeExpr <- PrefixTypeOp* AttrList? TypeBase TypeBase <- FnTypeExpr / TypePath + / KEYWORD_shape LBRACE ContainerDeclaration* RBRACE (* TODO *) / KEYWORD_struct LBRACE ContainerDeclaration* RBRACE / KEYWORD_union LBRACE ContainerDeclaration* RBRACE / KEYWORD_enum LBRACE ContainerDeclaration* RBRACE @@ -141,7 +143,7 @@ ConstDecl # ================================================================ -# 块 / 语句层 (Block & Statement — 仅函数体内) +# 块 / 语句层 (Block & Statement - 仅函数体内) # ================================================================ Block <- LBRACE BlockItem* Expr? RBRACE @@ -159,6 +161,9 @@ Statement (* LL(1): 14 分支互 / BreakStatement / ContinueStatement / DeferStatement + / TryStatement (* TODO *) + / CatchStatement (* TODO *) + / ErrDeferStatement (* TODO *) / VarDecl / ConstDecl / TypeDecl @@ -234,8 +239,7 @@ ShiftExpr <- AddExpr ((L_ARROW2 / R_ARROW2) AddExpr)* AddExpr <- MulExpr ((PLUS / MINUS) MulExpr)* MulExpr <- PrefixExpr ((ASTERISK / SLASH / PERCENT) PrefixExpr)* PrefixExpr <- PrefixOp* PostfixExpr -PrefixOp <- MINUS / BANG / TILDE / AMPERSAND / ASTERISK - +PrefixOp <- MINUS / BANG / TILDE / AMPERSAND # ---- 后缀 ---- @@ -389,19 +393,29 @@ FLOAT <- [0-9]+ '.' [0-9]+ CHAR_LITERAL <- "'" (CHAR_PLAIN / CHAR_ESCAPE) "'" CHAR_PLAIN <- [^\\'\n] CHAR_ESCAPE <- '\\' [ntr\\'"0] + / '\\x' [0-9a-fA-F] [0-9a-fA-F] STRING_LITERAL <- '"' (STRING_CHUNK)* '"' STRING_CHUNK <- [^\\"\n]+ / '\\' [ntr\\'"0] + / '\\x' [0-9a-fA-F] [0-9a-fA-F] LINE_COMMENT <- '//' [^\n]* -BLOCK_COMMENT <- '/*' (!'*/' .)* '*/' +BLOCK_COMMENT <- '/*' (BLOCK_COMMENT / !'*/' .)* '*/' (* 支持嵌套 *) eof <- !. ``` +## 当前阶段暂不支持(stage1 引导实现限制) + +以下语法/特性在当前引导阶段**暂不实现**,使用时报编译错误("not implemented")。 +实现推进时按序补齐,并同步更新本清单与测试。 + +- **comptime 语句**: `comptime { }` / `comptime expr;`(spl_ast.c 报 "not implemented: comptime statement") +- **f32 类型**: `var x: f32` 变量声明暂不可用(缺 float 转换指令,f64 字面量->f32 需截断),见 BUGS.md #1;f64 类型已完整支持 +- **@ / # 指令块**: `@init { }` / `#test { }`(spl_ast.c 报 "not implemented: @/# directive block") +- **嵌套类型路径构造**: 类型体内嵌套类型可定义,但 `Shape.Inner { ... }` 的路径构造未实现 + ## TODO -```spl -// 约束关键字,语义是`类型子集形状` type name = shape { ... } // 默认字段 @@ -443,7 +457,20 @@ DirectiveBlock @id { } / #id { } 为扩展占位,无预定义行为。未识 @name(args) / #name(args): 内置调用,出现在表达式位置。 -语义: 完全由语言版本或库注册决定。当前所有均视为未识别,产生警告 (宽松) 或错误 (严格)。 +语义: 由编译器的内置函数注册表决定(stage1/spl_builtin.h/c)。未注册名称在宽松模式下警告、严格模式下错误。 + +### 内置函数注册表 + +| 内置 | 参数 | 返回 | 状态 | +|---|---|---|---| +| @sizeof(T) | 类型表达式 | usize | 已实现 | +| @bitsizeof(T) | 类型表达式 | usize | 已实现 | +| @alignof(T) | 类型表达式 | usize | 已实现 | +| @offsetof(T, field) | 类型表达式 + 字段标识符 | usize | 已实现 | +| @field_count(T) | 类型表达式 | usize | 已实现 | +| @dbg(args...) | 表达式列表 | void | 已实现(发射断点) | +| @assert(cond) | bool 表达式 | void | 已实现(失败 trap) | +| @import(path) | 字符串字面量 | 模块 | 预留,未实现 | ## 函数 @@ -459,7 +486,7 @@ AttrList? fn IDENTIFIER ( ParamDeclList ) TypeExpr? ( ; | Block ) ## 类型声明与聚合体 ### 别名 -type T = TypeExpr — 完全同义。 +type T = TypeExpr - 完全同义。 ### struct 字段必须 name: Type,不可省略。名称唯一。 @@ -798,13 +825,13 @@ T (任意) T 是 无 相同类型 *_ *T 是 警告: “不安全的指针重解释” [N]T []T 是 无 数组到切片强制转换 整数字面量 整数类型 U 是 (若值在 U 范围内) 无 字面量自动拓宽 (含字符 'c' 视为 u8) -i32 i64 否 — 需显式 as i64,防止意外 -i64 i32 否 — 窄化必须显式 +i32 i64 否 - 需显式 as i64,防止意外 +i64 i32 否 - 窄化必须显式 null *T / []T 是 无 空指针/空切片初始化、比较、赋值、聚合字段 浮点字面量 f32 是 (值可表示则) 无 -f64 f32 否 — 窄化需显式 -bool 整数 否 — -整数 bool 否 — +f64 f32 否 - 窄化需显式 +bool 整数 否 - +整数 bool 否 - 注: @@ -1179,11 +1206,11 @@ CONSTANT ← INTEGER | FLOAT | STRING | 'true' | 'false' | 'null' | 'undefine 标记附加在函数定义前,用逗号分隔。所有标记均不影响 IR 控制流语义,仅向后端传递元数据。 标记 参数 含义 使用场景 -!link("export") — 符号对外可见 库的公开 API -!link("import") — 符号来自外部模块 调用外部库 -!link("weak") — 弱符号 可被覆盖的默认实现 +!link("export") - 符号对外可见 库的公开 API +!link("import") - 符号来自外部模块 调用外部库 +!link("weak") - 弱符号 可被覆盖的默认实现 !abi("C") 调用约定名称 指定跨函数调用的 ABI 与 C 代码交互 !symbol("name") 字符串 自定义导出符号名 避免名称混淆 -!naked — 无函数序言/尾声 中断向量、系统调用包装 -!noinline — 禁止内联 调试或特殊性能需求 -!alwaysinline — 总是内联 简单的包装函数 +!naked - 无函数序言/尾声 中断向量、系统调用包装 +!noinline - 禁止内联 调试或特殊性能需求 +!alwaysinline - 总是内联 简单的包装函数 diff --git a/build.py b/build.py index df2c2b7..4bf42bd 100644 --- a/build.py +++ b/build.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""SPL build system — .c → .o → exe, .spl → .sir, deps auto-resolved.""" +"""SPL build system - .c -> .o -> exe, .spl -> .sir, deps auto-resolved.""" import argparse import hashlib @@ -304,13 +304,13 @@ def clean(): print(f" CLEAN {BUILD_DIR}") def list_targets(desc): - print("Executables (.c → .o → exe):") + print("Executables (.c -> .o -> exe):") for name, sources in desc.get("exe", {}).items(): print(f" {name}") for s in sources: print(f" {s}") if desc.get("spl"): - print("\nSPL programs (.spl → .sir via pipeline):") + print("\nSPL programs (.spl -> .sir via pipeline):") for name, info in desc["spl"].items(): pl_name = info.get("pipeline", "-") print(f" {name} pipeline={pl_name} src={info['src']}") @@ -366,7 +366,7 @@ def main(): save_cache(cache) return rc - # Pipeline: build compiler → compile .spl → run via runner + # Pipeline: build compiler -> compile .spl -> run via runner if args.command == "pipeline": desc = load_desc(); cache = load_cache() pl = desc.get("pipeline", {}).get(args.name) @@ -384,7 +384,7 @@ def main(): if not build(compiler, desc, cache, False): return 1 if not build(runner, desc, cache, False): return 1 - # Compile .spl → .sir (temp name = src path hash) + # Compile .spl -> .sir (temp name = src path hash) sir_name = "pipeline_" + hashlib.sha256(str(src_path).encode()).hexdigest()[:8] if not compile_spl(sir_name, args.src, compiler, desc, cache, False): return 1 diff --git a/project_desc.py b/project_desc.py index 000d8ef..e66f92f 100644 --- a/project_desc.py +++ b/project_desc.py @@ -5,19 +5,19 @@ vm = [ ] splc0_part = [ - "stage1/spl_ir.c", + # "stage1/spl_ir.c", "stage1/spl_ast.c", "stage1/spl_lexer.c", "stage1/spl_dumptree.c", - "stage1/spl_type.c", - "stage1/spl_sema.c", - "stage1/spl_ast2ir.c", - "stage1/spl_ir2vm.c", + # "stage1/spl_type.c", + # "stage1/spl_sema.c", + # "stage1/spl_builtin.c", + # "stage1/spl_ast2ir.c", + # "stage1/spl_ir2vm.c", ] exe = { "spl_cli": ["stage0/spl_cli.c"] + vm, - "splc_cli": ["stage1/splc_cli.c"] + vm, "splc0": ["stage1/splc0.c"] + vm + splc0_part, "test": ["stage0/test_spl_vm.c"] + vm, "spl_disasm": ["stage0/spl_disasm.c"] + vm, @@ -25,23 +25,23 @@ exe = { pipeline = { "splc0b": {"compiler": "splc0", "runner": "spl_cli"}, - "splc0r": {"compiler": "splc0", "runner": "splc_cli"}, + "splc0r": {"compiler": "splc0", "runner": "spl_cli"}, "splc0d": {"compiler": "splc0", "runner": "spl_disasm"}, - "splc1b": {"compiler": "splc0", "runner": "splc_cli"}, - "splc1r": {"compiler": "splc1", "runner": "splc_cli"}, + "splc1b": {"compiler": "splc0", "runner": "spl_cli"}, + "splc1r": {"compiler": "splc1", "runner": "spl_cli"}, "splc1d": {"compiler": "splc1", "runner": "spl_disasm"}, - "splc2b": {"compiler": "splc1", "runner": "splc_cli"}, - "splc2r": {"compiler": "splc2", "runner": "splc_cli"}, + "splc2b": {"compiler": "splc1", "runner": "spl_cli"}, + "splc2r": {"compiler": "splc2", "runner": "spl_cli"}, "splc2d": {"compiler": "splc2", "runner": "spl_disasm"}, - "splc3b": {"compiler": "splc2", "runner": "splc_cli"}, - "splc3r": {"compiler": "splc3", "runner": "splc_cli"}, + "splc3b": {"compiler": "splc2", "runner": "spl_cli"}, + "splc3r": {"compiler": "splc3", "runner": "spl_cli"}, "splc3d": {"compiler": "splc3", "runner": "spl_disasm"}, - "splc4b": {"compiler": "splc3", "runner": "splc_cli"}, - "splc4r": {"compiler": "splc4", "runner": "splc_cli"}, + "splc4b": {"compiler": "splc3", "runner": "spl_cli"}, + "splc4r": {"compiler": "splc4", "runner": "spl_cli"}, "splc4d": {"compiler": "splc4", "runner": "spl_disasm"}, } diff --git a/stage0/include/log.h b/stage0/include/log.h index c827e73..35a820c 100644 --- a/stage0/include/log.h +++ b/stage0/include/log.h @@ -14,7 +14,7 @@ #include #define log_vsnprintf vsnprintf #define log_puts puts -#define log_abort abort +#define log_abort() exit(1) #endif #ifdef __GNUC__ // GCC, Clang diff --git a/stage0/spl_cli.c b/stage0/spl_cli.c index 0c68613..446cc46 100644 --- a/stage0/spl_cli.c +++ b/stage0/spl_cli.c @@ -1,4 +1,4 @@ -/* spl_cli.c — SIR VM launcher + gdb-style interactive debugger +/* spl_cli.c SIR VM launcher + gdb-style interactive debugger * * Usage: spl_cli [options] [args...] * -d, --debug stack-canary checks diff --git a/stage0/spl_disasm.c b/stage0/spl_disasm.c index b09d06c..de59f66 100644 --- a/stage0/spl_disasm.c +++ b/stage0/spl_disasm.c @@ -1,4 +1,4 @@ -/* spl_disasm.c — SIR bytecode disassembler +/* spl_disasm.c - SIR bytecode disassembler * * Usage: spl_disasm */ diff --git a/stage0/spl_mcode.c b/stage0/spl_mcode.c index 4508b6a..54b9dda 100644 --- a/stage0/spl_mcode.c +++ b/stage0/spl_mcode.c @@ -1,4 +1,4 @@ -/* spl_mcode.c — SPL VM machine code binary serialization, deserialization, and utilities +/* spl_mcode.c - SPL VM machine code binary serialization, deserialization, and utilities * * Binary format (all metadata fields are spl_val_t = uint64_t LE): * [HEADER] magic(8) nfuncs(8) ninsns(8) nnatives(8) nstrs(8) ndata(8) diff --git a/stage0/spl_syscall.c b/stage0/spl_syscall.c index 08dfa57..14dfb08 100644 --- a/stage0/spl_syscall.c +++ b/stage0/spl_syscall.c @@ -1,4 +1,4 @@ -/* spl_syscall.c — built-in syscall implementations + registration +/* spl_syscall.c - built-in syscall implementations + registration * * All syscalls validate nargs, cast spl_val_t args to the expected C types, * execute, and return the result as spl_val_t. @@ -23,7 +23,7 @@ * Each SYSCALL_N macro: * 1. Validates nargs (prints error and returns -1 on mismatch) * 2. Casts args[n] from spl_val_t to the specified C type via - * (type)(uintptr_t) — this handles both integer and pointer types + * (type)(uintptr_t) - this handles both integer and pointer types * 3. Evaluates the expression and returns the result as spl_val_t * ================================================================= */ @@ -80,34 +80,34 @@ * OS syscalls * ================================================================= */ -/* vm_exit — terminate process with the given exit code */ +/* vm_exit - terminate process with the given exit code */ SYSCALL_1(vm_exit, int, (exit(a1), (spl_val_t)0)) -/* vm_putchar — write a single character to stdout */ +/* vm_putchar - write a single character to stdout */ SYSCALL_1(vm_putchar, int, putchar(a1)) -/* vm_getchar — read a single character from stdin */ +/* vm_getchar - read a single character from stdin */ SYSCALL_0(vm_getchar, getchar()) -/* vm_putint — print an integer to stdout */ +/* vm_putint - print an integer to stdout */ SYSCALL_1(vm_putint, int, (fprintf(stdout, "%d", a1), (spl_val_t)0)) -/* vm_putstr — print a string to stdout (no trailing newline) */ +/* vm_putstr - print a string to stdout (no trailing newline) */ SYSCALL_1(vm_putstr, const char *, (fputs(a1, stdout), (spl_val_t)0)) -/* vm_fopen — open a file, returns FILE* as spl_val_t */ +/* vm_fopen - open a file, returns FILE* as spl_val_t */ SYSCALL_2(vm_fopen, const char *, const char *, (uintptr_t)fopen(a1, a2)) -/* vm_fclose — close a file, returns 0 on success */ +/* vm_fclose - close a file, returns 0 on success */ SYSCALL_1(vm_fclose, FILE *, fclose(a1)) -/* vm_fread — read from file, returns number of items read */ +/* vm_fread - read from file, returns number of items read */ SYSCALL_4(vm_fread, void *, size_t, size_t, FILE *, fread(a1, a2, a3, a4)) -/* vm_fwrite — write to file, returns number of items written */ +/* vm_fwrite - write to file, returns number of items written */ SYSCALL_4(vm_fwrite, const void *, size_t, size_t, FILE *, fwrite(a1, a2, a3, a4)) -/* vm_fsize — get file size in bytes */ +/* vm_fsize - get file size in bytes */ static spl_val_t vm_fsize(int nargs, spl_val_t *args) { CHECK_NARGS("vm_fsize", 1); FILE *f = (FILE *)(uintptr_t)args[0]; @@ -122,7 +122,7 @@ SYSCALL_0(vm_stdin, stdin) SYSCALL_0(vm_stdout, stdout) SYSCALL_0(vm_stderr, stderr) -/* vm_read_file — read entire file into a malloc'd, null-terminated buffer */ +/* vm_read_file - read entire file into a malloc'd, null-terminated buffer */ static spl_val_t vm_read_file(int nargs, spl_val_t *args) { CHECK_NARGS("vm_read_file", 1); const char *path = (const char *)(uintptr_t)args[0]; @@ -149,22 +149,22 @@ static spl_val_t vm_read_file(int nargs, spl_val_t *args) { return (spl_val_t)(uintptr_t)buf; } -/* vm_alloc — allocate memory (malloc) */ +/* vm_alloc - allocate memory (malloc) */ SYSCALL_1(vm_alloc, size_t, (uintptr_t)malloc(a1)) -/* vm_free — free memory */ +/* vm_free - free memory */ SYSCALL_1(vm_free, void *, (free(a1), (spl_val_t)0)) -/* vm_realloc — reallocate memory (realloc) */ +/* vm_realloc - reallocate memory (realloc) */ SYSCALL_2(vm_realloc, void *, size_t, (uintptr_t)realloc(a1, a2)) -/* vm_strlen — get string length */ +/* vm_strlen - get string length */ SYSCALL_1(vm_strlen, const char *, strlen(a1)) -/* vm_strcmp — compare two strings */ +/* vm_strcmp - compare two strings */ SYSCALL_2(vm_strcmp, const char *, const char *, strcmp(a1, a2)) -/* vm_memcpy — copy memory, returns dst */ +/* vm_memcpy - copy memory, returns dst */ SYSCALL_3(vm_memcpy, void *, const void *, size_t, (memcpy(a1, a2, a3), (uintptr_t)a1)) static spl_val_t vm_printf(int nargs, spl_val_t *args) { @@ -228,13 +228,13 @@ static spl_val_t vm_printf(int nargs, spl_val_t *args) { } /* ================================================================= - * VM syscalls (for comptime — compile-time code execution) + * VM syscalls (for comptime - compile-time code execution) * * These let SPL code create isolated sub-VMs, load compiled .sir * programs into them, push arguments, call functions, and run. * ================================================================= */ -/* vm_new — create a new sub-VM instance, returns spl_vm_t* */ +/* vm_new - create a new sub-VM instance, returns spl_vm_t* */ static spl_val_t vm_new(int nargs, spl_val_t *args) { CHECK_NARGS("vm_new", 0); (void)args; @@ -245,7 +245,7 @@ static spl_val_t vm_new(int nargs, spl_val_t *args) { return (spl_val_t)(uintptr_t)vm; } -/* vm_drop — destroy a sub-VM and its loaded program */ +/* vm_drop - destroy a sub-VM and its loaded program */ static spl_val_t vm_drop(int nargs, spl_val_t *args) { CHECK_NARGS("vm_drop", 1); spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; @@ -261,7 +261,7 @@ static spl_val_t vm_drop(int nargs, spl_val_t *args) { return 0; } -/* vm_load — load a .sir file, register syscalls, return spl_prog_t* */ +/* vm_load - load a .sir file, register syscalls, return spl_prog_t* */ static spl_val_t vm_load(int nargs, spl_val_t *args) { CHECK_NARGS("vm_load", 2); spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; @@ -285,7 +285,7 @@ static spl_val_t vm_load(int nargs, spl_val_t *args) { return (spl_val_t)(uintptr_t)prog; } -/* vm_push — push a value onto the sub-VM's stack (for passing arguments) */ +/* vm_push - push a value onto the sub-VM's stack (for passing arguments) */ static spl_val_t vm_push(int nargs, spl_val_t *args) { CHECK_NARGS("vm_push", 2); spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; @@ -300,7 +300,7 @@ static spl_val_t vm_push(int nargs, spl_val_t *args) { return 0; } -/* vm_call — call a function by name with pre-pushed arguments +/* vm_call - call a function by name with pre-pushed arguments * * Args (3): vm, function_name, nargs * The arguments should already be on the sub-VM's stack via vm_push. @@ -347,7 +347,7 @@ static spl_val_t vm_call(int nargs, spl_val_t *args) { return 0; } -/* vm_run — run a sub-VM to completion, returns exit_code */ +/* vm_run - run a sub-VM to completion, returns exit_code */ SYSCALL_1(vm_run, spl_vm_t *, spl_vm_run_until(a1, 0)) /* ================================================================= diff --git a/stage0/spl_syscall.h b/stage0/spl_syscall.h index f6e023d..66718fd 100644 --- a/stage0/spl_syscall.h +++ b/stage0/spl_syscall.h @@ -1,4 +1,4 @@ -/* spl_syscall.h — built-in syscall layer for SIR VM +/* spl_syscall.h - built-in syscall layer for SIR VM * * Provides I/O native functions (putchar, getchar, file ops, etc.) * that compiled SPL programs can call via NCALL. diff --git a/stage0/spl_vm.c b/stage0/spl_vm.c index 9bc60a4..04e6fa1 100644 --- a/stage0/spl_vm.c +++ b/stage0/spl_vm.c @@ -1,4 +1,4 @@ -/* spl_vm.c — SIR step-by-step interpreter +/* spl_vm.c - SIR step-by-step interpreter * * Implements the spl_vm.h API with macro-based type dispatch to * eliminate repetitive per-type switch cases. @@ -109,13 +109,13 @@ static int spl_type_size(spl_type_t t) { /* ================================================================ * Type-dispatch macros for arithmetic / comparison * - * ARITH_BINOP — ADD / SUB / MUL (two's complement: op same for + * ARITH_BINOP - ADD / SUB / MUL (two's complement: op same for * signed and unsigned at the same bit-width) - * DIV_REM_S — signed division / remainder - * DIV_REM_U — unsigned division / remainder - * CMP_ALL — EQ / NE (bitwise compare, also handles floats) - * CMP_S — signed ordering (<, <=, >, >=) - * CMP_U — unsigned ordering + * DIV_REM_S - signed division / remainder + * DIV_REM_U - unsigned division / remainder + * CMP_ALL - EQ / NE (bitwise compare, also handles floats) + * CMP_S - signed ordering (<, <=, >, >=) + * CMP_U - unsigned ordering * ================================================================ */ #define ARITH_BINOP(OP) \ @@ -177,7 +177,7 @@ static int spl_type_size(spl_type_t t) { PUSH(_r); \ } while (0) -/* signed division / remainder — all types cast to signed */ +/* signed division / remainder - all types cast to signed */ #define DIV_REM_S(OP) \ do { \ spl_val_t _b = POP(), _a = POP(); \ @@ -280,7 +280,7 @@ static int spl_type_size(spl_type_t t) { PUSH(_r); \ } while (0) -/* CMP_ALL — equality comparisons (all types, floats via memcpy) */ +/* CMP_ALL - equality comparisons (all types, floats via memcpy) */ #define CMP_ALL(OP) \ do { \ spl_val_t _b = POP(), _a = POP(); \ @@ -334,7 +334,7 @@ static int spl_type_size(spl_type_t t) { PUSH(_r); \ } while (0) -/* CMP_S — signed ordering (all ints cast to signed, floats OK) */ +/* CMP_S - signed ordering (all ints cast to signed, floats OK) */ #define CMP_S(OP) \ do { \ spl_val_t _b = POP(), _a = POP(); \ @@ -388,7 +388,7 @@ static int spl_type_size(spl_type_t t) { PUSH(_r); \ } while (0) -/* CMP_U — unsigned ordering (all ints cast to unsigned, no float) */ +/* CMP_U - unsigned ordering (all ints cast to unsigned, no float) */ #define CMP_U(OP) \ do { \ spl_val_t _b = POP(), _a = POP(); \ @@ -726,7 +726,7 @@ int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv, } /* ================================================================ - * spl_vm_run_once — execute one instruction + * spl_vm_run_once - execute one instruction * * Returns: 0 = still running, 1 = halted, 2 = breakpoint (SPL_DBG), -1 = error * ================================================================ */ @@ -745,7 +745,7 @@ int spl_vm_run_once(spl_vm_t *vm) { return -1; } - /* 断点:即将执行的指令命中 ip 断点 → 暂停(返回 2)。 + /* 断点:即将执行的指令命中 ip 断点 -> 暂停(返回 2)。 * skip_bp 置位时执行当前指令(continue 越过当前断点)。 */ if (ip_breakpoint_hit(vm)) { if (vm->skip_bp) { diff --git a/stage0/spl_vm.h b/stage0/spl_vm.h index 15cdd66..bb93c67 100644 --- a/stage0/spl_vm.h +++ b/stage0/spl_vm.h @@ -1,4 +1,4 @@ -/* spl_vm.h — SIR interpreter */ +/* spl_vm.h - SIR interpreter */ #ifndef __SPL_VM_H__ #define __SPL_VM_H__ diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index 477b1bc..c42aaa8 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -1,14 +1,19 @@ // WRITE BY AI -/* spl_ast.c SPL AST 模块:LL(1) 递归下降解析+ valid/dump/drop */ +/* spl_ast.c SPL AST 模块:LL(1) 递归下降解析 + valid/dump/drop + * + * 设计:节点 kind 是唯一身份(扁平化)。无 `SPL_AST_EXPR`/`SPL_AST_BLOCK_ITEM` + * 等外壳类别--每个表达式/语句/类型节点直接用具体 kind。 + * 子节点以 spl_ast_node_ref 引用(ref 0 = 空),union 数据由 kind 决定解释。 + */ #include "spl_ast.h" +#include "spl_dbg.h" #include "spl_dumptree.h" -#include +#include "spl_tok.h" #include #include #include -/* 从 token 复制 lexeme(带长度,NUL 终止),供 AST 字符串字段持有 */ static char *sdupn(const char *s, usize n) { char *r = malloc(n + 1); if (!r) @@ -18,46 +23,76 @@ static char *sdupn(const char *s, usize n) { return r; } -/* ================================================================ - * 内联节点解读上下 * - * 内联子节点(attr_item/param_decl/prefix_expr/postfix_expr/primary_expr/ - * packed_expr/aggregate_init_item/type_atom/prefix_type)不暴露独立 kind * 创建时用占位 - * kind,解读(valid/dump/drop)一律按父字段引用类型递归 * - * ================================================================ */ -typedef enum { - CTX_CONTAINER, /* container_item */ - CTX_DECL, /* fn/type/var/const/member 声明*/ - CTX_ATTR_ITEM, /* attr_item */ - CTX_PARAM, /* param_decl */ - CTX_BLOCK_ITEM, /* block_item / 尾表达式 */ - CTX_EXPR, /* expr */ - CTX_PREFIX, /* prefix_expr */ - CTX_POSTFIX, /* postfix_expr */ - CTX_PRIMARY, /* primary_expr */ - CTX_PACKED, /* packed_expr */ - CTX_AGG_ITEM, /* aggregate_init_item */ - CTX_TYPE_EXPR, /* type_expr */ - CTX_TYPE_ATOM, /* type_atom */ - CTX_PREFIX_TYPE, /* prefix_type */ -} walk_ctx_t; +const char *spl_ast_kind_name(spl_ast_node_kind_t kind) { + static const char *const names[] = { +#define X(a, b, c) #c, + SPL_AST_KIND_TABLE +#undef X + }; + if ((usize)kind < sizeof(names) / sizeof(names[0])) + return names[kind]; + return "?"; +} typedef struct { spl_ast_t *ast; usize pos; int failed; - int stop_as; /* 0 时后缀表达式不KW_AS(for 头部序列专用*/ - int stop_agg; /* 0 IDENT '{' 不作结构体字面量(if/while/match 头部专用*/ + int stop_as; /* 0 时后缀表达式不KW_AS(for 头部序列专用) */ + int stop_agg; /* 0 IDENT '{' 不作结构体字面量(if/while/match 头部专用) */ } parser_t; +static inline int is_trivia(spl_tok_type_t t) { return t == TOK_ENDLINE || t == TOK_LINE_COMMENT; } + +static inline const spl_tok_t *peek(parser_t *p) { + usize n = vec_size(p->ast->input); + usize i = p->pos; + while (i < n && is_trivia(vec_at(p->ast->input, i).type)) + i++; + p->pos = i; + if (i >= n) + return NULL; + return &vec_at(p->ast->input, i); +} + +static inline const spl_tok_t *advance(parser_t *p) { + const spl_tok_t *t = peek(p); + if (t && t->type != TOK_EOF) + p->pos++; + return t; +} + +static inline spl_ast_node_t *node_at(spl_ast_t *ast, spl_ast_node_ref_t ref) { + return &ast->node_buckets.data[ref]; +} + +static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const spl_tok_t *tok) { + spl_ast_node_t n = {0}; + n.kind = kind; + if (tok) { + n.dbg.dbg_name = spl_ast_kind_name(kind); + n.dbg.fpath = tok->fname; + n.dbg.line = (int)tok->line; + n.dbg.col = (int)tok->col; + } + vec_push(p->ast->node_buckets, n); + return p->ast->node_buckets.size - 1; +} + +static spl_ast_node_ref_t mk_bin(parser_t *p, const spl_tok_t *loc, spl_ast_node_kind_t op, + spl_ast_node_ref_t left, spl_ast_node_ref_t right) { + spl_ast_node_ref_t ref = new_node(p, op, loc); + node_at(p->ast, ref)->op_expr.left = left; + node_at(p->ast, ref)->op_expr.right = right; + return ref; +} + /* 前向声明 */ -static spl_tok_t *peek(parser_t *p); -static spl_tok_t *advance(parser_t *p); -static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, spl_tok_t *loc); -static spl_ast_node_t *node_at(spl_ast_t *ast, spl_ast_node_ref_t ref); static spl_ast_node_ref_t parse_expr(parser_t *p); static spl_ast_node_ref_vec_t parse_expr_list(parser_t *p); static spl_ast_node_ref_vec_t parse_block(parser_t *p); static spl_ast_node_ref_t parse_type_expr(parser_t *p); +static spl_ast_node_ref_t parse_type_base(parser_t *p); static spl_ast_node_ref_t parse_statement(parser_t *p); static spl_ast_node_ref_t parse_container_declaration(parser_t *p); static spl_ast_node_ref_t parse_param_decl_impl(parser_t *p); @@ -79,7 +114,6 @@ static spl_ast_node_ref_vec_t parse_aggregate_init_body(parser_t *p); static spl_ast_node_ref_t parse_builtin(parser_t *p); static spl_ast_node_ref_t parse_array_literal(parser_t *p); static spl_ast_node_ref_t parse_if(parser_t *p); -static spl_ast_node_ref_t parse_ifvar(parser_t *p); static spl_ast_node_ref_t parse_while(parser_t *p); static spl_ast_node_ref_t parse_loop(parser_t *p); static spl_ast_node_ref_t parse_for(parser_t *p); @@ -90,140 +124,7 @@ static spl_ast_node_ref_t parse_ret(parser_t *p); static spl_ast_node_ref_t parse_break(parser_t *p); static spl_ast_node_ref_t parse_continue(parser_t *p); static spl_ast_node_ref_t parse_defer(parser_t *p); -static spl_ast_node_ref_t parse_var_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list); -static spl_ast_node_ref_t parse_const_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list); -static spl_ast_node_ref_t parse_type_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list); -static spl_ast_node_ref_t parse_fn_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list); -static spl_ast_node_ref_t parse_member_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list); -static spl_ast_node_ref_t parse_type_atom(parser_t *p); -static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx, const char *prefix, - int is_last); -static void drop_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx); -static void drop_vec(spl_ast_t *ast, spl_ast_node_ref_vec_t *vec, walk_ctx_t ctx); -static void validate_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx); -static void validate_vec(spl_ast_t *ast, spl_ast_node_ref_vec_t *vec, walk_ctx_t ctx); - -/* ================================================================ - * 词法辅助 - * ================================================================ */ - -static int is_trivia(spl_tok_type_t t) { return t == TOK_ENDLINE || t == TOK_LINE_COMMENT; } - -/* 返回下一个有token(跳trivia),不前*/ -static spl_tok_t *peek(parser_t *p) { - spl_tok_t *toks = p->ast->input.data; - usize n = p->ast->input.size; - usize i = p->pos; - while (i < n && is_trivia(toks[i].type)) - i++; - p->pos = i; - if (i >= n) - return NULL; - return &toks[i]; -} - -/* 返回当前有效 token 并前进(EOF 处不前进*/ -static spl_tok_t *advance(parser_t *p) { - spl_tok_t *t = peek(p); - if (t && t->type != TOK_EOF) - p->pos++; - return t; -} - -/* 当前有效 token 的下一个有token */ -static spl_tok_t *peek_next(parser_t *p) { - usize i = p->pos; - spl_tok_t *toks = p->ast->input.data; - usize n = p->ast->input.size; - while (i < n && is_trivia(toks[i].type)) - i++; - i++; - while (i < n && is_trivia(toks[i].type)) - i++; - if (i >= n) - return NULL; - return &toks[i]; -} - -static void parse_error(parser_t *p, spl_tok_t *t, const char *msg) { - p->failed = 1; /* 出错即停(上层循环以 !p->failed 提前退出) */ - const char *fn = (t && t->fname) ? t->fname : ""; - usize line = t ? t->line : 0; - usize col = t ? t->col : 0; - LOG_ERROR("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col, - msg); -} - -static int expect(parser_t *p, spl_tok_type_t type, const char *what) { - spl_tok_t *t = peek(p); - if (t && t->type == type) { - advance(p); - return 1; - } - parse_error(p, t, what); - return 0; -} - -/* ================================================================ - * 节点创建 - * ================================================================ */ - -static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, spl_tok_t *loc) { - spl_ast_node_t n; - memset(&n, 0, sizeof(n)); - n.kind = kind; - if (loc) { - n.loc.fname = loc->fname; - n.loc.line = loc->line; - n.loc.col = loc->col; - } - vec_push(p->ast->buckets, n); - return p->ast->buckets.size - 1; -} - -static spl_ast_node_t *node_at(spl_ast_t *ast, spl_ast_node_ref_t ref) { - return &ast->buckets.data[ref]; -} - -static spl_ast_node_ref_t mk_bin(parser_t *p, spl_tok_t *loc, int op, spl_ast_node_ref_t left, - spl_ast_node_ref_t right) { - spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR, loc); - node_at(p->ast, ref)->expr.op = op; - node_at(p->ast, ref)->expr.op_expr.left = left; - node_at(p->ast, ref)->expr.op_expr.right = right; - return ref; -} - -/* 创建 primary_expr 内联节点(占kind=SPL_AST_EXPR*/ -static spl_ast_node_ref_t mk_primary(parser_t *p, spl_tok_t *loc, int pk) { - spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR, loc); - node_at(p->ast, ref)->primary_expr.kind = pk; - return ref; -} - -/* op=PRIMARY EXPR 节点包装内联 primary/prefix/postfix 节点 */ -static spl_ast_node_ref_t wrap_expr(parser_t *p, spl_ast_node_ref_t inner) { - spl_ast_node_ref_t e = new_node(p, SPL_AST_EXPR, NULL); - node_at(p->ast, e)->loc = node_at(p->ast, inner)->loc; - node_at(p->ast, e)->expr.op = SPL_AST_PRIMARY_EXPR; - node_at(p->ast, e)->expr.op_expr.left = inner; - return e; -} - -/* 用指op(PREFIX/POSTFIX/PRIMARY)包装内联节*/ -static spl_ast_node_ref_t wrap_op_expr(parser_t *p, spl_ast_node_ref_t inner, int op) { - spl_ast_node_ref_t e = new_node(p, SPL_AST_EXPR, NULL); - node_at(p->ast, e)->loc = node_at(p->ast, inner)->loc; - node_at(p->ast, e)->expr.op = op; - node_at(p->ast, e)->expr.op_expr.left = inner; - return e; -} - -/* ================================================================ - * 字面量解 * ================================================================ */ - -/* 整数字面量:去下划线后按 0x/0o/0b/十进制解析 */ static isize parse_int_literal(const spl_tok_t *t) { char buf[128]; usize j = 0; @@ -251,7 +152,6 @@ static double parse_float_literal(const spl_tok_t *t) { return strtod(buf, NULL); } -/* 字符字面量:解码转义 */ static char parse_char_literal(const spl_tok_t *t) { const char *p = t->lexeme + 1; const char *end = t->lexeme + t->len - 1; @@ -262,8 +162,6 @@ static char parse_char_literal(const spl_tok_t *t) { return c; } -/* 字符串字面量:解码为 C 字符串副本(去引号、展开转义,malloc 分配) * - * 所有权约定:该副本spl_ast_drop STRING_LIT 节点free*/ static char *parse_string_literal(const spl_tok_t *t) { const char *p = t->lexeme + 1; const char *end = t->lexeme + t->len - 1; @@ -285,9 +183,7 @@ static char *parse_string_literal(const spl_tok_t *t) { return out; } -/* ================================================================ - * 起始判定 - * ================================================================ */ +// 起始判定 static int can_start_expr(spl_tok_type_t t) { switch (t) { @@ -315,21 +211,6 @@ static int can_start_expr(spl_tok_type_t t) { } } -static int can_start_type(spl_tok_type_t t) { - switch (t) { - case TOK_MUL: - case TOK_L_BRACKET: - case KW_FN: - case KW_VOID: - case KW_BOOL: - case KW_ANY: - case TOK_IDENT: - return 1; - default: - return 0; - } -} - static int can_start_statement(spl_tok_type_t t) { switch (t) { case KW_IF: @@ -351,45 +232,50 @@ static int can_start_statement(spl_tok_type_t t) { } } -/* ================================================================ - * 容器层:声明 - * ================================================================ */ +// 容器层声明 -/* AttrList -> 追加 attr_item 节点out(空out 不变*/ static void parse_attr_list(parser_t *p, spl_ast_node_ref_vec_t *out) { + const spl_tok_t *t = NULL; while (1) { - spl_tok_t *t = peek(p); + t = peek(p); if (!t) return; if (t->type != TOK_AT && t->type != TOK_SHARP) return; advance(p); - spl_tok_t *name = peek(p); - if (!name || name->type != TOK_IDENT) { - parse_error(p, name, "expected identifier after attribute"); + t = peek(p); + if (!t || t->type != TOK_IDENT) { + SPL_FATAL(t, "expected identifier after attribute"); return; } advance(p); - spl_ast_node_ref_t ref = new_node(p, SPL_AST_ATTR_LIST, t); - node_at(p->ast, ref)->attr_item.ident = sdupn(name->lexeme, name->len); - if (peek(p) && peek(p)->type == TOK_L_PAREN) { + spl_ast_node_ref_t ref = new_node(p, SPL_AST_ATTR_ITEM, t); + node_at(p->ast, ref)->attr_item.ident = sdupn(t->lexeme, t->len); + t = peek(p); + if (t != NULL && t->type == TOK_L_PAREN) { advance(p); spl_ast_node_ref_vec_t evec = parse_expr_list(p); node_at(p->ast, ref)->attr_item.expr_list = evec; - if (!expect(p, TOK_R_PAREN, "expected ')' to close attribute args")) - return; + t = peek(p); + if (t == NULL || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' to close attribute args"); + } + advance(p); + return; } vec_push(*out, ref); } } -/* ParamDeclList -> 追加 param_decl 节点out */ static void parse_param_list(parser_t *p, spl_ast_node_ref_vec_t *out) { while (1) { - spl_tok_t *t = peek(p); - if (!t) - return; - if (t->type == TOK_AT || t->type == TOK_SHARP || t->type == TOK_IDENT) { + const spl_tok_t *t = peek(p); + if (!t) { + break; + } + if (t->type == TOK_R_PAREN) { + break; + } else if (t->type == TOK_AT || t->type == TOK_SHARP || t->type == TOK_IDENT) { spl_ast_node_ref_t pd = parse_param_decl_impl(p); if (pd) vec_push(*out, pd); @@ -397,23 +283,26 @@ static void parse_param_list(parser_t *p, spl_ast_node_ref_vec_t *out) { advance(p); continue; } - return; + break; } else if (t->type == TOK_ELLIPSIS) { - /* 变长参数:追name=NULL、type_expr=NULL 的空 param_decl */ + // 变长参数: 追加 name=NULL、type_expr=NULL 的空 param_decl advance(p); - spl_ast_node_ref_t pd = new_node(p, SPL_AST_MEMBER_DECL, t); + spl_ast_node_ref_t pd = new_node(p, SPL_AST_PARAM_DECL, t); node_at(p->ast, pd)->param_decl.name = NULL; node_at(p->ast, pd)->param_decl.type_expr = 0; vec_push(*out, pd); if (peek(p) && peek(p)->type == TOK_COMMA) advance(p); - return; + break; } else if (t->type == KW_VOID) { - /* fn(void):无参写法 */ + // fn(void): 无参写法 advance(p); - return; + t = peek(p); + Assert(t && t->type == TOK_R_PAREN); + break; + } else { + UNREACHABLE(); } - return; } } @@ -421,16 +310,22 @@ static spl_ast_node_ref_t parse_param_decl_impl(parser_t *p) { spl_ast_node_ref_vec_t attr_list; vec_init(attr_list); parse_attr_list(p, &attr_list); - spl_tok_t *name = peek(p); + const spl_tok_t *name = peek(p); if (!name || name->type != TOK_IDENT) { - parse_error(p, name, "expected parameter name"); + SPL_FATAL(name, "expected parameter name"); return 0; } advance(p); - if (!expect(p, TOK_COLON, "expected ':' in parameter declaration")) + + const spl_tok_t *t = peek(p); + if (t == NULL || t->type != TOK_COLON) { + SPL_FATAL(t, "expected ':' in parameter declaration"); return 0; + } + advance(p); + spl_ast_node_ref_t type_expr = parse_type_expr(p); - spl_ast_node_ref_t ref = new_node(p, SPL_AST_MEMBER_DECL, name); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_PARAM_DECL, name); node_at(p->ast, ref)->param_decl.attr_list = attr_list; node_at(p->ast, ref)->param_decl.name = sdupn(name->lexeme, name->len); node_at(p->ast, ref)->param_decl.type_expr = type_expr; @@ -438,49 +333,55 @@ static spl_ast_node_ref_t parse_param_decl_impl(parser_t *p) { } static spl_ast_node_ref_t parse_fn_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_FN */ - spl_tok_t *name = peek(p); + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_FN); + advance(p); + + const spl_tok_t *name = peek(p); if (!name || name->type != TOK_IDENT) { - parse_error(p, name ? name : kw, "expected function name"); + SPL_FATAL(name ? name : kw, "expected function name"); return 0; } advance(p); - if (!expect(p, TOK_L_PAREN, "expected '(' in function declaration")) + + const spl_tok_t *t = peek(p); + if (t == NULL || t->type != TOK_L_PAREN) { + SPL_FATAL(t, "expected '(' in function declaration"); return 0; + } + advance(p); + spl_ast_node_ref_vec_t param_list; vec_init(param_list); parse_param_list(p, ¶m_list); - if (!expect(p, TOK_R_PAREN, "expected ')' in function declaration")) + t = peek(p); + if (t == NULL || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in function declaration"); return 0; + } + advance(p); spl_ast_node_ref_t type_expr = 0; spl_ast_node_ref_vec_t block; vec_init(block); int has_body = 0; - spl_tok_t *t = peek(p); + t = peek(p); + Assert(t != NULL); + if (t->type != TOK_SEMICOLON && t->type != TOK_L_BRACE) { + type_expr = parse_type_expr(p); + t = peek(p); + } + if (t && t->type == TOK_SEMICOLON) { advance(p); } else if (t && t->type == TOK_L_BRACE) { block = parse_block(p); has_body = 1; - } else if (t && can_start_type(t->type)) { - type_expr = parse_type_expr(p); - t = peek(p); - if (t && t->type == TOK_SEMICOLON) { - advance(p); - } else if (t && t->type == TOK_L_BRACE) { - block = parse_block(p); - has_body = 1; - } else { - parse_error(p, t, "function declaration must end with ';' or a block"); - } } else { - parse_error(p, t, "expected return type, ';' or a block"); + SPL_FATAL(t, "function declaration must end with ';' or a block"); } - /* 定义SPL_AST_FN_DEFINE,外部声明(;)用 SPL_AST_FN_DECL */ spl_ast_node_ref_t ref = new_node(p, has_body ? SPL_AST_FN_DEFINE : SPL_AST_FN_DECL, kw); node_at(p->ast, ref)->fn_decl.attr_list = attr_list; node_at(p->ast, ref)->fn_decl.name = sdupn(name->lexeme, name->len); @@ -490,33 +391,48 @@ static spl_ast_node_ref_t parse_fn_decl(parser_t *p, spl_ast_node_ref_vec_t attr return ref; } -/* TypeDecl <- KEYWORD_type IDENTIFIER EQUAL TypeExpr */ static spl_ast_node_ref_t parse_type_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list) { - (void)attr_list; /* type_decl 自身不承载 attr,attr 归 TypeExpr 管理 */ - spl_tok_t *kw = peek(p); - advance(p); /* KW_TYPE */ - spl_tok_t *name = peek(p); + (void)attr_list; + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_TYPE); + advance(p); + + const spl_tok_t *name = peek(p); if (!name || name->type != TOK_IDENT) { - parse_error(p, name ? name : kw, "expected type name"); + SPL_FATAL(name ? name : kw, "expected type name"); return 0; } advance(p); - if (!expect(p, TOK_ASSIGN, "expected '=' in type declaration")) + + const spl_tok_t *t = peek(p); + if (t == NULL || t->type != TOK_ASSIGN) { + SPL_FATAL(t, "expected '=' in type declaration"); return 0; + } + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_DECL, kw); node_at(p->ast, ref)->type_decl.name = sdupn(name->lexeme, name->len); spl_ast_node_ref_t te = parse_type_expr(p); node_at(p->ast, ref)->type_decl.type_expr = te; - if (peek(p) && (peek(p)->type == TOK_SEMICOLON || peek(p)->type == TOK_COMMA)) + t = peek(p); + if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) { advance(p); + } else { + LOG_WARN("need comma or semicolon with member decl"); + } return ref; } static spl_ast_node_ref_t parse_member_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list) { - spl_tok_t *name = peek(p); - advance(p); /* TOK_IDENT */ + const spl_tok_t *name = peek(p); + Assert(name && name->type == TOK_IDENT); + advance(p); + + const spl_tok_t *t = NULL; spl_ast_node_ref_t type_expr = 0; - if (peek(p) && peek(p)->type == TOK_COLON) { + t = peek(p); + if (t && t->type == TOK_COLON) { advance(p); type_expr = parse_type_expr(p); } @@ -524,93 +440,77 @@ static spl_ast_node_ref_t parse_member_decl(parser_t *p, spl_ast_node_ref_vec_t node_at(p->ast, ref)->member_decl.attr_list = attr_list; node_at(p->ast, ref)->member_decl.name = sdupn(name->lexeme, name->len); node_at(p->ast, ref)->member_decl.type_expr = type_expr; - spl_tok_t *t = peek(p); - if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) + t = peek(p); + if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) { advance(p); + } else { + LOG_WARN("need comma or semicolon with member decl"); + } return ref; } -static spl_ast_node_ref_t parse_var_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_VAR */ - spl_tok_t *name = peek(p); +static spl_ast_node_ref_t parse_var_const_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list, + int is_const) { + const spl_tok_t *kw = peek(p); + Assert(kw); + if (is_const) { + Assert(kw->type == KW_CONST); + } else { + Assert(kw->type == KW_VAR); + } + advance(p); + + const spl_tok_t *name = peek(p); if (!name || name->type != TOK_IDENT) { - parse_error(p, name ? name : kw, "expected variable name"); + SPL_FATAL(name ? name : kw, "expected variable name"); return 0; } advance(p); + spl_ast_node_ref_t type_expr = 0; spl_ast_node_ref_t expr = 0; - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (t && t->type == TOK_COLON) { advance(p); type_expr = parse_type_expr(p); + t = peek(p); + if (t && t->type == TOK_ASSIGN) { + advance(p); + expr = parse_expr(p); + } else { + SPL_FATAL(t ? t : kw, "need assign in var decl"); + } } else if (t && t->type == TOK_COLON_ASSIGN) { advance(p); expr = parse_expr(p); } + + spl_ast_node_ref_t ref = new_node(p, is_const ? SPL_AST_CONST_DECL : SPL_AST_VAR_DECL, kw); + node_at(p->ast, ref)->var_const_decl.attr_list = attr_list; + node_at(p->ast, ref)->var_const_decl.name = sdupn(name->lexeme, name->len); + node_at(p->ast, ref)->var_const_decl.type_expr = type_expr; + node_at(p->ast, ref)->var_const_decl.expr = expr; t = peek(p); - if (t && t->type == TOK_ASSIGN) { + if (t && t->type == TOK_SEMICOLON) { advance(p); - expr = parse_expr(p); + } else { + LOG_WARN("need semicolon in decl var/const"); } - if (peek(p) && peek(p)->type == TOK_SEMICOLON) - advance(p); - spl_ast_node_ref_t ref = new_node(p, SPL_AST_VAR_DECL, kw); - node_at(p->ast, ref)->var_decl.attr_list = attr_list; - node_at(p->ast, ref)->var_decl.name = sdupn(name->lexeme, name->len); - node_at(p->ast, ref)->var_decl.type_expr = type_expr; - node_at(p->ast, ref)->var_decl.expr = expr; return ref; } -static spl_ast_node_ref_t parse_const_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_CONST */ - spl_tok_t *name = peek(p); - if (!name || name->type != TOK_IDENT) { - parse_error(p, name ? name : kw, "expected constant name"); - return 0; - } - advance(p); - spl_ast_node_ref_t type_expr = 0; - spl_ast_node_ref_t expr = 0; - spl_tok_t *t = peek(p); - if (t && t->type == TOK_COLON) { - advance(p); - type_expr = parse_type_expr(p); - } else if (t && t->type == TOK_COLON_ASSIGN) { - advance(p); - expr = parse_expr(p); - } - t = peek(p); - if (t && t->type == TOK_ASSIGN) { - advance(p); - expr = parse_expr(p); - } - if (peek(p) && peek(p)->type == TOK_SEMICOLON) - advance(p); - spl_ast_node_ref_t ref = new_node(p, SPL_AST_CONST_DECL, kw); - node_at(p->ast, ref)->const_decl.attr_list = attr_list; - node_at(p->ast, ref)->const_decl.type_expr = type_expr; - node_at(p->ast, ref)->const_decl.name = sdupn(name->lexeme, name->len); - node_at(p->ast, ref)->const_decl.expr = expr; - return ref; -} - -/* ContainerDeclaration <- AttrList? DeclarationBody */ static spl_ast_node_ref_t parse_container_declaration(parser_t *p) { spl_ast_node_ref_vec_t attr_list; vec_init(attr_list); parse_attr_list(p, &attr_list); - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t || t->type == TOK_EOF) { - parse_error(p, t, "unexpected end of file"); + SPL_FATAL(t, "unexpected end of file"); return 0; } if (t->type == TOK_L_BRACE) { - /* DirectiveBlock(@init {} / #test {}):不实*/ - parse_error(p, t, "not implemented: @/# directive block"); + /* DirectiveBlock(@init {} / #test {}):不实现 */ + SPL_FATAL(t, "not implemented: @/# directive block"); return 0; } switch (t->type) { @@ -619,33 +519,35 @@ static spl_ast_node_ref_t parse_container_declaration(parser_t *p) { case KW_TYPE: return parse_type_decl(p, attr_list); case KW_VAR: - return parse_var_decl(p, attr_list); + return parse_var_const_decl(p, attr_list, false); case KW_CONST: - return parse_const_decl(p, attr_list); - case KW_COMPTIME: - parse_error(p, t, "not implemented: comptime statement"); - return 0; + return parse_var_const_decl(p, attr_list, true); case TOK_IDENT: return parse_member_decl(p, attr_list); + case KW_COMPTIME: + SPL_FATAL(t, "not implemented: comptime statement"); + return 0; default: - parse_error(p, t, "unrecognized declaration"); + SPL_FATAL(t, "unrecognized declaration"); return 0; } } -/* ================================================================ - * 语句 * ================================================================ */ +// 语句 -/* Block <- LBRACE BlockItem* Expr? RBRACE */ static spl_ast_node_ref_vec_t parse_block(parser_t *p) { spl_ast_node_ref_vec_t vec; vec_init(vec); - if (!expect(p, TOK_L_BRACE, "expected '{'")) + const spl_tok_t *t = peek(p); + if (t == NULL || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected '{'"); return vec; + } + advance(p); while (!p->failed) { - spl_tok_t *t = peek(p); + t = peek(p); if (!t || t->type == TOK_EOF) { - parse_error(p, t, "block missing '}'"); + SPL_FATAL(t, "block missing '}'"); break; } if (t->type == TOK_R_BRACE) { @@ -654,39 +556,35 @@ static spl_ast_node_ref_vec_t parse_block(parser_t *p) { } if (can_start_statement(t->type)) { spl_ast_node_ref_t s = parse_statement(p); - if (s) + if (s) { vec_push(vec, s); + } else { + UNREACHABLE(); + } } else if (can_start_expr(t->type)) { spl_ast_node_ref_t e = parse_expr(p); - spl_tok_t *n = peek(p); - if (n && n->type == TOK_SEMICOLON) { + t = peek(p); + if (t && t->type == TOK_SEMICOLON) { advance(p); - spl_ast_node_ref_t st = new_node(p, SPL_AST_BLOCK_ITEM, t); - node_at(p->ast, st)->block_item.kind = SPL_AST_EXPR_STATEMENT; - node_at(p->ast, st)->block_item.expr_statement = e; - vec_push(vec, st); - } else { - /* 尾表达式:EXPR 节点直接block vec */ vec_push(vec, e); + } else { + // Tail expretion + UNREACHABLE(); } } else { - parse_error(p, t, "unrecognized statement"); + SPL_FATAL(t, "unrecognized statement"); } } return vec; } static spl_ast_node_ref_t parse_statement(parser_t *p) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t) return 0; switch (t->type) { - case KW_IF: { - spl_tok_t *n = peek_next(p); - if (n && n->type == KW_VAR) - return parse_ifvar(p); + case KW_IF: return parse_if(p); - } case KW_WHILE: return parse_while(p); case KW_LOOP: @@ -706,203 +604,207 @@ static spl_ast_node_ref_t parse_statement(parser_t *p) { case KW_VAR: { spl_ast_node_ref_vec_t al; vec_init(al); - spl_ast_node_ref_t v = parse_var_decl(p, al); - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, t); - node_at(p->ast, s)->block_item.kind = SPL_AST_VARDECL; - node_at(p->ast, s)->block_item.var_decl = v; - return s; + return parse_var_const_decl(p, al, false); } case KW_CONST: { spl_ast_node_ref_vec_t al; vec_init(al); - spl_ast_node_ref_t v = parse_const_decl(p, al); - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, t); - node_at(p->ast, s)->block_item.kind = SPL_AST_CONSTDECL; - node_at(p->ast, s)->block_item.const_decl = v; - return s; + return parse_var_const_decl(p, al, true); } case KW_TYPE: { spl_ast_node_ref_vec_t al; vec_init(al); - spl_ast_node_ref_t v = parse_type_decl(p, al); - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, t); - node_at(p->ast, s)->block_item.kind = SPL_AST_TYPEDECL; - node_at(p->ast, s)->block_item.type_decl = v; - return s; + return parse_type_decl(p, al); } case KW_COMPTIME: - parse_error(p, t, "not implemented: comptime statement"); + SPL_FATAL(t, "not implemented: comptime statement"); return 0; default: - parse_error(p, t, "unrecognized statement"); + SPL_FATAL(t, "unrecognized statement"); return 0; } } static spl_ast_node_ref_t parse_if(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_IF */ - p->stop_agg++; - spl_ast_node_ref_t expr = parse_expr(p); - p->stop_agg--; - spl_ast_node_ref_vec_t if_block = parse_block(p); - spl_ast_node_ref_vec_t else_block; - vec_init(else_block); - if (peek(p) && peek(p)->type == KW_ELSE) { - advance(p); - spl_tok_t *t = peek(p); - if (t && t->type == KW_IF) { - vec_push(else_block, parse_if(p)); - } else if (t && t->type == KW_VAR) { - vec_push(else_block, parse_ifvar(p)); - } else { - else_block = parse_block(p); - } - } - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_IF_STATEMENT; - node_at(p->ast, s)->block_item.if_statement.expr = expr; - node_at(p->ast, s)->block_item.if_statement.if_block = if_block; - node_at(p->ast, s)->block_item.if_statement.else_block = else_block; - return s; -} - -static spl_ast_node_ref_t parse_ifvar(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_IF */ - advance(p); /* KW_VAR */ - if (!expect(p, TOK_DOT, "expected '.' in if var")) - return 0; - spl_tok_t *name = peek(p); - if (!name || name->type != TOK_IDENT) { - parse_error(p, name, "expected variable name in if var"); - return 0; - } + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_IF); advance(p); + + int is_ifvar = false; char *bind = NULL; - if (peek(p) && peek(p)->type == TOK_L_BRACKET) { + const spl_tok_t *name = NULL; + const spl_tok_t *t = peek(p); + if (t && t->type == KW_VAR) { advance(p); - spl_tok_t *b = peek(p); - if (!b || b->type != TOK_IDENT) { - parse_error(p, b, "expected identifier in if var binding"); + t = peek(p); + if (t == NULL || t->type != TOK_DOT) { + SPL_FATAL(t, "expected '.' in if var"); + return 0; + } + name = peek(p); + if (!name || name->type != TOK_IDENT) { + SPL_FATAL(name, "expected variable name in if var"); return 0; } advance(p); - bind = sdupn(b->lexeme, b->len); - if (!expect(p, TOK_R_BRACKET, "expected ']' in if var binding")) - return 0; - } - if (!expect(p, TOK_ASSIGN, "expected '=' in if var")) + t = peek(p); + if (t && t->type == TOK_L_BRACKET) { + advance(p); + t = peek(p); + if (!t || t->type != TOK_IDENT) { + SPL_FATAL(t, "expected identifier in if var binding"); + return 0; + } + advance(p); + bind = sdupn(t->lexeme, t->len); + + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in if var binding"); + return 0; + } + advance(p); + } + + t = peek(p); + if (t == NULL || t->type != TOK_ASSIGN) { + SPL_FATAL(t, "expected '=' in if var"); + } + advance(p); return 0; + } + p->stop_agg++; spl_ast_node_ref_t expr = parse_expr(p); p->stop_agg--; + spl_ast_node_ref_vec_t if_block = parse_block(p); spl_ast_node_ref_vec_t else_block; vec_init(else_block); - if (peek(p) && peek(p)->type == KW_ELSE) { + t = peek(p); + if (t && t->type == KW_ELSE) { advance(p); - spl_tok_t *t = peek(p); + t = peek(p); if (t && t->type == KW_IF) { vec_push(else_block, parse_if(p)); - } else if (t && t->type == KW_VAR) { - vec_push(else_block, parse_ifvar(p)); } else { else_block = parse_block(p); } } - spl_ast_node_ref_t packed = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, packed)->packed_expr.ident = sdupn(name->lexeme, name->len); - node_at(p->ast, packed)->packed_expr.bind_ident = bind; - node_at(p->ast, packed)->packed_expr.expr = expr; - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_IFVAR_STATEMENT; - node_at(p->ast, s)->block_item.ifvar_statement.packed_expr = packed; - node_at(p->ast, s)->block_item.ifvar_statement.if_block = if_block; - node_at(p->ast, s)->block_item.ifvar_statement.else_block = else_block; + + spl_ast_node_ref_t s = 0; + if (is_ifvar) { + Assert(name != NULL && bind != NULL); + spl_ast_node_ref_t packed = new_node(p, SPL_AST_PACKED_EXPR, kw); + node_at(p->ast, packed)->packed_expr.ident = sdupn(name->lexeme, name->len); + node_at(p->ast, packed)->packed_expr.bind_ident = bind; + node_at(p->ast, packed)->packed_expr.expr = expr; + s = new_node(p, SPL_AST_IFVAR_STATEMENT, kw); + node_at(p->ast, s)->ifvar_statement.packed_expr = packed; + node_at(p->ast, s)->ifvar_statement.if_block = if_block; + node_at(p->ast, s)->ifvar_statement.else_block = else_block; + } else { + s = new_node(p, SPL_AST_IF_STATEMENT, kw); + node_at(p->ast, s)->if_statement.expr = expr; + node_at(p->ast, s)->if_statement.if_block = if_block; + node_at(p->ast, s)->if_statement.else_block = else_block; + } return s; } static spl_ast_node_ref_t parse_while(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_WHILE */ + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_WHILE); + advance(p); p->stop_agg++; spl_ast_node_ref_t expr = parse_expr(p); p->stop_agg--; spl_ast_node_ref_vec_t block = parse_block(p); - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_WHILE_STATEMENT; - node_at(p->ast, s)->block_item.while_statement.expr = expr; - node_at(p->ast, s)->block_item.while_statement.while_block = block; + spl_ast_node_ref_t s = new_node(p, SPL_AST_WHILE_STATEMENT, kw); + node_at(p->ast, s)->while_statement.expr = expr; + node_at(p->ast, s)->while_statement.while_block = block; return s; } static spl_ast_node_ref_t parse_loop(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_LOOP */ + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_LOOP); + advance(p); spl_ast_node_ref_vec_t block = parse_block(p); - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_LOOP_STATEMENT; - node_at(p->ast, s)->block_item.loop_statement.loop_block = block; + spl_ast_node_ref_t s = new_node(p, SPL_AST_LOOP_STATEMENT, kw); + node_at(p->ast, s)->loop_statement.loop_block = block; return s; } static spl_ast_node_ref_t parse_for(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_FOR */ + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_FOR); + advance(p); spl_ast_node_ref_vec_t expr_vec; vec_init(expr_vec); - p->stop_as = 1; /* for 头部序列as 属于 for,不属于后缀类型转换 */ + + // For as is not type case + p->stop_as = 1; vec_push(expr_vec, parse_expr(p)); while (peek(p) && peek(p)->type == TOK_COMMA) { advance(p); vec_push(expr_vec, parse_expr(p)); } p->stop_as = 0; - if (!expect(p, KW_AS, "expected 'as' in for")) + + const spl_tok_t *t = peek(p); + if (t == NULL || t->type != KW_AS) { + SPL_FATAL(t, "expected 'as' in for"); return 0; - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_FOR_STATEMENT; - node_at(p->ast, s)->block_item.for_statement.expr_vec = expr_vec; - spl_tok_t *v = peek(p); - if (!v || (v->type != TOK_IDENT && v->type != KW_ANY)) { - parse_error(p, v, "expected binding variable in for"); + } + advance(p); + + spl_ast_node_ref_t s = new_node(p, SPL_AST_FOR_STATEMENT, kw); + node_at(p->ast, s)->for_statement.expr_vec = expr_vec; + t = peek(p); + if (!t || (t->type != TOK_IDENT && t->type != KW_ANY)) { + SPL_FATAL(t, "expected binding variable in for"); return s; } advance(p); - vec_push(node_at(p->ast, s)->block_item.for_statement.ident_vec, sdupn(v->lexeme, v->len)); + vec_push(node_at(p->ast, s)->for_statement.ident_vec, sdupn(t->lexeme, t->len)); while (peek(p) && peek(p)->type == TOK_COMMA) { advance(p); - spl_tok_t *vi = peek(p); - if (!vi || (vi->type != TOK_IDENT && vi->type != KW_ANY)) { - parse_error(p, vi, "expected binding variable in for"); + t = peek(p); + if (!t || (t->type != TOK_IDENT && t->type != KW_ANY)) { + SPL_FATAL(t, "expected binding variable in for"); return s; } advance(p); - vec_push(node_at(p->ast, s)->block_item.for_statement.ident_vec, - sdupn(vi->lexeme, vi->len)); + vec_push(node_at(p->ast, s)->for_statement.ident_vec, sdupn(t->lexeme, t->len)); } spl_ast_node_ref_vec_t fblock = parse_block(p); - node_at(p->ast, s)->block_item.for_statement.block = fblock; + node_at(p->ast, s)->for_statement.block = fblock; return s; } static spl_ast_node_ref_t parse_match(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_MATCH */ + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_MATCH); + advance(p); p->stop_agg++; spl_ast_node_ref_t expr = parse_expr(p); p->stop_agg--; - if (!expect(p, TOK_L_BRACE, "expected '{' in match")) { + + const spl_tok_t *t = peek(p); + if (t == NULL || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected '{' in match"); return 0; } + advance(p); + spl_ast_node_ref_vec_t paced_vec, stmt_vec; vec_init(paced_vec); vec_init(stmt_vec); while (1) { - spl_tok_t *t = peek(p); + t = peek(p); if (!t || t->type == TOK_EOF) { - parse_error(p, t, "match missing '}'"); + SPL_FATAL(t, "match missing '}'"); break; } if (t->type == TOK_R_BRACE) { @@ -911,74 +813,73 @@ static spl_ast_node_ref_t parse_match(parser_t *p) { } if (!parse_match_arm(p, &paced_vec, &stmt_vec)) break; - if (peek(p) && peek(p)->type == TOK_COMMA) + t = peek(p); + if (t && t->type == TOK_COMMA) advance(p); } - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_MATCH_STATEMENT; - node_at(p->ast, s)->block_item.match_statement.expr = expr; - node_at(p->ast, s)->block_item.match_statement.paced_exprs = paced_vec; - node_at(p->ast, s)->block_item.match_statement.match_block = stmt_vec; + spl_ast_node_ref_t s = new_node(p, SPL_AST_MATCH_STATEMENT, kw); + node_at(p->ast, s)->match_statement.expr = expr; + node_at(p->ast, s)->match_statement.paced_exprs = paced_vec; + node_at(p->ast, s)->match_statement.match_block = stmt_vec; return s; } -/* MatchArm <- MatchPat (',' MatchPat)* '=>' Block - * 模式合并: 多模式共享同一臂体。每个模式生成一个 packed_expr, - * 臂体解析一次,其节点引用按模式个数共享写入 block_vec。 - * 这样 paced_vec 与 block_vec 一一对应(每模式一条),语义等价 - * 于展开为多个独立臂。 */ static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *paced_vec, spl_ast_node_ref_vec_t *block_vec) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t) return 0; spl_ast_node_ref_vec_t modes; vec_init(modes); while (1) { - spl_tok_t *mt = peek(p); + const spl_tok_t *mt = peek(p); if (!mt) { - parse_error(p, mt, "invalid match arm pattern"); + SPL_FATAL(mt, "invalid match arm pattern"); return 0; } - spl_ast_node_ref_t pk = new_node(p, SPL_AST_BLOCK_ITEM, mt); + spl_ast_node_ref_t pk = new_node(p, SPL_AST_PACKED_EXPR, mt); node_at(p->ast, pk)->packed_expr.ident = NULL; node_at(p->ast, pk)->packed_expr.bind_ident = NULL; node_at(p->ast, pk)->packed_expr.expr = 0; if (mt->type == TOK_DOT) { advance(p); - spl_tok_t *name = peek(p); + const spl_tok_t *name = peek(p); if (!name || name->type != TOK_IDENT) { - parse_error(p, name, "expected variant name in match pattern"); + SPL_FATAL(name, "expected variant name in match pattern"); return 0; } advance(p); node_at(p->ast, pk)->packed_expr.ident = sdupn(name->lexeme, name->len); if (peek(p) && peek(p)->type == TOK_L_BRACKET) { advance(p); - spl_tok_t *b = peek(p); + const spl_tok_t *b = peek(p); if (!b || b->type != TOK_IDENT) { - parse_error(p, b, "expected identifier in match binding"); + SPL_FATAL(b, "expected identifier in match binding"); return 0; } advance(p); node_at(p->ast, pk)->packed_expr.bind_ident = sdupn(b->lexeme, b->len); - if (!expect(p, TOK_R_BRACKET, "expected ']' in match binding")) + + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in match binding"); return 0; + } + advance(p); } } else if (mt->type == KW_ANY) { - /* _ 通配;_ 后跟 '{'(且非聚合抑制)按匿名聚合字面量模式解析 */ - spl_tok_t *nx = peek_next(p); - if (nx && nx->type == TOK_L_BRACE && !p->stop_agg) { + t = peek(p); + if (t && t->type == TOK_L_BRACE && !p->stop_agg) { spl_ast_node_ref_t pe = parse_expr(p); node_at(p->ast, pk)->packed_expr.expr = pe; } else { - advance(p); /* _ 通配 */ + advance(p); } } else if (can_start_expr(mt->type)) { spl_ast_node_ref_t pe = parse_expr(p); node_at(p->ast, pk)->packed_expr.expr = pe; } else { - parse_error(p, mt, "invalid match arm pattern"); + SPL_FATAL(mt, "invalid match arm pattern"); return 0; } vec_push(modes, pk); @@ -988,16 +889,23 @@ static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *paced_vec, } break; } - if (!expect(p, TOK_FAT_ARROW, "expected '=>' in match arm")) - return 0; - if (!peek(p) || peek(p)->type != TOK_L_BRACE) { - parse_error(p, peek(p), "expected '{' block in match arm body"); + + t = peek(p); + if (t == NULL || t->type != TOK_FAT_ARROW) { + SPL_FATAL(t, "expected '=>' in match arm"); return 0; } + advance(p); + + t = peek(p); + if (!t || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected '{' block in match arm body"); + return 0; + } + spl_ast_node_ref_vec_t bvec = parse_block(p); - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_BLOCK_EXPR); - node_at(p->ast, pr)->primary_expr.block_expr = bvec; - spl_ast_node_ref_t body = wrap_expr(p, pr); + spl_ast_node_ref_t body = new_node(p, SPL_AST_BLOCK_EXPR, t); + node_at(p->ast, body)->primary_expr.block_expr = bvec; for (usize i = 0; i < modes.size; i++) { vec_push(*paced_vec, modes.data[i]); vec_push(*block_vec, body); @@ -1007,79 +915,78 @@ static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *paced_vec, } static spl_ast_node_ref_t parse_ret(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_RET */ + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_RET); + advance(p); spl_ast_node_ref_t expr = 0; - if (peek(p) && can_start_expr(peek(p)->type)) + + const spl_tok_t *t = peek(p); + if (t && can_start_expr(t->type)) expr = parse_expr(p); - if (peek(p) && peek(p)->type == TOK_SEMICOLON) + t = peek(p); + if (t && t->type == TOK_SEMICOLON) advance(p); - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_RET_STATEMENT; - node_at(p->ast, s)->block_item.ret_statement.expr = expr; + spl_ast_node_ref_t s = new_node(p, SPL_AST_RET_STATEMENT, kw); + node_at(p->ast, s)->ret_statement.expr = expr; return s; } static spl_ast_node_ref_t parse_break(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_BREAK */ - if (peek(p) && peek(p)->type == TOK_SEMICOLON) + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_BREAK); + advance(p); + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_SEMICOLON) advance(p); - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_BREAK_STATEMENT; - return s; + return new_node(p, SPL_AST_BREAK_STATEMENT, kw); } static spl_ast_node_ref_t parse_continue(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_CONTINUE */ - if (peek(p) && peek(p)->type == TOK_SEMICOLON) + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_CONTINUE); + advance(p); + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_SEMICOLON) advance(p); - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_CONTINUE_STATEMENT; - return s; + return new_node(p, SPL_AST_CONTINUE_STATEMENT, kw); } static spl_ast_node_ref_t parse_defer(parser_t *p) { - spl_tok_t *kw = peek(p); - advance(p); /* KW_DEFER */ + const spl_tok_t *kw = peek(p); + Assert(kw && kw->type == KW_DEFER); + advance(p); spl_ast_node_ref_vec_t vec; vec_init(vec); - if (peek(p) && peek(p)->type == TOK_L_BRACE) { + + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_L_BRACE) { vec = parse_block(p); - } else if (peek(p) && can_start_statement(peek(p)->type)) { + } else if (t && can_start_statement(t->type)) { spl_ast_node_ref_t st = parse_statement(p); if (st) vec_push(vec, st); } else { - /* ExprStatement: defer ; */ - spl_tok_t *t = peek(p); spl_ast_node_ref_t e = parse_expr(p); - if (peek(p) && peek(p)->type == TOK_SEMICOLON) + t = peek(p); + if (t && t->type == TOK_SEMICOLON) advance(p); - spl_ast_node_ref_t st = new_node(p, SPL_AST_BLOCK_ITEM, t); - node_at(p->ast, st)->block_item.kind = SPL_AST_EXPR_STATEMENT; - node_at(p->ast, st)->block_item.expr_statement = e; - vec_push(vec, st); + vec_push(vec, e); } - spl_ast_node_ref_t s = new_node(p, SPL_AST_BLOCK_ITEM, kw); - node_at(p->ast, s)->block_item.kind = SPL_AST_DEFER_STATEMENT; - node_at(p->ast, s)->block_item.defer_statement.block_or_statement = vec; + spl_ast_node_ref_t s = new_node(p, SPL_AST_DEFER_STATEMENT, kw); + node_at(p->ast, s)->defer_statement.block_or_statement = vec; return s; } -/* ================================================================ - * 表达式(优先级爬升) - * ================================================================ */ +// 表达式 -static int assign_op_of(spl_tok_type_t t) { +static spl_ast_node_kind_t assign_op_of(spl_tok_type_t t) { switch (t) { case TOK_ASSIGN: return SPL_AST_ASSIGN_EXPR; case TOK_ASSIGN_ADD: return SPL_AST_ASSIGN_ADD_EXPR; case TOK_ASSIGN_SUB: - return SPL_AST_ASSIGN_sUB_EXPR; + return SPL_AST_ASSIGN_SUB_EXPR; case TOK_ASSIGN_MUL: return SPL_AST_ASSIGN_MUL_EXPR; case TOK_ASSIGN_DIV: @@ -1097,7 +1004,7 @@ static int assign_op_of(spl_tok_type_t t) { case TOK_ASSIGN_R_SH: return SPL_AST_ASSIGN_USHIFT_EXPR; default: - return -1; + return SPL_AST_COUNT; } } @@ -1105,9 +1012,9 @@ static spl_ast_node_ref_t parse_assign(parser_t *p) { spl_ast_node_ref_t left = parse_bool_or(p); if (p->failed) return left; - spl_tok_t *t = peek(p); - int op = t ? assign_op_of(t->type) : -1; - if (op < 0) + const spl_tok_t *t = peek(p); + spl_ast_node_kind_t op = t ? assign_op_of(t->type) : SPL_AST_COUNT; + if (op == SPL_AST_COUNT) return left; advance(p); spl_ast_node_ref_t right = parse_assign(p); @@ -1117,12 +1024,12 @@ static spl_ast_node_ref_t parse_assign(parser_t *p) { static spl_ast_node_ref_t parse_bool_or(parser_t *p) { spl_ast_node_ref_t left = parse_bool_and(p); while (!p->failed) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t || t->type != TOK_OR_OR) break; advance(p); spl_ast_node_ref_t right = parse_bool_and(p); - left = mk_bin(p, t, SPL_AST_BOOLOR_EXPR, left, right); + left = mk_bin(p, t, SPL_AST_BOOL_OR_EXPR, left, right); } return left; } @@ -1130,12 +1037,12 @@ static spl_ast_node_ref_t parse_bool_or(parser_t *p) { static spl_ast_node_ref_t parse_bool_and(parser_t *p) { spl_ast_node_ref_t left = parse_bit_or(p); while (!p->failed) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t || t->type != TOK_AND_AND) break; advance(p); spl_ast_node_ref_t right = parse_bit_or(p); - left = mk_bin(p, t, SPL_AST_BOOLAND_EXPR, left, right); + left = mk_bin(p, t, SPL_AST_BOOL_AND_EXPR, left, right); } return left; } @@ -1143,12 +1050,12 @@ static spl_ast_node_ref_t parse_bool_and(parser_t *p) { static spl_ast_node_ref_t parse_bit_or(parser_t *p) { spl_ast_node_ref_t left = parse_bit_xor(p); while (!p->failed) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t || t->type != TOK_OR) break; advance(p); spl_ast_node_ref_t right = parse_bit_xor(p); - left = mk_bin(p, t, SPL_AST_BITOR_EXPR, left, right); + left = mk_bin(p, t, SPL_AST_BIT_OR_EXPR, left, right); } return left; } @@ -1156,12 +1063,12 @@ static spl_ast_node_ref_t parse_bit_or(parser_t *p) { static spl_ast_node_ref_t parse_bit_xor(parser_t *p) { spl_ast_node_ref_t left = parse_bit_and(p); while (!p->failed) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t || t->type != TOK_XOR) break; advance(p); spl_ast_node_ref_t right = parse_bit_and(p); - left = mk_bin(p, t, SPL_AST_BITXOR_EXPR, left, right); + left = mk_bin(p, t, SPL_AST_BIT_XOR_EXPR, left, right); } return left; } @@ -1169,12 +1076,12 @@ static spl_ast_node_ref_t parse_bit_xor(parser_t *p) { static spl_ast_node_ref_t parse_bit_and(parser_t *p) { spl_ast_node_ref_t left = parse_cmp_eq(p); while (!p->failed) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t || t->type != TOK_AND) break; advance(p); spl_ast_node_ref_t right = parse_cmp_eq(p); - left = mk_bin(p, t, SPL_AST_BITAND_EXPR, left, right); + left = mk_bin(p, t, SPL_AST_BIT_AND_EXPR, left, right); } return left; } @@ -1182,15 +1089,15 @@ static spl_ast_node_ref_t parse_bit_and(parser_t *p) { static spl_ast_node_ref_t parse_cmp_eq(parser_t *p) { spl_ast_node_ref_t left = parse_cmp(p); while (!p->failed) { - spl_tok_t *t = peek(p); - int op = -1; + const spl_tok_t *t = peek(p); + spl_ast_node_kind_t op = SPL_AST_COUNT; if (t) { if (t->type == TOK_EQ) - op = SPL_AST_CMPEQ_EXPR; + op = SPL_AST_CMP_EQ_EXPR; else if (t->type == TOK_NEQ) - op = SPL_AST_CMPNE_EXPR; + op = SPL_AST_CMP_NE_EXPR; } - if (op < 0) + if (op == SPL_AST_COUNT) break; advance(p); spl_ast_node_ref_t right = parse_cmp(p); @@ -1202,8 +1109,8 @@ static spl_ast_node_ref_t parse_cmp_eq(parser_t *p) { static spl_ast_node_ref_t parse_cmp(parser_t *p) { spl_ast_node_ref_t left = parse_range(p); while (!p->failed) { - spl_tok_t *t = peek(p); - int op = -1; + const spl_tok_t *t = peek(p); + spl_ast_node_kind_t op = SPL_AST_COUNT; if (t) { if (t->type == TOK_LT) op = SPL_AST_CMP_LT_EXPR; @@ -1214,7 +1121,7 @@ static spl_ast_node_ref_t parse_cmp(parser_t *p) { else if (t->type == TOK_GE) op = SPL_AST_CMP_GE_EXPR; } - if (op < 0) + if (op == SPL_AST_COUNT) break; advance(p); spl_ast_node_ref_t right = parse_range(p); @@ -1227,7 +1134,7 @@ static spl_ast_node_ref_t parse_range(parser_t *p) { spl_ast_node_ref_t left = parse_shift(p); if (p->failed) return left; - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (t && t->type == TOK_RANGE) { advance(p); spl_ast_node_ref_t right = 0; /* a.. 无右端点 */ @@ -1241,15 +1148,15 @@ static spl_ast_node_ref_t parse_range(parser_t *p) { static spl_ast_node_ref_t parse_shift(parser_t *p) { spl_ast_node_ref_t left = parse_add(p); while (!p->failed) { - spl_tok_t *t = peek(p); - int op = -1; + const spl_tok_t *t = peek(p); + spl_ast_node_kind_t op = SPL_AST_COUNT; if (t) { if (t->type == TOK_L_SH) op = SPL_AST_LSHIFT_EXPR; else if (t->type == TOK_R_SH) op = SPL_AST_RSHIFT_EXPR; } - if (op < 0) + if (op == SPL_AST_COUNT) break; advance(p); spl_ast_node_ref_t right = parse_add(p); @@ -1261,15 +1168,15 @@ static spl_ast_node_ref_t parse_shift(parser_t *p) { static spl_ast_node_ref_t parse_add(parser_t *p) { spl_ast_node_ref_t left = parse_mul(p); while (!p->failed) { - spl_tok_t *t = peek(p); - int op = -1; + const spl_tok_t *t = peek(p); + spl_ast_node_kind_t op = SPL_AST_COUNT; if (t) { if (t->type == TOK_ADD) op = SPL_AST_ADD_EXPR; else if (t->type == TOK_SUB) op = SPL_AST_SUB_EXPR; } - if (op < 0) + if (op == SPL_AST_COUNT) break; advance(p); spl_ast_node_ref_t right = parse_mul(p); @@ -1281,8 +1188,8 @@ static spl_ast_node_ref_t parse_add(parser_t *p) { static spl_ast_node_ref_t parse_mul(parser_t *p) { spl_ast_node_ref_t left = parse_prefix(p); while (!p->failed) { - spl_tok_t *t = peek(p); - int op = -1; + const spl_tok_t *t = peek(p); + spl_ast_node_kind_t op = SPL_AST_COUNT; if (t) { if (t->type == TOK_MUL) op = SPL_AST_MUL_EXPR; @@ -1291,7 +1198,7 @@ static spl_ast_node_ref_t parse_mul(parser_t *p) { else if (t->type == TOK_MOD) op = SPL_AST_MOD_EXPR; } - if (op < 0) + if (op == SPL_AST_COUNT) break; advance(p); spl_ast_node_ref_t right = parse_prefix(p); @@ -1300,124 +1207,112 @@ static spl_ast_node_ref_t parse_mul(parser_t *p) { return left; } -/* PrefixExpr <- PrefixOp* PostfixExpr */ static spl_ast_node_ref_t parse_prefix(parser_t *p) { - int ops[16]; - spl_tok_t *op_toks[16]; - int n = 0; - while (n < 16 && !p->failed) { - spl_tok_t *t = peek(p); - int op = -1; - if (t) { - switch (t->type) { - case TOK_SUB: - op = SPL_AST_MINUS_EXPR; - break; - case TOK_NOT: - op = SPL_AST_BANG_EXPR; - break; - case TOK_BIT_NOT: - op = SPL_AST_TILDE_EXPR; - break; - case TOK_AND: - op = SPL_AST_AMPERSAND_EXPR; - break; - case TOK_MUL: - op = SPL_AST_ASTERISK_EXPR; - break; - default: - break; - } - } - if (op < 0) - break; - ops[n] = op; - op_toks[n] = t; - n++; - advance(p); + const spl_tok_t *t = peek(p); + Assert(t != NULL); + spl_ast_node_kind_t op; + switch (t->type) { + case TOK_SUB: + op = SPL_AST_MINUS_EXPR; + break; + case TOK_NOT: + op = SPL_AST_NOT_EXPR; + break; + case TOK_BIT_NOT: + op = SPL_AST_BIT_NOT_EXPR; + break; + case TOK_AND: + op = SPL_AST_ADDRESS_EXPR; + break; + default: + return parse_postfix(p); } - spl_ast_node_ref_t inner = parse_postfix(p); - /* 从内到外包装(最内层 op 在列表末尾) */ - for (int i = n - 1; i >= 0; i--) { - spl_ast_node_ref_t pf = new_node(p, SPL_AST_EXPR, op_toks[i]); - node_at(p->ast, pf)->prefix_expr.kind = ops[i]; - node_at(p->ast, pf)->prefix_expr.postfix_expr = inner; - inner = wrap_op_expr(p, pf, SPL_AST_PREFIX_EXPR); - } - return inner; + advance(p); + spl_ast_node_ref_t inner = parse_prefix(p); + spl_ast_node_ref_t pf = new_node(p, op, t); + node_at(p->ast, pf)->prefix_expr.postfix_expr = inner; + return pf; } -/* PostfixExpr <- PrimaryExpr (call/field/deref/index/slice/as)* */ static spl_ast_node_ref_t parse_postfix(parser_t *p) { spl_ast_node_ref_t expr = parse_primary(p); while (!p->failed) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t) break; if (t->type == TOK_L_PAREN) { advance(p); - spl_ast_node_ref_t pf = new_node(p, SPL_AST_EXPR, t); - node_at(p->ast, pf)->postfix_expr.kind = SPL_AST_CALL_EXPR; + spl_ast_node_ref_t pf = new_node(p, SPL_AST_CALL_EXPR, t); node_at(p->ast, pf)->postfix_expr.primary_expr = expr; spl_ast_node_ref_vec_t cvec = parse_expr_list(p); node_at(p->ast, pf)->postfix_expr.call_expr = cvec; - if (!expect(p, TOK_R_PAREN, "expected ')' in call")) + + t = peek(p); + if (t == NULL || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in call"); return expr; - expr = wrap_op_expr(p, pf, SPL_AST_POSTFIX_EXPR); + } + advance(p); + expr = pf; } else if (t->type == TOK_DOT) { advance(p); - spl_tok_t *n = peek(p); + const spl_tok_t *n = peek(p); if (n && n->type == TOK_MUL) { advance(p); - spl_ast_node_ref_t pf = new_node(p, SPL_AST_EXPR, t); - node_at(p->ast, pf)->postfix_expr.kind = SPL_AST_DEREF_EXPR; + spl_ast_node_ref_t pf = new_node(p, SPL_AST_DEREF_EXPR, t); node_at(p->ast, pf)->postfix_expr.primary_expr = expr; - expr = wrap_op_expr(p, pf, SPL_AST_POSTFIX_EXPR); + expr = pf; } else if (n && n->type == TOK_IDENT) { advance(p); - spl_ast_node_ref_t pf = new_node(p, SPL_AST_EXPR, t); - node_at(p->ast, pf)->postfix_expr.kind = SPL_AST_FIELD_EXPR; + spl_ast_node_ref_t pf = new_node(p, SPL_AST_FIELD_EXPR, t); node_at(p->ast, pf)->postfix_expr.primary_expr = expr; node_at(p->ast, pf)->postfix_expr.field_expr = sdupn(n->lexeme, n->len); - expr = wrap_op_expr(p, pf, SPL_AST_POSTFIX_EXPR); + expr = pf; } else { - parse_error(p, n, "expected identifier or '*' after '.'"); + SPL_FATAL(n, "expected identifier or '*' after '.'"); break; } } else if (t->type == TOK_L_BRACKET) { advance(p); - /* 切片 begin 用 parse_shift 解析:`a..b` 中 `..` 属切片标记而非 Range 表达式 */ spl_ast_node_ref_t begin = parse_shift(p); if (peek(p) && peek(p)->type == TOK_RANGE) { advance(p); spl_ast_node_ref_t end = 0; if (peek(p) && peek(p)->type != TOK_R_BRACKET) end = parse_expr(p); - if (!expect(p, TOK_R_BRACKET, "expected ']' in slice")) + + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in slice"); return expr; - spl_ast_node_ref_t pf = new_node(p, SPL_AST_EXPR, t); - node_at(p->ast, pf)->postfix_expr.kind = SPL_AST_SLICE_EXPR; + } + advance(p); + + spl_ast_node_ref_t pf = new_node(p, SPL_AST_SLICE_EXPR, t); node_at(p->ast, pf)->postfix_expr.primary_expr = expr; node_at(p->ast, pf)->postfix_expr.slice_expr.begin = begin; node_at(p->ast, pf)->postfix_expr.slice_expr.end = end; - expr = wrap_op_expr(p, pf, SPL_AST_POSTFIX_EXPR); + expr = pf; } else { - if (!expect(p, TOK_R_BRACKET, "expected ']' in index")) + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in index"); return expr; - spl_ast_node_ref_t pf = new_node(p, SPL_AST_EXPR, t); - node_at(p->ast, pf)->postfix_expr.kind = SPL_AST_INDEX_EXPR; + } + advance(p); + + spl_ast_node_ref_t pf = new_node(p, SPL_AST_INDEX_EXPR, t); node_at(p->ast, pf)->postfix_expr.primary_expr = expr; node_at(p->ast, pf)->postfix_expr.index_expr = begin; - expr = wrap_op_expr(p, pf, SPL_AST_POSTFIX_EXPR); + expr = pf; } } else if (t->type == KW_AS && !p->stop_as) { advance(p); spl_ast_node_ref_t te = parse_type_expr(p); - spl_ast_node_ref_t pf = new_node(p, SPL_AST_EXPR, t); - node_at(p->ast, pf)->postfix_expr.kind = SPL_AST_AS_EXPR; + spl_ast_node_ref_t pf = new_node(p, SPL_AST_AS_EXPR, t); node_at(p->ast, pf)->postfix_expr.primary_expr = expr; node_at(p->ast, pf)->postfix_expr.type_expr = te; - expr = wrap_op_expr(p, pf, SPL_AST_POSTFIX_EXPR); + expr = pf; } else { break; } @@ -1425,48 +1320,54 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) { return expr; } -/* ExprList <- (Expr COMMA)* Expr? */ static spl_ast_node_ref_vec_t parse_expr_list(parser_t *p) { spl_ast_node_ref_vec_t vec; vec_init(vec); if (p->failed) return vec; - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t || !can_start_expr(t->type)) return vec; vec_push(vec, parse_expr(p)); while (!p->failed && peek(p) && peek(p)->type == TOK_COMMA) { advance(p); if (!peek(p) || !can_start_expr(peek(p)->type)) - break; /* 尾逗号宽容 */ + break; // 尾逗号宽容 vec_push(vec, parse_expr(p)); } return vec; } -/* AggregateInitBody <- LBRACE StructInitList? RBRACE - * StructInit <- DOT (IDENTIFIER / UNDERSCORE) (EQUAL Expr)? - * UNDERSCORE 作为字段名表示匿名(positional)初始化,ident 存 "_"。 - * 返回 aggregate_init_item vec。 */ static spl_ast_node_ref_vec_t parse_aggregate_init_body(parser_t *p) { spl_ast_node_ref_vec_t agg_vec; vec_init(agg_vec); - if (!expect(p, TOK_L_BRACE, "expected '{' in struct init")) + + const spl_tok_t *t = peek(p); + if (t == NULL || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected '{' in struct init"); return agg_vec; + } + advance(p); while (1) { - spl_tok_t *s = peek(p); - if (!s || s->type == TOK_R_BRACE || s->type == TOK_EOF) + t = peek(p); + if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF) break; - if (!expect(p, TOK_DOT, "expected '.' in struct init")) - return agg_vec; - spl_tok_t *f = peek(p); - if (!f || f->type != TOK_IDENT) { - parse_error(p, f, "expected field name in struct init"); + + t = peek(p); + if (t == NULL || t->type != TOK_DOT) { + SPL_FATAL(t, "expected '.' in struct init"); return agg_vec; } advance(p); - spl_ast_node_ref_t item = new_node(p, SPL_AST_VAR_DECL, f); - node_at(p->ast, item)->aggregate_init_item.ident = sdupn(f->lexeme, f->len); + + t = peek(p); + if (!t || t->type != TOK_IDENT) { + SPL_FATAL(t, "expected field name in struct init"); + return agg_vec; + } + advance(p); + spl_ast_node_ref_t item = new_node(p, SPL_AST_ARGG_INIT_ITEM, t); + node_at(p->ast, item)->aggregate_init_item.ident = sdupn(t->lexeme, t->len); if (peek(p) && peek(p)->type == TOK_ASSIGN) { advance(p); spl_ast_node_ref_t ae = parse_expr(p); @@ -1479,84 +1380,90 @@ static spl_ast_node_ref_vec_t parse_aggregate_init_body(parser_t *p) { } break; } - if (!expect(p, TOK_R_BRACE, "expected '}' in struct literal")) + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACE) { + SPL_FATAL(t, "expected '}' in struct literal"); return agg_vec; + } + advance(p); return agg_vec; } static spl_ast_node_ref_t parse_primary(parser_t *p) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); if (!t) { - parse_error(p, t, "unexpected expression start"); + SPL_FATAL(t, "unexpected expression start"); return 0; } switch (t->type) { case TOK_INT_LITERAL: { advance(p); - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_INTEGER); + spl_ast_node_ref_t pr = new_node(p, SPL_AST_EXPR_INTEGER_LIT, t); node_at(p->ast, pr)->primary_expr.integer_expr = parse_int_literal(t); - return wrap_expr(p, pr); + return pr; } case TOK_FLOAT_LITERAL: { advance(p); - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_FLOAT); + spl_ast_node_ref_t pr = new_node(p, SPL_AST_EXPR_FLOAT_LIT, t); node_at(p->ast, pr)->primary_expr.float_expr = parse_float_literal(t); - return wrap_expr(p, pr); + return pr; } case TOK_CHAR_LITERAL: { advance(p); - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_CHAR_LIT); + spl_ast_node_ref_t pr = new_node(p, SPL_AST_EXPR_CHAR_LIT, t); node_at(p->ast, pr)->primary_expr.char_lit_expr = parse_char_literal(t); - return wrap_expr(p, pr); + return pr; } case TOK_STRING_LITERAL: { advance(p); - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_STRING_LIT); + spl_ast_node_ref_t pr = new_node(p, SPL_AST_EXPR_STRING_LIT, t); node_at(p->ast, pr)->primary_expr.string_lit_expr = parse_string_literal(t); - return wrap_expr(p, pr); + return pr; } case KW_TRUE: { advance(p); - return wrap_expr(p, mk_primary(p, t, SPL_AST_TRUE)); + return new_node(p, SPL_AST_EXPR_TRUE, t); } case KW_FALSE: { advance(p); - return wrap_expr(p, mk_primary(p, t, SPL_AST_FALSE)); + return new_node(p, SPL_AST_EXPR_FALSE, t); } case KW_NULL: { advance(p); - return wrap_expr(p, mk_primary(p, t, SPL_AST_NULL)); + return new_node(p, SPL_AST_EXPR_NULL, t); + } + case KW_UNDEFINDED: { + advance(p); + return new_node(p, SPL_AST_EXPR_UNDEFINED, t); } case TOK_IDENT: { advance(p); if (peek(p) && peek(p)->type == TOK_L_BRACE && !p->stop_agg) { - /* 结构体字面量 T { .f1 = e1, ... } */ spl_ast_node_ref_vec_t agg_vec = parse_aggregate_init_body(p); - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_ARGGREGATE_INIT); + spl_ast_node_ref_t pr = new_node(p, SPL_AST_ARGGREGATE_INIT, t); node_at(p->ast, pr)->primary_expr.aggregate_init.name = sdupn(t->lexeme, t->len); node_at(p->ast, pr)->primary_expr.aggregate_init.expr = agg_vec; - return wrap_expr(p, pr); + return pr; } - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_IDENT); + spl_ast_node_ref_t pr = new_node(p, SPL_AST_EXPR_IDENT, t); node_at(p->ast, pr)->primary_expr.ident = sdupn(t->lexeme, t->len); - return wrap_expr(p, pr); + return pr; } case TOK_DOT: { - /* 匿名聚合字面量 .{ .f = e };primary 位置裸 '.' 非法 */ - spl_tok_t *nx = peek_next(p); + advance(p); + const spl_tok_t *nx = peek(p); if (nx && nx->type == TOK_L_BRACE && !p->stop_agg) { - advance(p); spl_ast_node_ref_vec_t agg_vec = parse_aggregate_init_body(p); - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_ARGGREGATE_INIT); + spl_ast_node_ref_t pr = new_node(p, SPL_AST_ARGGREGATE_INIT, t); node_at(p->ast, pr)->primary_expr.aggregate_init.name = NULL; node_at(p->ast, pr)->primary_expr.aggregate_init.expr = agg_vec; - return wrap_expr(p, pr); + return pr; } - parse_error(p, t, "unexpected '.' in expression"); + SPL_FATAL(t, "unexpected '.' in expression"); return 0; } case KW_ANY: - parse_error(p, t, "unexpected '_' in expression"); + SPL_FATAL(t, "unexpected '_' in expression"); return 0; case TOK_AT: case TOK_SHARP: @@ -1564,284 +1471,339 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) { case TOK_L_PAREN: { advance(p); spl_ast_node_ref_t e = parse_expr(p); - if (!expect(p, TOK_R_PAREN, "expected ')' in parenthesized expression")) + + t = peek(p); + if (t == NULL || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in parenthesized expression"); return e; - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_EXPR_EXPR); - node_at(p->ast, pr)->primary_expr.expr = e; - return wrap_expr(p, pr); + } + advance(p); + return e; } case TOK_L_BRACKET: return parse_array_literal(p); case TOK_L_BRACE: { spl_ast_node_ref_vec_t bvec = parse_block(p); - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_BLOCK_EXPR); + spl_ast_node_ref_t pr = new_node(p, SPL_AST_BLOCK_EXPR, t); node_at(p->ast, pr)->primary_expr.block_expr = bvec; - return wrap_expr(p, pr); + return pr; } default: - parse_error(p, t, "unrecognized expression"); + SPL_FATAL(t, "unrecognized expression"); return 0; } } -/* BuiltinExpr <- (AT / SHARP) IDENTIFIER (LPAREN ExprList? RPAREN) */ static spl_ast_node_ref_t parse_builtin(parser_t *p) { - spl_tok_t *t = peek(p); - advance(p); /* AT / SHARP */ - spl_tok_t *name = peek(p); + const spl_tok_t *t = peek(p); + Assert(t && (t->type == TOK_AT || t->type == TOK_SHARP)); + advance(p); + const spl_tok_t *name = peek(p); if (!name || name->type != TOK_IDENT) { - parse_error(p, name, "expected builtin name"); + SPL_FATAL(name, "expected builtin name"); return 0; } advance(p); - if (!expect(p, TOK_L_PAREN, "expected '(' in builtin call")) + + t = peek(p); + if (t == NULL || t->type != TOK_L_PAREN) { + SPL_FATAL(t, "expected '(' in builtin call"); return 0; + } + advance(p); + spl_ast_node_ref_vec_t args = parse_expr_list(p); - if (!expect(p, TOK_R_PAREN, "expected ')' in builtin call")) + + t = peek(p); + if (t == NULL || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in builtin call"); return 0; - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_BUILTIN_EXPR); + } + advance(p); + + spl_ast_node_ref_t pr = new_node(p, SPL_AST_BUILTIN_EXPR, t); node_at(p->ast, pr)->primary_expr.builtin_expr.ident = sdupn(name->lexeme, name->len); node_at(p->ast, pr)->primary_expr.builtin_expr.expr_list = args; - return wrap_expr(p, pr); + return pr; } -/* ArrayLiteral <- LBRACKET INTEGER RBRACKET TypeExpr LBRACE ExprList? RBRACE */ static spl_ast_node_ref_t parse_array_literal(parser_t *p) { - spl_tok_t *t = peek(p); + const spl_tok_t *t = peek(p); advance(p); /* L_BRACKET */ isize integer = 0; - if (peek(p) && peek(p)->type == TOK_INT_LITERAL) { - integer = parse_int_literal(peek(p)); + + t = peek(p); + if (t && t->type == TOK_INT_LITERAL) { + integer = parse_int_literal(t); advance(p); } - if (!expect(p, TOK_R_BRACKET, "expected ']' in array literal")) + + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in array literal"); return 0; + } + advance(p); + spl_ast_node_ref_t te = parse_type_expr(p); - if (!expect(p, TOK_L_BRACE, "expected '{' in array literal")) + + t = peek(p); + if (t == NULL || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected '{' in array literal"); return 0; + } + advance(p); + spl_ast_node_ref_vec_t items = parse_expr_list(p); - if (!expect(p, TOK_R_BRACE, "expected '}' in array literal")) + + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACE) { + SPL_FATAL(t, "expected '}' in array literal"); return 0; - spl_ast_node_ref_t pr = mk_primary(p, t, SPL_AST_ARRAY_LIT); + } + advance(p); + + spl_ast_node_ref_t pr = new_node(p, SPL_AST_ARRAY_LIT, t); node_at(p->ast, pr)->primary_expr.array_lit_expr.integer = integer; node_at(p->ast, pr)->primary_expr.array_lit_expr.type_expr = te; node_at(p->ast, pr)->primary_expr.array_lit_expr.expr_list = items; - return wrap_expr(p, pr); + return pr; } static spl_ast_node_ref_t parse_expr(parser_t *p) { return parse_assign(p); } -/* ================================================================ - * 类型表达 * ================================================================ */ +// 类型表达式 -/* TypeExpr <- PrefixTypeOp* TypeBase */ -static spl_ast_node_ref_t parse_type_expr(parser_t *p) { - spl_tok_t *t = peek(p); - spl_ast_node_ref_vec_t type_prefixs; - vec_init(type_prefixs); - while (1) { - spl_tok_t *s = peek(p); - if (!s) - break; - if (s->type == TOK_MUL) { - advance(p); - spl_ast_node_ref_t pf = new_node(p, SPL_AST_TYPE_EXPR, s); - node_at(p->ast, pf)->prefix_type.pointer = 1; - node_at(p->ast, pf)->prefix_type.array_size = 0; - vec_push(type_prefixs, pf); - } else if (s->type == TOK_L_BRACKET) { - advance(p); - int sz = 0; - if (peek(p) && peek(p)->type == TOK_INT_LITERAL) { - sz = (int)parse_int_literal(peek(p)); - advance(p); - } - if (!expect(p, TOK_R_BRACKET, "expected ']' in array type")) - return 0; - spl_ast_node_ref_t pf = new_node(p, SPL_AST_TYPE_EXPR, s); - node_at(p->ast, pf)->prefix_type.pointer = 2; - node_at(p->ast, pf)->prefix_type.array_size = sz; - vec_push(type_prefixs, pf); - } else { - break; - } +static spl_ast_node_kind_t type_atom_kind_of(spl_tok_type_t tt) { + switch (tt) { + case KW_VOID: + return SPL_AST_TYPE_VOID; + case KW_BOOL: + return SPL_AST_TYPE_BOOL; + case KW_ANY: + return SPL_AST_TYPE_ANY; + default: + return SPL_AST_COUNT; } - spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_EXPR, t); - node_at(p->ast, ref)->type_expr.type_prefixs = type_prefixs; - node_at(p->ast, ref)->type_expr.spl_base_type = NULL; +} + +static const struct { + const char *name; + spl_ast_node_kind_t kind; +} type_kw_table[] = { + {"i8", SPL_AST_TYPE_I8}, {"u8", SPL_AST_TYPE_U8}, {"i16", SPL_AST_TYPE_I16}, + {"u16", SPL_AST_TYPE_U16}, {"i32", SPL_AST_TYPE_I32}, {"u32", SPL_AST_TYPE_U32}, + {"i64", SPL_AST_TYPE_I64}, {"u64", SPL_AST_TYPE_U64}, {"isize", SPL_AST_TYPE_ISIZE}, + {"usize", SPL_AST_TYPE_USIZE}, {"f32", SPL_AST_TYPE__F32}, {"f64", SPL_AST_TYPE__F64}, +}; + +static spl_ast_node_kind_t type_kw_kind_of(const spl_tok_t *t) { + if (t->type == TOK_IDENT) { + const char *s = t->lexeme; + usize slen = t->len; + for (usize i = 0; i < sizeof(type_kw_table) / sizeof(type_kw_table[0]); i++) { + const char *nm = type_kw_table[i].name; + if (slen == strlen(nm) && memcmp(s, nm, slen) == 0) + return type_kw_table[i].kind; + } + return SPL_AST_COUNT; + } + return type_atom_kind_of(t->type); +} + +static spl_ast_node_ref_t parse_type_expr(parser_t *p) { + const spl_tok_t *t = peek(p); + if (!t) { + SPL_FATAL(t, "expected type"); + return 0; + } + if (t->type == TOK_MUL) { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_POINTER, t); + node_at(p->ast, ref)->type_expr.pointer_type.pointee = parse_type_expr(p); + return ref; + } + if (t->type == TOK_L_BRACKET) { + advance(p); + spl_ast_node_ref_t sz = 0; + + t = peek(p); + if (t && t->type == TOK_INT_LITERAL) { + sz = new_node(p, SPL_AST_EXPR_INTEGER_LIT, t); + node_at(p->ast, sz)->primary_expr.integer_expr = parse_int_literal(peek(p)); + advance(p); + } + + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in array type"); + return 0; + } + advance(p); + + spl_ast_node_ref_t ref = 0; + if (sz == 0) { + ref = new_node(p, SPL_AST_TYPE_SLICE, t); + node_at(p->ast, ref)->type_expr.slice_type.element = parse_type_expr(p); + } else { + ref = new_node(p, SPL_AST_TYPE_ARRAY, t); + node_at(p->ast, ref)->type_expr.array_type.element = parse_type_expr(p); + node_at(p->ast, ref)->type_expr.array_type.size = sz; + } + Assert(ref != 0); + return ref; + } + return parse_type_base(p); +} + +static spl_ast_node_ref_t parse_type_base(parser_t *p) { spl_ast_node_ref_vec_t attr_list; vec_init(attr_list); parse_attr_list(p, &attr_list); - node_at(p->ast, ref)->type_expr.attr_list = attr_list; - spl_tok_t *bt = peek(p); - if (bt && bt->type == KW_FN) { - node_at(p->ast, ref)->type_expr.kind = SPL_AST_BASE_TYPE_FN; + + spl_ast_node_ref_t base = 0; + const spl_tok_t *bt = peek(p); + if (!bt) { + SPL_FATAL(bt, "expected type base"); + return 0; + } + + const spl_tok_t *t = NULL; + if (bt->type == KW_FN) { advance(p); /* KW_FN */ - if (!expect(p, TOK_L_PAREN, "expected '(' in function type")) - return ref; + + t = peek(p); + if (t == NULL || t->type != TOK_L_PAREN) { + SPL_FATAL(t, "expected '(' in function type"); + return 0; + } + advance(p); + + base = new_node(p, SPL_AST_BASE_TYPE_FN, bt); + node_at(p->ast, base)->type_expr.attr_list = attr_list; spl_ast_node_ref_vec_t param_list; vec_init(param_list); while (!p->failed && peek(p) && peek(p)->type != TOK_R_PAREN) { spl_ast_node_ref_t pt = parse_type_expr(p); - spl_ast_node_ref_t pd = new_node(p, SPL_AST_MEMBER_DECL, t); - node_at(p->ast, pd)->param_decl.name = NULL; - node_at(p->ast, pd)->param_decl.type_expr = pt; - vec_push(param_list, pd); + vec_push(param_list, pt); if (peek(p) && peek(p)->type == TOK_COMMA) { advance(p); continue; } break; } - if (!expect(p, TOK_R_PAREN, "expected ')' in function type")) - return ref; - spl_ast_node_ref_t ret = parse_type_expr(p); - node_at(p->ast, ref)->type_expr.fn_type.param_list = param_list; - node_at(p->ast, ref)->type_expr.fn_type.type_expr = ret; - } else if (bt && (bt->type == KW_STRUCT || bt->type == KW_UNION || bt->type == KW_ENUM)) { - /* 内联聚合类型: struct { ... } / union { ... } / enum { ... } */ - node_at(p->ast, ref)->type_expr.kind = (bt->type == KW_STRUCT) ? SPL_AST_TYPE_STRUCT - : (bt->type == KW_UNION) ? SPL_AST_TYPE_UNION - : SPL_AST_TYPE_ENUM; + + t = peek(p); + if (t == NULL || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in function type"); + return 0; + } advance(p); - if (!expect(p, TOK_L_BRACE, "expected '{' in aggregate type")) - return ref; + + spl_ast_node_ref_t ret = parse_type_expr(p); + node_at(p->ast, base)->type_expr.fn_type.param_list = param_list; + node_at(p->ast, base)->type_expr.fn_type.type_expr = ret; + return base; + } + if (bt->type == KW_STRUCT || bt->type == KW_UNION || bt->type == KW_ENUM) { + spl_ast_node_kind_t aggk = (bt->type == KW_STRUCT) ? SPL_AST_TYPE_STRUCT + : (bt->type == KW_UNION) ? SPL_AST_TYPE_UNION + : SPL_AST_TYPE_ENUM; + advance(p); + + t = peek(p); + if (t == NULL || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected '{' in aggregate type"); + return 0; + } + advance(p); + + base = new_node(p, aggk, bt); + node_at(p->ast, base)->type_expr.attr_list = attr_list; spl_ast_node_ref_vec_t members; vec_init(members); while (1) { - spl_tok_t *m = peek(p); - if (!m || m->type == TOK_R_BRACE || m->type == TOK_EOF) + t = peek(p); + if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF) break; spl_ast_node_ref_t md = parse_container_declaration(p); if (md) vec_push(members, md); } - if (!expect(p, TOK_R_BRACE, "expected '}' in aggregate type")) - return ref; - node_at(p->ast, ref)->type_expr.aggregate_list = members; - } else { - node_at(p->ast, ref)->type_expr.kind = SPL_AST_BASE_TYPE_PATH; - spl_ast_node_ref_vec_t type_path; - vec_init(type_path); - while (1) { - spl_ast_node_ref_t atom = parse_type_atom(p); - if (!atom) - break; - vec_push(type_path, atom); - if (peek(p) && peek(p)->type == TOK_DOT) { - advance(p); - continue; - } + + t = peek(p); + if (t == NULL || t->type != TOK_R_BRACE) { + SPL_FATAL(t, "expected '}' in aggregate type"); + return 0; + } + advance(p); + + node_at(p->ast, base)->type_expr.aggregate_list = members; + return base; + } + spl_ast_node_kind_t kwk = type_kw_kind_of(bt); + if (kwk != SPL_AST_COUNT) { + advance(p); + base = new_node(p, kwk, bt); + node_at(p->ast, base)->type_expr.attr_list = attr_list; + return base; + } + + if (bt->type != TOK_IDENT) { + SPL_FATAL(bt, "unrecognized type"); + return 0; + } + base = new_node(p, SPL_AST_BASE_TYPE_PATH, bt); + node_at(p->ast, base)->type_expr.attr_list = attr_list; + while (1) { + t = peek(p); + if (!t || t->type != TOK_IDENT) { + SPL_FATAL(t, "unrecognized type atom"); break; } - node_at(p->ast, ref)->type_expr.type_path = type_path; - if (type_path.size > 0) { - spl_ast_node_t *last = node_at(p->ast, type_path.data[type_path.size - 1]); - node_at(p->ast, ref)->type_expr.spl_base_type = last->type_atom.ident; + vec_push(node_at(p->ast, base)->type_expr.type_path.ident_vec, sdupn(t->lexeme, t->len)); + advance(p); + if (peek(p) && peek(p)->type == TOK_DOT) { + advance(p); + continue; } + break; } - return ref; + return base; } -/* TypeAtom <- 内置类型关键/ 内置TOK_IDENT) / _ / 自定义标识符 */ -static spl_ast_node_ref_t parse_type_atom(parser_t *p) { - spl_tok_t *t = peek(p); - if (!t) - return 0; - spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_EXPR, t); - int kind = -1; - switch (t->type) { - case KW_VOID: - kind = SPL_AST_TYPE_VOID; - break; - case KW_BOOL: - kind = SPL_AST_TYPE_BOOL; - break; - case KW_ANY: - kind = SPL_AST_TYPE_ANY; - break; - case TOK_IDENT: { - const char *s = t->lexeme; - usize slen = t->len; -#define IS_TY(NAME) (slen == (usize)(sizeof(NAME) - 1) && memcmp(s, NAME, sizeof(NAME) - 1) == 0) - if (IS_TY("i8")) - kind = SPL_AST_TYPE_I8; - else if (IS_TY("u8")) - kind = SPL_AST_TYPE_U8; - else if (IS_TY("i16")) - kind = SPL_AST_TYPE_I16; - else if (IS_TY("u16")) - kind = SPL_AST_TYPE_U16; - else if (IS_TY("i32")) - kind = SPL_AST_TYPE_I32; - else if (IS_TY("u32")) - kind = SPL_AST_TYPE_U32; - else if (IS_TY("i64")) - kind = SPL_AST_TYPE_I64; - else if (IS_TY("u64")) - kind = SPL_AST_TYPE_U64; - else if (IS_TY("isize")) - kind = SPL_AST_TYPE_ISIZE; - else if (IS_TY("usize")) - kind = SPL_AST_TYPE_USIZE; - else if (IS_TY("ptr")) - kind = SPL_AST_TYPE_PTR; - else if (IS_TY("f32")) - kind = SPL_AST_TYPE__F32; - else if (IS_TY("f64")) - kind = SPL_AST_TYPE__F64; - else { - kind = SPL_AST_TYPE_IDENT; - } -#undef IS_TY - break; - } - default: - parse_error(p, t, "unrecognized type"); - return 0; - } - node_at(p->ast, ref)->type_atom.kind = kind; - node_at(p->ast, ref)->type_atom.ident = sdupn(t->lexeme, t->len); - advance(p); - return ref; -} - -/* ================================================================ - * 公共 API - * ================================================================ */ - void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec) { - memset(ast, 0, sizeof(*ast)); - ast->input = *tok_vec; /* move:共token 数据 */ - vec_init(ast->buckets); + ast->input = *tok_vec; // move + vec_init(ast->node_buckets); + vec_init(ast->str_buckets); ast->root = 0; ast->parsed = 0; - /* 哨兵节点:ref 0 表示空引用,永不被真正使*/ - spl_ast_node_t n; - memset(&n, 0, sizeof(n)); - vec_push(ast->buckets, n); + + spl_ast_node_t n = {0}; + vec_push(ast->node_buckets, n); } void spl_ast_prase(spl_ast_t *ast) { - if (!ast || !ast->input.data || ast->buckets.size == 0) + if (!ast || !ast->input.data || ast->node_buckets.size == 0) return; parser_t p; p.ast = ast; p.pos = 0; p.failed = 0; ast->parsed = 0; + spl_tok_t *begin = &vec_at(ast->input, 0); spl_ast_node_ref_vec_t members; vec_init(members); while (!p.failed) { - spl_tok_t *t = peek(&p); + const spl_tok_t *t = peek(&p); if (!t || t->type == TOK_EOF) break; spl_ast_node_ref_t d = parse_container_declaration(&p); if (d) vec_push(members, d); } - spl_ast_node_ref_t root = new_node(&p, SPL_AST_CONTAINER_ITEM, NULL); + spl_ast_node_ref_t root = new_node(&p, SPL_AST_CONTAINER_ITEM, begin); node_at(ast, root)->container_item.members = members; ast->root = root; ast->parsed = p.failed ? -1 : 1; @@ -1850,38 +1812,14 @@ void spl_ast_prase(spl_ast_t *ast) { void spl_ast_drop(spl_ast_t *ast) { if (!ast) return; - if (ast->root) - drop_node(ast, ast->root, CTX_CONTAINER); - vec_free(ast->buckets); + vec_for(ast->str_buckets, idx) { free(vec_at(ast->str_buckets, idx)); } + vec_free(ast->str_buckets); + vec_free(ast->node_buckets); vec_free(ast->input); ast->parsed = 0; ast->root = 0; } -static walk_ctx_t ctx_from_kind(spl_ast_node_kind_t k) { - switch (k) { - case SPL_AST_CONTAINER_ITEM: - return CTX_CONTAINER; - case SPL_AST_FN_DECL: - case SPL_AST_FN_DEFINE: - case SPL_AST_TYPE_DECL: - case SPL_AST_VAR_DECL: - case SPL_AST_CONST_DECL: - case SPL_AST_MEMBER_DECL: - return CTX_DECL; - case SPL_AST_BLOCK_ITEM: - return CTX_BLOCK_ITEM; - case SPL_AST_EXPR: - return CTX_EXPR; - case SPL_AST_TYPE_EXPR: - return CTX_TYPE_EXPR; - case SPL_AST_ATTR_LIST: - return CTX_ATTR_ITEM; - default: - return CTX_CONTAINER; - } -} - void spl_ast_valid(spl_ast_t *ast) { if (!ast) return; @@ -1889,1545 +1827,330 @@ void spl_ast_valid(spl_ast_t *ast) { printf("valid: AST not parsed successfully (parsed=%d)\n", ast->parsed); return; } - validate_node(ast, ast->root, CTX_CONTAINER); + // TODO } +typedef VEC(char) dump_stack_t; +static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, int last); + void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) { - if (!ast || !node || node >= ast->buckets.size) + if (!ast || !node || node >= ast->node_buckets.size) return; - dump_node(ast, node, ctx_from_kind(ast->buckets.data[node].kind), "", 1); + dump_stack_t stack; + vec_init(stack); + dump_node(ast, node, &stack, 1); } -/* ================================================================ - * dump - * ================================================================ */ +#define dump_vec(_ast, _vec, _stack) \ + do { \ + vec_for(_vec, _i) { dump_node(_ast, vec_at(_vec, _i), _stack, _i + 1 == vec_size(_vec)); } \ + } while (0) -#define STR(s) ((s) ? (s) : "") +static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, int last) { + spl_ast_node_t *node = &vec_at(ast->node_buckets, node_ref); -static const char *expr_op_name(int op) { - switch (op) { - case SPL_AST_ASSIGN_EXPR: - return "="; - case SPL_AST_ASSIGN_ADD_EXPR: - return "+="; - case SPL_AST_ASSIGN_sUB_EXPR: - return "-="; - case SPL_AST_ASSIGN_MUL_EXPR: - return "*="; - case SPL_AST_ASSIGN_DIV_EXPR: - return "/="; - case SPL_AST_ASSIGN_MOD_EXPR: - return "%="; - case SPL_AST_ASSIGN_AND_EXPR: - return "&="; - case SPL_AST_ASSIGN_OR_EXPR: - return "|="; - case SPL_AST_ASSIGN_XOR_EXPR: - return "^="; - case SPL_AST_ASSIGN_LSHIFT_EXPR: - return "<<="; - case SPL_AST_ASSIGN_USHIFT_EXPR: - return ">>="; - case SPL_AST_BOOLOR_EXPR: - return "||"; - case SPL_AST_BOOLAND_EXPR: - return "&&"; - case SPL_AST_BITOR_EXPR: - return "|"; - case SPL_AST_BITXOR_EXPR: - return "^"; - case SPL_AST_BITAND_EXPR: - return "&"; - case SPL_AST_CMPEQ_EXPR: - return "=="; - case SPL_AST_CMPNE_EXPR: - return "!="; - case SPL_AST_CMP_LE_EXPR: - return "<="; - case SPL_AST_CMP_GE_EXPR: - return ">="; - case SPL_AST_CMP_LT_EXPR: - return "<"; - case SPL_AST_CMP_GT_EXPR: - return ">"; - case SPL_AST_RANGE_EXPR: - return ".."; - case SPL_AST_LSHIFT_EXPR: - return "<<"; - case SPL_AST_RSHIFT_EXPR: - return ">>"; - case SPL_AST_ADD_EXPR: - return "+"; - case SPL_AST_SUB_EXPR: - return "-"; - case SPL_AST_MUL_EXPR: - return "*"; - case SPL_AST_DIV_EXPR: - return "/"; - case SPL_AST_MOD_EXPR: - return "%"; - case SPL_AST_PREFIX_EXPR: - return "prefix"; - case SPL_AST_POSTFIX_EXPR: - return "postfix"; - case SPL_AST_PRIMARY_EXPR: - return "primary"; - default: - return "?"; - } -} - -static const char *type_atom_name(int k) { - switch (k) { - case SPL_AST_TYPE_VOID: - return "void"; - case SPL_AST_TYPE_BOOL: - return "bool"; - case SPL_AST_TYPE_I8: - return "i8"; - case SPL_AST_TYPE_U8: - return "u8"; - case SPL_AST_TYPE_I16: - return "i16"; - case SPL_AST_TYPE_U16: - return "u16"; - case SPL_AST_TYPE_I32: - return "i32"; - case SPL_AST_TYPE_U32: - return "u32"; - case SPL_AST_TYPE_I64: - return "i64"; - case SPL_AST_TYPE_U64: - return "u64"; - case SPL_AST_TYPE_ISIZE: - return "isize"; - case SPL_AST_TYPE_USIZE: - return "usize"; - case SPL_AST_TYPE__F32: - return "f32"; - case SPL_AST_TYPE__F64: - return "f64"; - case SPL_AST_TYPE_PTR: - return "ptr"; - case SPL_AST_TYPE_ANY: - return "_"; - case SPL_AST_TYPE_IDENT: - return "ident"; - default: - return "?"; - } -} - -static const spl_dumptree_style_t *dt = &spl_dumptree_ascii_style; - -/* 打印一行节点标签:缩进骨架 + 分支符 + label */ -static void node_label(const char *prefix, int is_last, const char *fmt, ...) { - va_list ap; - printf("%s%s ", prefix, is_last ? dt->last_branch : dt->branch); - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); + for (usize i = 0; i < vec_size(*stack); i++) + printf("%s", vec_at(*stack, i) ? " " : "| "); + printf("%s%s #%zu", last ? "`-" : "|-", spl_ast_kind_name(node->kind), node_ref); + if (node->dbg.fpath) + printf(" (%d:%d)", node->dbg.line, node->dbg.col); printf("\n"); -} -/* 以每个子节点为一行递归打印 vec(父级骨架由 prefix/is_last 决定) */ -static void dump_vec_children(spl_ast_t *ast, spl_ast_node_ref_vec_t *vec, walk_ctx_t ctx, - const char *prefix, int is_last) { - char cp[512]; - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - for (usize i = 0; i < vec->size; i++) - dump_node(ast, vec->data[i], ctx, cp, (int)(i == vec->size - 1)); -} - -static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx, const char *prefix, - int is_last); -static void dump_vec_children(spl_ast_t *ast, spl_ast_node_ref_vec_t *vec, walk_ctx_t ctx, - const char *prefix, int is_last); -static void dump_expr(spl_ast_t *ast, spl_ast_node_ref_t ref, const char *prefix, int is_last); -static void dump_type_expr(spl_ast_t *ast, spl_ast_node_ref_t ref, const char *prefix, int is_last); -static void dump_block(spl_ast_t *ast, spl_ast_node_ref_vec_t *block, const char *prefix, - int is_last); -static void expr_inline(spl_ast_t *ast, spl_ast_node_ref_t ref, char *out, size_t cap); -static void type_inline(spl_ast_t *ast, spl_ast_node_ref_t ref, char *out, size_t cap); - -/* ---- 内联文本渲染(供树标签使用) ---- */ - -static void expr_list_inline(spl_ast_t *ast, spl_ast_node_ref_vec_t *vec, char *out, size_t cap); -static void agg_items_inline(spl_ast_t *ast, spl_ast_node_ref_vec_t *items, char *out, size_t cap); - -/* 字符串字面量转义:写入 "..." */ -static void escape_string(char *out, size_t cap, const char *s) { - size_t w = strlen(out); - out[w++] = '"'; - for (; *s && w < cap - 2; s++) { - unsigned char c = (unsigned char)*s; - switch (c) { - case '\n': - out[w++] = '\\'; - out[w++] = 'n'; - break; - case '\t': - out[w++] = '\\'; - out[w++] = 't'; - break; - case '\r': - out[w++] = '\\'; - out[w++] = 'r'; - break; - case '"': - out[w++] = '\\'; - out[w++] = '"'; - break; - case '\\': - out[w++] = '\\'; - out[w++] = '\\'; - break; - default: - if (c < 0x20 || c == 0x7f) { - if (w + 4 >= cap) - break; - out[w++] = '\\'; - out[w++] = 'x'; - out[w++] = "0123456789abcdef"[c >> 4]; - out[w++] = "0123456789abcdef"[c & 15]; - } else if (w + 1 < cap) { - out[w++] = (char)c; - } - break; - } - } - out[w++] = '"'; - out[w] = '\0'; -} - -/* 表达式完整文本(含 primary/prefix/postfix 包装折叠) */ -static void expr_inline(spl_ast_t *ast, spl_ast_node_ref_t ref, char *out, size_t cap) { - if (!ref || ref >= ast->buckets.size) { - strncat(out, "?", cap - strlen(out) - 1); - return; - } - spl_ast_node_t *n = &ast->buckets.data[ref]; - char tmp[512]; - int op = n->expr.op; - switch (op) { - case SPL_AST_PRIMARY_EXPR: { - spl_ast_node_t *pn = &ast->buckets.data[n->expr.op_expr.left]; - switch (pn->primary_expr.kind) { - case SPL_AST_INTEGER: - snprintf(tmp, sizeof tmp, "%lld", (long long)pn->primary_expr.integer_expr); - break; - case SPL_AST_FLOAT: - snprintf(tmp, sizeof tmp, "%g", pn->primary_expr.float_expr); - break; - case SPL_AST_CHAR_LIT: - snprintf(tmp, sizeof tmp, "'%c'", (int)pn->primary_expr.char_lit_expr); - break; - case SPL_AST_STRING_LIT: - tmp[0] = '\0'; - escape_string(tmp, sizeof tmp, STR(pn->primary_expr.string_lit_expr)); - break; - case SPL_AST_TRUE: - snprintf(tmp, sizeof tmp, "true"); - break; - case SPL_AST_FALSE: - snprintf(tmp, sizeof tmp, "false"); - break; - case SPL_AST_NULL: - snprintf(tmp, sizeof tmp, "null"); - break; - case SPL_AST_IDENT: - snprintf(tmp, sizeof tmp, "%s", STR(pn->primary_expr.ident)); - break; - case SPL_AST_ARGGREGATE_INIT: - snprintf(tmp, sizeof tmp, "%s{ ", STR(pn->primary_expr.aggregate_init.name)); - agg_items_inline(ast, &pn->primary_expr.aggregate_init.expr, tmp, sizeof tmp); - strncat(tmp, " }", sizeof tmp - strlen(tmp) - 1); - break; - case SPL_AST_EXPR_EXPR: - tmp[0] = '('; - tmp[1] = '\0'; - expr_inline(ast, pn->primary_expr.expr, tmp, sizeof tmp); - strncat(tmp, ")", sizeof tmp - strlen(tmp) - 1); - break; - case SPL_AST_ARRAY_LIT: - snprintf(tmp, sizeof tmp, "[%lld]", (long long)pn->primary_expr.array_lit_expr.integer); - if (pn->primary_expr.array_lit_expr.type_expr) - type_inline(ast, pn->primary_expr.array_lit_expr.type_expr, tmp, sizeof tmp); - strncat(tmp, "{ ", sizeof tmp - strlen(tmp) - 1); - expr_list_inline(ast, &pn->primary_expr.array_lit_expr.expr_list, tmp, sizeof tmp); - strncat(tmp, " }", sizeof tmp - strlen(tmp) - 1); - break; - case SPL_AST_BUILTIN_EXPR: - snprintf(tmp, sizeof tmp, "@%s(", STR(pn->primary_expr.builtin_expr.ident)); - expr_list_inline(ast, &pn->primary_expr.builtin_expr.expr_list, tmp, sizeof tmp); - strncat(tmp, ")", sizeof tmp - strlen(tmp) - 1); - break; - case SPL_AST_BLOCK_EXPR: - snprintf(tmp, sizeof tmp, "{...}"); - break; - default: - snprintf(tmp, sizeof tmp, "?"); - break; - } - strncat(out, tmp, cap - strlen(out) - 1); + vec_push(*stack, last); + switch (node->kind) { + case SPL_AST_NONE: + UNREACHABLE(); break; - } - case SPL_AST_PREFIX_EXPR: { - spl_ast_node_t *pn = &ast->buckets.data[n->expr.op_expr.left]; - const char *pn_txt = "?"; - switch (pn->prefix_expr.kind) { - case SPL_AST_MINUS_EXPR: - pn_txt = "-"; - break; - case SPL_AST_BANG_EXPR: - pn_txt = "!"; - break; - case SPL_AST_TILDE_EXPR: - pn_txt = "~"; - break; - case SPL_AST_AMPERSAND_EXPR: - pn_txt = "&"; - break; - case SPL_AST_ASTERISK_EXPR: - pn_txt = "*"; - break; - } - strncat(out, pn_txt, cap - strlen(out) - 1); - expr_inline(ast, pn->prefix_expr.postfix_expr, out, cap); + + case SPL_AST_CONTAINER_ITEM: + dump_vec(ast, node->container_item.attr_list, stack); + dump_vec(ast, node->container_item.members, stack); break; - } - case SPL_AST_POSTFIX_EXPR: { - spl_ast_node_t *pn = &ast->buckets.data[n->expr.op_expr.left]; - expr_inline(ast, pn->postfix_expr.primary_expr, out, cap); - switch (pn->postfix_expr.kind) { - case SPL_AST_CALL_EXPR: - strncat(out, "(", cap - strlen(out) - 1); - expr_list_inline(ast, &pn->postfix_expr.call_expr, out, cap); - strncat(out, ")", cap - strlen(out) - 1); - break; - case SPL_AST_FIELD_EXPR: { - char t[256]; - snprintf(t, sizeof t, ".%s", STR(pn->postfix_expr.field_expr)); - strncat(out, t, cap - strlen(out) - 1); - break; - } - case SPL_AST_DEREF_EXPR: - strncat(out, ".*", cap - strlen(out) - 1); - break; - case SPL_AST_INDEX_EXPR: - strncat(out, "[", cap - strlen(out) - 1); - expr_inline(ast, pn->postfix_expr.index_expr, out, cap); - strncat(out, "]", cap - strlen(out) - 1); - break; - case SPL_AST_SLICE_EXPR: - strncat(out, "[", cap - strlen(out) - 1); - if (pn->postfix_expr.slice_expr.begin) - expr_inline(ast, pn->postfix_expr.slice_expr.begin, out, cap); - strncat(out, "..", cap - strlen(out) - 1); - if (pn->postfix_expr.slice_expr.end) - expr_inline(ast, pn->postfix_expr.slice_expr.end, out, cap); - strncat(out, "]", cap - strlen(out) - 1); - break; - case SPL_AST_AS_EXPR: - strncat(out, " as ", cap - strlen(out) - 1); - if (pn->postfix_expr.type_expr) - type_inline(ast, pn->postfix_expr.type_expr, out, cap); - break; - default: - break; - } + + case SPL_AST_FN_DECL: + case SPL_AST_FN_DEFINE: + dump_vec(ast, node->fn_decl.attr_list, stack); + dump_vec(ast, node->fn_decl.param_list, stack); + if (node->fn_decl.type_expr) + dump_node(ast, node->fn_decl.type_expr, stack, 1); + dump_vec(ast, node->fn_decl.block, stack); break; - } - default: - expr_inline(ast, n->expr.op_expr.left, out, cap); - { - char t[64]; - snprintf(t, sizeof t, " %s ", expr_op_name(op)); - strncat(out, t, cap - strlen(out) - 1); - } - if (n->expr.op_expr.right) - expr_inline(ast, n->expr.op_expr.right, out, cap); + + case SPL_AST_TYPE_DECL: + if (node->type_decl.type_expr) + dump_node(ast, node->type_decl.type_expr, stack, 1); break; - } -} -/* 逗号分隔的表达式文本 */ -static void expr_list_inline(spl_ast_t *ast, spl_ast_node_ref_vec_t *vec, char *out, size_t cap) { - for (usize i = 0; i < vec->size; i++) { - if (i) - strncat(out, ", ", cap - strlen(out) - 1); - expr_inline(ast, vec->data[i], out, cap); - } -} + case SPL_AST_VAR_DECL: + case SPL_AST_CONST_DECL: + dump_vec(ast, node->var_const_decl.attr_list, stack); + if (node->var_const_decl.type_expr) + dump_node(ast, node->var_const_decl.type_expr, stack, 0); + if (node->var_const_decl.expr) + dump_node(ast, node->var_const_decl.expr, stack, 1); + break; -/* 属性文本:@name(args) */ -static void attrs_inline(spl_ast_t *ast, spl_ast_node_ref_vec_t *attrs, char *out, size_t cap) { - for (usize i = 0; i < attrs->size; i++) { - spl_ast_node_t *a = &ast->buckets.data[attrs->data[i]]; - char t[256]; - snprintf(t, sizeof t, "@%s(", STR(a->attr_item.ident)); - strncat(out, t, cap - strlen(out) - 1); - expr_list_inline(ast, &a->attr_item.expr_list, out, cap); - strncat(out, ") ", cap - strlen(out) - 1); - } -} + case SPL_AST_MEMBER_DECL: + dump_vec(ast, node->member_decl.attr_list, stack); + if (node->member_decl.type_expr) + dump_node(ast, node->member_decl.type_expr, stack, 1); + break; -/* 参数文本:a: T, b: U */ -static void params_inline(spl_ast_t *ast, spl_ast_node_ref_vec_t *params, char *out, size_t cap) { - for (usize i = 0; i < params->size; i++) { - spl_ast_node_t *p = &ast->buckets.data[params->data[i]]; - if (i) - strncat(out, ", ", cap - strlen(out) - 1); - if (!p->param_decl.name) { - strncat(out, "...", cap - strlen(out) - 1); - continue; + case SPL_AST_PARAM_DECL: + dump_vec(ast, node->param_decl.attr_list, stack); + if (node->param_decl.type_expr) + dump_node(ast, node->param_decl.type_expr, stack, 1); + break; + + case SPL_AST_ATTR_ITEM: + dump_vec(ast, node->attr_item.expr_list, stack); + break; + + case SPL_AST_ARGG_INIT_ITEM: + if (node->aggregate_init_item.expr) + dump_node(ast, node->aggregate_init_item.expr, stack, 1); + break; + + case SPL_AST_IF_STATEMENT: + if (node->if_statement.expr) + dump_node(ast, node->if_statement.expr, stack, 0); + dump_vec(ast, node->if_statement.if_block, stack); + dump_vec(ast, node->if_statement.else_block, stack); + break; + + case SPL_AST_IFVAR_STATEMENT: + if (node->ifvar_statement.packed_expr) + dump_node(ast, node->ifvar_statement.packed_expr, stack, 0); + dump_vec(ast, node->ifvar_statement.if_block, stack); + dump_vec(ast, node->ifvar_statement.else_block, stack); + break; + + case SPL_AST_WHILE_STATEMENT: + if (node->while_statement.expr) + dump_node(ast, node->while_statement.expr, stack, 0); + dump_vec(ast, node->while_statement.while_block, stack); + break; + + case SPL_AST_LOOP_STATEMENT: + dump_vec(ast, node->loop_statement.loop_block, stack); + break; + + case SPL_AST_FOR_STATEMENT: + dump_vec(ast, node->for_statement.expr_vec, stack); + for (usize i = 0; i < vec_size(node->for_statement.ident_vec); i++) { + for (usize j = 0; j < vec_size(*stack); j++) + printf("%s", vec_at(*stack, j) ? " " : "| "); + printf("%sfor_binding %s\n", + i + 1 == vec_size(node->for_statement.ident_vec) ? "`-" : "|-", + node->for_statement.ident_vec.data[i]); } - attrs_inline(ast, &p->param_decl.attr_list, out, cap); - char t[256]; - snprintf(t, sizeof t, "%s: ", STR(p->param_decl.name)); - strncat(out, t, cap - strlen(out) - 1); - if (p->param_decl.type_expr) - type_inline(ast, p->param_decl.type_expr, out, cap); - else - strncat(out, "?", cap - strlen(out) - 1); - } -} + dump_vec(ast, node->for_statement.block, stack); + break; -/* 聚合初始化项文本:.f = expr */ -static void agg_items_inline(spl_ast_t *ast, spl_ast_node_ref_vec_t *items, char *out, size_t cap) { - for (usize i = 0; i < items->size; i++) { - spl_ast_node_t *it = &ast->buckets.data[items->data[i]]; - if (i) - strncat(out, ", ", cap - strlen(out) - 1); - char t[128]; - snprintf(t, sizeof t, ".%s", STR(it->aggregate_init_item.ident)); - strncat(out, t, cap - strlen(out) - 1); - if (it->aggregate_init_item.expr) { - strncat(out, " = ", cap - strlen(out) - 1); - expr_inline(ast, it->aggregate_init_item.expr, out, cap); - } - } -} + case SPL_AST_MATCH_STATEMENT: + if (node->match_statement.expr) + dump_node(ast, node->match_statement.expr, stack, 0); + dump_vec(ast, node->match_statement.paced_exprs, stack); + dump_vec(ast, node->match_statement.match_block, stack); + break; + + case SPL_AST_RET_STATEMENT: + if (node->ret_statement.expr) + dump_node(ast, node->ret_statement.expr, stack, 1); + break; + + case SPL_AST_DEFER_STATEMENT: + dump_vec(ast, node->defer_statement.block_or_statement, stack); + break; + + case SPL_AST_PACKED_EXPR: + if (node->packed_expr.expr) + dump_node(ast, node->packed_expr.expr, stack, 1); + break; + + case SPL_AST_ASSIGN_EXPR: + case SPL_AST_ASSIGN_ADD_EXPR: + case SPL_AST_ASSIGN_SUB_EXPR: + case SPL_AST_ASSIGN_MUL_EXPR: + case SPL_AST_ASSIGN_DIV_EXPR: + case SPL_AST_ASSIGN_MOD_EXPR: + case SPL_AST_ASSIGN_AND_EXPR: + case SPL_AST_ASSIGN_OR_EXPR: + case SPL_AST_ASSIGN_XOR_EXPR: + case SPL_AST_ASSIGN_LSHIFT_EXPR: + case SPL_AST_ASSIGN_USHIFT_EXPR: + case SPL_AST_BOOL_OR_EXPR: + case SPL_AST_BOOL_AND_EXPR: + case SPL_AST_BIT_OR_EXPR: + case SPL_AST_BIT_XOR_EXPR: + case SPL_AST_BIT_AND_EXPR: + case SPL_AST_CMP_EQ_EXPR: + case SPL_AST_CMP_NE_EXPR: + case SPL_AST_CMP_LE_EXPR: + case SPL_AST_CMP_GE_EXPR: + case SPL_AST_CMP_LT_EXPR: + case SPL_AST_CMP_GT_EXPR: + case SPL_AST_RANGE_EXPR: + case SPL_AST_LSHIFT_EXPR: + case SPL_AST_RSHIFT_EXPR: + case SPL_AST_ADD_EXPR: + case SPL_AST_SUB_EXPR: + case SPL_AST_MUL_EXPR: + case SPL_AST_DIV_EXPR: + case SPL_AST_MOD_EXPR: + if (node->op_expr.left) + dump_node(ast, node->op_expr.left, stack, 0); + if (node->op_expr.right) + dump_node(ast, node->op_expr.right, stack, 1); + break; + + case SPL_AST_MINUS_EXPR: + case SPL_AST_NOT_EXPR: + case SPL_AST_BIT_NOT_EXPR: + case SPL_AST_ADDRESS_EXPR: + if (node->prefix_expr.postfix_expr) + dump_node(ast, node->prefix_expr.postfix_expr, stack, 1); + break; + + case SPL_AST_CALL_EXPR: + if (node->postfix_expr.primary_expr) + dump_node(ast, node->postfix_expr.primary_expr, stack, 0); + dump_vec(ast, node->postfix_expr.call_expr, stack); + break; + + case SPL_AST_FIELD_EXPR: + case SPL_AST_DEREF_EXPR: + if (node->postfix_expr.primary_expr) + dump_node(ast, node->postfix_expr.primary_expr, stack, 1); + break; + + case SPL_AST_INDEX_EXPR: + if (node->postfix_expr.primary_expr) + dump_node(ast, node->postfix_expr.primary_expr, stack, 0); + if (node->postfix_expr.index_expr) + dump_node(ast, node->postfix_expr.index_expr, stack, 1); + break; + + case SPL_AST_SLICE_EXPR: + if (node->postfix_expr.primary_expr) + dump_node(ast, node->postfix_expr.primary_expr, stack, 0); + if (node->postfix_expr.slice_expr.begin) + dump_node(ast, node->postfix_expr.slice_expr.begin, stack, 0); + if (node->postfix_expr.slice_expr.end) + dump_node(ast, node->postfix_expr.slice_expr.end, stack, 1); + break; + + case SPL_AST_AS_EXPR: + if (node->postfix_expr.primary_expr) + dump_node(ast, node->postfix_expr.primary_expr, stack, 0); + if (node->postfix_expr.type_expr) + dump_node(ast, node->postfix_expr.type_expr, stack, 1); + break; + + case SPL_AST_EXPR_INTEGER_LIT: + case SPL_AST_EXPR_FLOAT_LIT: + case SPL_AST_EXPR_CHAR_LIT: + case SPL_AST_EXPR_STRING_LIT: + case SPL_AST_EXPR_TRUE: + case SPL_AST_EXPR_FALSE: + case SPL_AST_EXPR_NULL: + case SPL_AST_EXPR_UNDEFINED: + case SPL_AST_EXPR_IDENT: + break; + + case SPL_AST_ARGGREGATE_INIT: + dump_vec(ast, node->primary_expr.aggregate_init.expr, stack); + break; + + case SPL_AST_EXPR_EXPR: + if (node->primary_expr.expr) + dump_node(ast, node->primary_expr.expr, stack, 1); + break; + + case SPL_AST_ARRAY_LIT: + if (node->primary_expr.array_lit_expr.type_expr) + dump_node(ast, node->primary_expr.array_lit_expr.type_expr, stack, 0); + dump_vec(ast, node->primary_expr.array_lit_expr.expr_list, stack); + break; + + case SPL_AST_BUILTIN_EXPR: + dump_vec(ast, node->primary_expr.builtin_expr.expr_list, stack); + break; + + case SPL_AST_BLOCK_EXPR: + dump_vec(ast, node->primary_expr.block_expr, stack); + break; -/* 完整类型文本(含前缀指针/数组):*u8 / []u8 / [4]i32 / fn(a: i32) void */ -static void type_inline(spl_ast_t *ast, spl_ast_node_ref_t ref, char *out, size_t cap) { - if (!ref || ref >= ast->buckets.size) { - strncat(out, "?", cap - strlen(out) - 1); - return; - } - spl_ast_node_t *n = &ast->buckets.data[ref]; - for (usize i = 0; i < n->type_expr.type_prefixs.size; i++) { - spl_ast_node_t *pt = &ast->buckets.data[n->type_expr.type_prefixs.data[i]]; - char t[32]; - if (pt->prefix_type.pointer == 1) - snprintf(t, sizeof t, "*"); - else if (pt->prefix_type.array_size != 0) - snprintf(t, sizeof t, "[%d]", pt->prefix_type.array_size); - else - snprintf(t, sizeof t, "[]"); - strncat(out, t, cap - strlen(out) - 1); - } - if (n->type_expr.attr_list.size) - attrs_inline(ast, &n->type_expr.attr_list, out, cap); - char t[256]; - switch (n->type_expr.kind) { case SPL_AST_BASE_TYPE_FN: - snprintf(t, sizeof t, "fn("); - strncat(out, t, cap - strlen(out) - 1); - params_inline(ast, &n->type_expr.fn_type.param_list, out, cap); - strncat(out, ") ", cap - strlen(out) - 1); - type_inline(ast, n->type_expr.fn_type.type_expr, out, cap); + dump_vec(ast, node->type_expr.attr_list, stack); + dump_vec(ast, node->type_expr.fn_type.param_list, stack); + if (node->type_expr.fn_type.type_expr) + dump_node(ast, node->type_expr.fn_type.type_expr, stack, 1); break; + + case SPL_AST_BASE_TYPE_PATH: + dump_vec(ast, node->type_expr.attr_list, stack); + break; + + case SPL_AST_TYPE_POINTER: + dump_vec(ast, node->type_expr.attr_list, stack); + if (node->type_expr.pointer_type.pointee) + dump_node(ast, node->type_expr.pointer_type.pointee, stack, 1); + break; + + case SPL_AST_TYPE_SLICE: + dump_vec(ast, node->type_expr.attr_list, stack); + if (node->type_expr.slice_type.element) + dump_node(ast, node->type_expr.slice_type.element, stack, 1); + break; + + case SPL_AST_TYPE_ARRAY: + dump_vec(ast, node->type_expr.attr_list, stack); + if (node->type_expr.array_type.element) + dump_node(ast, node->type_expr.array_type.element, stack, 0); + if (node->type_expr.array_type.size) + dump_node(ast, node->type_expr.array_type.size, stack, 1); + break; + case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: - case SPL_AST_TYPE_ENUM: { - const char *kw = n->type_expr.kind == SPL_AST_TYPE_STRUCT ? "struct" - : n->type_expr.kind == SPL_AST_TYPE_UNION ? "union" - : "enum"; - snprintf(t, sizeof t, "%s{ ", kw); - strncat(out, t, cap - strlen(out) - 1); - for (usize i = 0; i < n->type_expr.aggregate_list.size; i++) { - spl_ast_node_t *m = &ast->buckets.data[n->type_expr.aggregate_list.data[i]]; - if (m->kind == SPL_AST_MEMBER_DECL) { - snprintf(t, sizeof t, "%s: ", STR(m->member_decl.name)); - strncat(out, t, cap - strlen(out) - 1); - if (m->member_decl.type_expr) - type_inline(ast, m->member_decl.type_expr, out, cap); - else - strncat(out, "?", cap - strlen(out) - 1); - } else if (m->kind == SPL_AST_FN_DECL || m->kind == SPL_AST_FN_DEFINE) { - snprintf(t, sizeof t, "fn %s(", STR(m->fn_decl.name)); - strncat(out, t, cap - strlen(out) - 1); - params_inline(ast, &m->fn_decl.param_list, out, cap); - strncat(out, ") ", cap - strlen(out) - 1); - if (m->fn_decl.type_expr) - type_inline(ast, m->fn_decl.type_expr, out, cap); - } else { - strncat(out, "...", cap - strlen(out) - 1); - } - strncat(out, ", ", cap - strlen(out) - 1); - } - strncat(out, "}", cap - strlen(out) - 1); - break; - } - default: { - for (usize i = 0; i < n->type_expr.type_path.size; i++) { - spl_ast_node_t *at = &ast->buckets.data[n->type_expr.type_path.data[i]]; - if (i) - strncat(out, ".", cap - strlen(out) - 1); - if (at->type_atom.kind == SPL_AST_TYPE_IDENT) - strncat(out, STR(at->type_atom.ident), cap - strlen(out) - 1); - else - strncat(out, type_atom_name(at->type_atom.kind), cap - strlen(out) - 1); - } - if (!n->type_expr.type_path.size) - strncat(out, "?", cap - strlen(out) - 1); - break; - } - } -} - -/* 聚合初始化项文本已由 agg_items_inline 提供 */ - -/* ---- 树版表达式渲染 ---- */ - -/* 解包 BLOCK_EXPR 包装,返回 block_item 列表(match 臂体) */ -static spl_ast_node_ref_vec_t *unwrap_block_expr(spl_ast_t *ast, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = &ast->buckets.data[ref]; - spl_ast_node_t *p = &ast->buckets.data[n->expr.op_expr.left]; - return &p->primary_expr.block_expr; -} - -/* 单行 packed_expr 模式文本(非表达式模式) */ -static void pattern_inline(spl_ast_t *ast, spl_ast_node_ref_t ref, char *out, size_t cap) { - out[0] = '\0'; - if (!ref || ref >= ast->buckets.size) - return; - spl_ast_node_t *n = &ast->buckets.data[ref]; - if (n->packed_expr.expr) { - expr_inline(ast, n->packed_expr.expr, out, cap); - } else if (n->packed_expr.ident) { - char t[128]; - if (n->packed_expr.bind_ident) - snprintf(t, sizeof t, ".%s[%s]", STR(n->packed_expr.ident), - STR(n->packed_expr.bind_ident)); - else - snprintf(t, sizeof t, ".%s", STR(n->packed_expr.ident)); - strncat(out, t, cap - strlen(out) - 1); - } else { - strncat(out, "_", cap - strlen(out) - 1); - } -} - -/* packed_expr 作为一行节点 */ -static void dump_packed(spl_ast_t *ast, spl_ast_node_ref_t ref, const char *prefix, int is_last) { - spl_ast_node_t *n = &ast->buckets.data[ref]; - if (n->packed_expr.expr) { - dump_expr(ast, n->packed_expr.expr, prefix, is_last); - return; - } - char t[128]; - pattern_inline(ast, ref, t, sizeof t); - node_label(prefix, is_last, "%s", t); -} - -/* match 臂:模式 + 体(BLOCK_EXPR) */ -static void dump_arm(spl_ast_t *ast, spl_ast_node_ref_t pat, spl_ast_node_ref_t body, - const char *prefix, int is_last) { - spl_ast_node_t *n = &ast->buckets.data[pat]; - char cp[512]; - if (n->packed_expr.expr) { - node_label(prefix, is_last, "Arm"); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_expr(ast, n->packed_expr.expr, cp, 0); - dump_block(ast, unwrap_block_expr(ast, body), cp, 1); - return; - } - char t[128]; - pattern_inline(ast, pat, t, sizeof t); - node_label(prefix, is_last, "Arm %s", t); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_block(ast, unwrap_block_expr(ast, body), cp, 1); -} - -/* primary_expr 树版:label + 子节点 */ -static void dump_primary_expr(spl_ast_t *ast, spl_ast_node_ref_t ref, const char *prefix, - int is_last) { - spl_ast_node_t *n = &ast->buckets.data[ref]; - char cp[512]; - switch (n->primary_expr.kind) { - case SPL_AST_INTEGER: - node_label(prefix, is_last, "Integer %lld", (long long)n->primary_expr.integer_expr); - break; - case SPL_AST_FLOAT: - node_label(prefix, is_last, "Float %g", n->primary_expr.float_expr); - break; - case SPL_AST_CHAR_LIT: - node_label(prefix, is_last, "Char '%c'", (int)n->primary_expr.char_lit_expr); - break; - case SPL_AST_STRING_LIT: { - char t[512]; - t[0] = '\0'; - escape_string(t, sizeof t, STR(n->primary_expr.string_lit_expr)); - node_label(prefix, is_last, "String %s", t); - break; - } - case SPL_AST_TRUE: - node_label(prefix, is_last, "Bool true"); - break; - case SPL_AST_FALSE: - node_label(prefix, is_last, "Bool false"); - break; - case SPL_AST_NULL: - node_label(prefix, is_last, "Null"); - break; - case SPL_AST_IDENT: - node_label(prefix, is_last, "Ident %s", STR(n->primary_expr.ident)); - break; - case SPL_AST_ARGGREGATE_INIT: - node_label(prefix, is_last, "AggInit %s", STR(n->primary_expr.aggregate_init.name)); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - for (usize i = 0; i < n->primary_expr.aggregate_init.expr.size; i++) { - spl_ast_node_t *it = &ast->buckets.data[n->primary_expr.aggregate_init.expr.data[i]]; - int it_last = (int)(i == n->primary_expr.aggregate_init.expr.size - 1); - node_label(cp, it_last, "Field .%s", STR(it->aggregate_init_item.ident)); - if (it->aggregate_init_item.expr) { - char cq[512]; - spl_dumptree_child_prefix(dt, cp, it_last, cq, sizeof cq); - dump_expr(ast, it->aggregate_init_item.expr, cq, 1); - } - } - break; - case SPL_AST_EXPR_EXPR: - dump_expr(ast, n->primary_expr.expr, prefix, is_last); - break; - case SPL_AST_ARRAY_LIT: - node_label(prefix, is_last, "Array [%lld]", - (long long)n->primary_expr.array_lit_expr.integer); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - if (n->primary_expr.array_lit_expr.type_expr) - dump_type_expr(ast, n->primary_expr.array_lit_expr.type_expr, cp, - (int)(n->primary_expr.array_lit_expr.expr_list.size == 0)); - for (usize i = 0; i < n->primary_expr.array_lit_expr.expr_list.size; i++) - dump_expr(ast, n->primary_expr.array_lit_expr.expr_list.data[i], cp, - (int)(i == n->primary_expr.array_lit_expr.expr_list.size - 1)); - break; - case SPL_AST_BUILTIN_EXPR: - node_label(prefix, is_last, "Builtin @%s", STR(n->primary_expr.builtin_expr.ident)); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - for (usize i = 0; i < n->primary_expr.builtin_expr.expr_list.size; i++) - dump_expr(ast, n->primary_expr.builtin_expr.expr_list.data[i], cp, - (int)(i == n->primary_expr.builtin_expr.expr_list.size - 1)); - break; - case SPL_AST_BLOCK_EXPR: - node_label(prefix, is_last, "BlockExpr"); - dump_vec_children(ast, &n->primary_expr.block_expr, CTX_BLOCK_ITEM, prefix, is_last); - break; - default: - node_label(prefix, is_last, "?"); - break; - } -} - -/* postfix_expr 树版:label + 子节点 */ -static void dump_postfix_expr(spl_ast_t *ast, spl_ast_node_ref_t ref, const char *prefix, - int is_last) { - spl_ast_node_t *n = &ast->buckets.data[ref]; - spl_ast_node_ref_t tgt = n->postfix_expr.primary_expr; - char cp[512]; - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - switch (n->postfix_expr.kind) { - case SPL_AST_CALL_EXPR: { - usize nkids = 1 + n->postfix_expr.call_expr.size; - node_label(prefix, is_last, "Call"); - dump_expr(ast, tgt, cp, (int)(nkids == 1)); - for (usize i = 0; i < n->postfix_expr.call_expr.size; i++) - dump_expr(ast, n->postfix_expr.call_expr.data[i], cp, - (int)(i == n->postfix_expr.call_expr.size - 1)); - break; - } - case SPL_AST_FIELD_EXPR: - node_label(prefix, is_last, "Field .%s", STR(n->postfix_expr.field_expr)); - dump_expr(ast, tgt, cp, 1); - break; - case SPL_AST_DEREF_EXPR: - node_label(prefix, is_last, "Deref"); - dump_expr(ast, tgt, cp, 1); - break; - case SPL_AST_INDEX_EXPR: - node_label(prefix, is_last, "Index"); - dump_expr(ast, tgt, cp, 0); - dump_expr(ast, n->postfix_expr.index_expr, cp, 1); - break; - case SPL_AST_SLICE_EXPR: - node_label(prefix, is_last, "Slice"); - dump_expr(ast, tgt, cp, 0); - if (n->postfix_expr.slice_expr.begin) - dump_expr(ast, n->postfix_expr.slice_expr.begin, cp, 0); - if (n->postfix_expr.slice_expr.end) - dump_expr(ast, n->postfix_expr.slice_expr.end, cp, 1); - break; - case SPL_AST_AS_EXPR: { - char t[256]; - t[0] = '\0'; - if (n->postfix_expr.type_expr) - type_inline(ast, n->postfix_expr.type_expr, t, sizeof t); - node_label(prefix, is_last, "As %s", t); - dump_expr(ast, tgt, cp, 1); - break; - } - default: - node_label(prefix, is_last, "?"); - break; - } -} - -/* primary_expr 树版见 dump_primary_expr */ - -/* 表达式树版:EXPR 包装层折叠,直接显示具体节点类型 */ -static void dump_expr(spl_ast_t *ast, spl_ast_node_ref_t ref, const char *prefix, int is_last) { - if (!ref || ref >= ast->buckets.size) { - node_label(prefix, is_last, "?"); - return; - } - spl_ast_node_t *n = &ast->buckets.data[ref]; - char cp[512]; - int op = n->expr.op; - switch (op) { - case SPL_AST_PRIMARY_EXPR: - dump_primary_expr(ast, n->expr.op_expr.left, prefix, is_last); - break; - case SPL_AST_PREFIX_EXPR: { - spl_ast_node_t *pn = &ast->buckets.data[n->expr.op_expr.left]; - const char *nm = "?"; - switch (pn->prefix_expr.kind) { - case SPL_AST_MINUS_EXPR: - nm = "Neg"; - break; - case SPL_AST_BANG_EXPR: - nm = "Not"; - break; - case SPL_AST_TILDE_EXPR: - nm = "BitNot"; - break; - case SPL_AST_AMPERSAND_EXPR: - nm = "Addr"; - break; - case SPL_AST_ASTERISK_EXPR: - nm = "Star"; - break; - } - node_label(prefix, is_last, "%s", nm); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_expr(ast, pn->prefix_expr.postfix_expr, cp, 1); - break; - } - case SPL_AST_POSTFIX_EXPR: - dump_postfix_expr(ast, n->expr.op_expr.left, prefix, is_last); - break; - default: - node_label(prefix, is_last, "%s", expr_op_name(op)); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_expr(ast, n->expr.op_expr.left, cp, 0); - if (n->expr.op_expr.right) - dump_expr(ast, n->expr.op_expr.right, cp, 1); - break; - } -} - -/* 代码块树版 */ -static void dump_block(spl_ast_t *ast, spl_ast_node_ref_vec_t *block, const char *prefix, - int is_last) { - node_label(prefix, is_last, "Block"); - dump_vec_children(ast, block, CTX_BLOCK_ITEM, prefix, is_last); -} - -/* 模式文本见 pattern_inline;vec 递归见 dump_vec_children */ - -/* 类型节点树版:聚合(struct/union/enum)展开为子树,其余内联为 Type 标签 */ -static void dump_type_expr(spl_ast_t *ast, spl_ast_node_ref_t ref, const char *prefix, - int is_last) { - if (!ref || ref >= ast->buckets.size) { - node_label(prefix, is_last, "?"); - return; - } - spl_ast_node_t *n = &ast->buckets.data[ref]; - int agg = n->type_expr.kind == SPL_AST_TYPE_STRUCT || n->type_expr.kind == SPL_AST_TYPE_UNION || - n->type_expr.kind == SPL_AST_TYPE_ENUM; - if (!agg && n->type_expr.kind == SPL_AST_BASE_TYPE_PATH) { - char t[512]; - t[0] = '\0'; - type_inline(ast, ref, t, sizeof t); - node_label(prefix, is_last, "Type %s", t); - return; - } - const char *nm = n->type_expr.kind == SPL_AST_TYPE_STRUCT ? "Struct" - : n->type_expr.kind == SPL_AST_TYPE_UNION ? "Union" - : n->type_expr.kind == SPL_AST_TYPE_ENUM ? "Enum" - : "FnType"; - node_label(prefix, is_last, "%s", nm); - char cp[512]; - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - if (agg) { - for (usize i = 0; i < n->type_expr.aggregate_list.size; i++) - dump_node(ast, n->type_expr.aggregate_list.data[i], CTX_DECL, cp, - (int)(i == n->type_expr.aggregate_list.size - 1)); - } else { - usize np = n->type_expr.fn_type.param_list.size; - int has_ret = n->type_expr.fn_type.type_expr != 0; - for (usize i = 0; i < np; i++) - dump_node(ast, n->type_expr.fn_type.param_list.data[i], CTX_PARAM, cp, - (int)(i == np - 1 && !has_ret)); - if (has_ret) - dump_type_expr(ast, n->type_expr.fn_type.type_expr, cp, 1); - } -} - -static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx, const char *prefix, - int is_last) { - if (!ref || ref >= ast->buckets.size) - return; - spl_ast_node_t *n = &ast->buckets.data[ref]; - char cp[512]; - switch (ctx) { - case CTX_CONTAINER: - printf("Program\n"); - dump_vec_children(ast, &n->container_item.members, CTX_DECL, "", 1); - break; - case CTX_DECL: - switch (n->kind) { - case SPL_AST_FN_DECL: - case SPL_AST_FN_DEFINE: { - int is_define = (n->kind == SPL_AST_FN_DEFINE); - node_label(prefix, is_last, "%s %s", is_define ? "FnDefine" : "FnDecl", - STR(n->fn_decl.name)); - usize total = n->fn_decl.attr_list.size + n->fn_decl.param_list.size + - (n->fn_decl.type_expr ? 1 : 0) + - (is_define && n->fn_decl.block.size ? 1 : 0); - if (total) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - for (usize i = 0; i < n->fn_decl.attr_list.size; i++) - dump_node(ast, n->fn_decl.attr_list.data[i], CTX_ATTR_ITEM, cp, - (int)(++k == total)); - for (usize i = 0; i < n->fn_decl.param_list.size; i++) - dump_node(ast, n->fn_decl.param_list.data[i], CTX_PARAM, cp, - (int)(++k == total)); - if (n->fn_decl.type_expr) - dump_type_expr(ast, n->fn_decl.type_expr, cp, (int)(++k == total)); - if (is_define && n->fn_decl.block.size) - dump_block(ast, &n->fn_decl.block, cp, (int)(++k == total)); - } - break; - } - case SPL_AST_TYPE_DECL: - node_label(prefix, is_last, "TypeDecl %s", STR(n->type_decl.name)); - if (n->type_decl.type_expr) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_type_expr(ast, n->type_decl.type_expr, cp, 1); - } - break; - case SPL_AST_VAR_DECL: { - node_label(prefix, is_last, "VarDecl %s", STR(n->var_decl.name)); - usize total = n->var_decl.attr_list.size + (n->var_decl.type_expr ? 1 : 0) + - (n->var_decl.expr ? 1 : 0); - if (total) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - for (usize i = 0; i < n->var_decl.attr_list.size; i++) - dump_node(ast, n->var_decl.attr_list.data[i], CTX_ATTR_ITEM, cp, - (int)(++k == total)); - if (n->var_decl.type_expr) - dump_type_expr(ast, n->var_decl.type_expr, cp, (int)(++k == total)); - if (n->var_decl.expr) - dump_expr(ast, n->var_decl.expr, cp, (int)(++k == total)); - } - break; - } - case SPL_AST_CONST_DECL: { - node_label(prefix, is_last, "ConstDecl %s", STR(n->const_decl.name)); - usize total = n->const_decl.attr_list.size + (n->const_decl.type_expr ? 1 : 0) + - (n->const_decl.expr ? 1 : 0); - if (total) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - for (usize i = 0; i < n->const_decl.attr_list.size; i++) - dump_node(ast, n->const_decl.attr_list.data[i], CTX_ATTR_ITEM, cp, - (int)(++k == total)); - if (n->const_decl.type_expr) - dump_type_expr(ast, n->const_decl.type_expr, cp, (int)(++k == total)); - if (n->const_decl.expr) - dump_expr(ast, n->const_decl.expr, cp, (int)(++k == total)); - } - break; - } - case SPL_AST_MEMBER_DECL: { - node_label(prefix, is_last, "Member %s", STR(n->member_decl.name)); - usize total = n->member_decl.attr_list.size + (n->member_decl.type_expr ? 1 : 0); - if (total) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - for (usize i = 0; i < n->member_decl.attr_list.size; i++) - dump_node(ast, n->member_decl.attr_list.data[i], CTX_ATTR_ITEM, cp, - (int)(++k == total)); - if (n->member_decl.type_expr) - dump_type_expr(ast, n->member_decl.type_expr, cp, (int)(++k == total)); - } - break; - } - default: - node_label(prefix, is_last, "Decl ?"); - break; - } - break; - case CTX_ATTR_ITEM: - node_label(prefix, is_last, "Attr @%s", STR(n->attr_item.ident)); - if (n->attr_item.expr_list.size) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - for (usize i = 0; i < n->attr_item.expr_list.size; i++) - dump_expr(ast, n->attr_item.expr_list.data[i], cp, - (int)(i == n->attr_item.expr_list.size - 1)); - } - break; - case CTX_PARAM: - if (n->param_decl.name) { - node_label(prefix, is_last, "Param %s", STR(n->param_decl.name)); - if (n->param_decl.attr_list.size || n->param_decl.type_expr) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize total = n->param_decl.attr_list.size + (n->param_decl.type_expr ? 1 : 0); - usize k = 0; - for (usize i = 0; i < n->param_decl.attr_list.size; i++) - dump_node(ast, n->param_decl.attr_list.data[i], CTX_ATTR_ITEM, cp, - (int)(++k == total)); - if (n->param_decl.type_expr) - dump_type_expr(ast, n->param_decl.type_expr, cp, (int)(++k == total)); - } - } else { - node_label(prefix, is_last, "Param ..."); - } - break; - case CTX_BLOCK_ITEM: - if (n->kind == SPL_AST_EXPR) { - dump_expr(ast, ref, prefix, is_last); - break; - } - switch (n->block_item.kind) { - case SPL_AST_IF_STATEMENT: { - node_label(prefix, is_last, "If"); - usize nkids = 1 + (n->block_item.if_statement.if_block.size ? 1 : 0) + - (n->block_item.if_statement.else_block.size ? 1 : 0); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - dump_expr(ast, n->block_item.if_statement.expr, cp, (int)(++k == nkids)); - if (n->block_item.if_statement.if_block.size) - dump_block(ast, &n->block_item.if_statement.if_block, cp, (int)(++k == nkids)); - if (n->block_item.if_statement.else_block.size) - dump_block(ast, &n->block_item.if_statement.else_block, cp, (int)(++k == nkids)); - break; - } - case SPL_AST_IFVAR_STATEMENT: { - node_label(prefix, is_last, "IfVar"); - usize nkids = 1 + (n->block_item.ifvar_statement.if_block.size ? 1 : 0) + - (n->block_item.ifvar_statement.else_block.size ? 1 : 0); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - dump_packed(ast, n->block_item.ifvar_statement.packed_expr, cp, (int)(++k == nkids)); - if (n->block_item.ifvar_statement.if_block.size) - dump_block(ast, &n->block_item.ifvar_statement.if_block, cp, (int)(++k == nkids)); - if (n->block_item.ifvar_statement.else_block.size) - dump_block(ast, &n->block_item.ifvar_statement.else_block, cp, (int)(++k == nkids)); - break; - } - case SPL_AST_WHILE_STATEMENT: { - node_label(prefix, is_last, "While"); - usize nkids = 1 + (n->block_item.while_statement.while_block.size ? 1 : 0); - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - dump_expr(ast, n->block_item.while_statement.expr, cp, (int)(++k == nkids)); - if (n->block_item.while_statement.while_block.size) - dump_block(ast, &n->block_item.while_statement.while_block, cp, - (int)(++k == nkids)); - break; - } - case SPL_AST_LOOP_STATEMENT: - node_label(prefix, is_last, "Loop"); - if (n->block_item.loop_statement.loop_block.size) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_block(ast, &n->block_item.loop_statement.loop_block, cp, 1); - } - break; - case SPL_AST_FOR_STATEMENT: { - node_label(prefix, is_last, "For"); - usize nkids = n->block_item.for_statement.expr_vec.size + - n->block_item.for_statement.ident_vec.size + - (n->block_item.for_statement.block.size ? 1 : 0); - if (nkids) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - for (usize i = 0; i < n->block_item.for_statement.expr_vec.size; i++) - dump_expr(ast, n->block_item.for_statement.expr_vec.data[i], cp, - (int)(++k == nkids)); - for (usize i = 0; i < n->block_item.for_statement.ident_vec.size; i++) { - const char *bi = STR(n->block_item.for_statement.ident_vec.data[i]); - node_label(cp, (int)(++k == nkids), "Bind %s", bi); - } - if (n->block_item.for_statement.block.size) - dump_block(ast, &n->block_item.for_statement.block, cp, (int)(++k == nkids)); - } - break; - } - case SPL_AST_MATCH_STATEMENT: { - node_label(prefix, is_last, "Match"); - spl_ast_node_ref_vec_t *pp = &n->block_item.match_statement.paced_exprs; - spl_ast_node_ref_vec_t *mb = &n->block_item.match_statement.match_block; - usize nkids = 1 + pp->size; - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - usize k = 0; - dump_expr(ast, n->block_item.match_statement.expr, cp, (int)(++k == nkids)); - for (usize i = 0; i < pp->size && i < mb->size; i++) - dump_arm(ast, pp->data[i], mb->data[i], cp, (int)(++k == nkids)); - break; - } - case SPL_AST_RET_STATEMENT: - node_label(prefix, is_last, "Ret"); - if (n->block_item.ret_statement.expr) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_expr(ast, n->block_item.ret_statement.expr, cp, 1); - } - break; - case SPL_AST_BREAK_STATEMENT: - node_label(prefix, is_last, "Break"); - break; - case SPL_AST_CONTINUE_STATEMENT: - node_label(prefix, is_last, "Continue"); - break; - case SPL_AST_DEFER_STATEMENT: - node_label(prefix, is_last, "Defer"); - if (n->block_item.defer_statement.block_or_statement.size) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_vec_children(ast, &n->block_item.defer_statement.block_or_statement, - CTX_BLOCK_ITEM, cp, 1); - } - break; - case SPL_AST_VARDECL: - dump_node(ast, n->block_item.var_decl, CTX_DECL, prefix, is_last); - break; - case SPL_AST_CONSTDECL: - dump_node(ast, n->block_item.const_decl, CTX_DECL, prefix, is_last); - break; - case SPL_AST_TYPEDECL: - dump_node(ast, n->block_item.type_decl, CTX_DECL, prefix, is_last); - break; - case SPL_AST_EXPR_STATEMENT: - node_label(prefix, is_last, "ExprStmt"); - if (n->block_item.expr_statement) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_expr(ast, n->block_item.expr_statement, cp, 1); - } - break; - default: - node_label(prefix, is_last, "BlockItem ?"); - break; - } - break; - case CTX_EXPR: - dump_expr(ast, ref, prefix, is_last); - break; - case CTX_PREFIX: - case CTX_POSTFIX: - case CTX_PRIMARY: - node_label(prefix, is_last, "?"); - break; - case CTX_PACKED: - dump_packed(ast, ref, prefix, is_last); - break; - case CTX_AGG_ITEM: - node_label(prefix, is_last, "Field .%s", STR(n->aggregate_init_item.ident)); - if (n->aggregate_init_item.expr) { - spl_dumptree_child_prefix(dt, prefix, is_last, cp, sizeof cp); - dump_expr(ast, n->aggregate_init_item.expr, cp, 1); - } - break; - case CTX_TYPE_EXPR: - dump_type_expr(ast, ref, prefix, is_last); - break; - case CTX_TYPE_ATOM: { - char t[128]; - t[0] = '\0'; - if (n->type_atom.kind == SPL_AST_TYPE_IDENT) - strncat(t, STR(n->type_atom.ident), sizeof t - strlen(t) - 1); - else - strncat(t, type_atom_name(n->type_atom.kind), sizeof t - strlen(t) - 1); - node_label(prefix, is_last, "%s", t); - break; - } - case CTX_PREFIX_TYPE: - if (n->prefix_type.pointer == 1) - node_label(prefix, is_last, "*"); - else if (n->prefix_type.array_size != 0) - node_label(prefix, is_last, "[%d]", n->prefix_type.array_size); - else - node_label(prefix, is_last, "[]"); - break; - default: - node_label(prefix, is_last, "?"); - break; - } -} - -static void drop_vec(spl_ast_t *ast, spl_ast_node_ref_vec_t *vec, walk_ctx_t ctx) { - for (usize i = 0; i < vec->size; i++) { - drop_node(ast, vec->data[i], ctx); - } - vec_free(*vec); -} - -static void drop_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx) { - if (!ref || ref >= ast->buckets.size) - return; - spl_ast_node_t *n = &ast->buckets.data[ref]; - switch (ctx) { - case CTX_CONTAINER: - drop_vec(ast, &n->container_item.members, CTX_DECL); - break; - case CTX_DECL: - switch (n->kind) { - case SPL_AST_FN_DECL: - case SPL_AST_FN_DEFINE: - free((void *)n->fn_decl.name); - drop_vec(ast, &n->fn_decl.attr_list, CTX_ATTR_ITEM); - drop_vec(ast, &n->fn_decl.param_list, CTX_PARAM); - drop_node(ast, n->fn_decl.type_expr, CTX_TYPE_EXPR); - drop_vec(ast, &n->fn_decl.block, CTX_BLOCK_ITEM); - break; - case SPL_AST_TYPE_DECL: - free((void *)n->type_decl.name); - drop_node(ast, n->type_decl.type_expr, CTX_TYPE_EXPR); - break; - case SPL_AST_VAR_DECL: - free((void *)n->var_decl.name); - drop_vec(ast, &n->var_decl.attr_list, CTX_ATTR_ITEM); - drop_node(ast, n->var_decl.type_expr, CTX_TYPE_EXPR); - drop_node(ast, n->var_decl.expr, CTX_EXPR); - break; - case SPL_AST_CONST_DECL: - free((void *)n->const_decl.name); - drop_vec(ast, &n->const_decl.attr_list, CTX_ATTR_ITEM); - drop_node(ast, n->const_decl.type_expr, CTX_TYPE_EXPR); - drop_node(ast, n->const_decl.expr, CTX_EXPR); - break; - case SPL_AST_MEMBER_DECL: - free((void *)n->member_decl.name); - drop_vec(ast, &n->member_decl.attr_list, CTX_ATTR_ITEM); - drop_node(ast, n->member_decl.type_expr, CTX_TYPE_EXPR); - break; - default: - break; - } - break; - case CTX_ATTR_ITEM: - free((void *)n->attr_item.ident); - drop_vec(ast, &n->attr_item.expr_list, CTX_EXPR); - break; - case CTX_PARAM: - free((void *)n->param_decl.name); - drop_vec(ast, &n->param_decl.attr_list, CTX_ATTR_ITEM); - drop_node(ast, n->param_decl.type_expr, CTX_TYPE_EXPR); - break; - case CTX_BLOCK_ITEM: - if (n->kind == SPL_AST_EXPR) { - drop_node(ast, ref, CTX_EXPR); - break; - } - switch (n->block_item.kind) { - case SPL_AST_IF_STATEMENT: - drop_node(ast, n->block_item.if_statement.expr, CTX_EXPR); - drop_vec(ast, &n->block_item.if_statement.if_block, CTX_BLOCK_ITEM); - drop_vec(ast, &n->block_item.if_statement.else_block, CTX_BLOCK_ITEM); - break; - case SPL_AST_IFVAR_STATEMENT: - drop_node(ast, n->block_item.ifvar_statement.packed_expr, CTX_PACKED); - drop_vec(ast, &n->block_item.ifvar_statement.if_block, CTX_BLOCK_ITEM); - drop_vec(ast, &n->block_item.ifvar_statement.else_block, CTX_BLOCK_ITEM); - break; - case SPL_AST_WHILE_STATEMENT: - drop_node(ast, n->block_item.while_statement.expr, CTX_EXPR); - drop_vec(ast, &n->block_item.while_statement.while_block, CTX_BLOCK_ITEM); - break; - case SPL_AST_LOOP_STATEMENT: - drop_vec(ast, &n->block_item.loop_statement.loop_block, CTX_BLOCK_ITEM); - break; - case SPL_AST_FOR_STATEMENT: - drop_vec(ast, &n->block_item.for_statement.expr_vec, CTX_EXPR); - for (usize fi = 0; fi < n->block_item.for_statement.ident_vec.size; fi++) - free(n->block_item.for_statement.ident_vec.data[fi]); - vec_free(n->block_item.for_statement.ident_vec); - drop_vec(ast, &n->block_item.for_statement.block, CTX_BLOCK_ITEM); - break; - case SPL_AST_MATCH_STATEMENT: - drop_node(ast, n->block_item.match_statement.expr, CTX_EXPR); - drop_vec(ast, &n->block_item.match_statement.paced_exprs, CTX_PACKED); - { - /* match_block 含共享 body 引用(模式合并),去重后 drop 防重复释放 */ - spl_ast_node_ref_vec_t dedup; - vec_init(dedup); - for (usize di = 0; di < n->block_item.match_statement.match_block.size; di++) { - spl_ast_node_ref_t r = n->block_item.match_statement.match_block.data[di]; - int found = 0; - for (usize dj = 0; dj < dedup.size; dj++) { - if (dedup.data[dj] == r) { - found = 1; - break; - } - } - if (!found) - vec_push(dedup, r); - } - drop_vec(ast, &dedup, CTX_BLOCK_ITEM); - } - vec_free(n->block_item.match_statement.match_block); - break; - case SPL_AST_RET_STATEMENT: - drop_node(ast, n->block_item.ret_statement.expr, CTX_EXPR); - break; - case SPL_AST_DEFER_STATEMENT: - drop_vec(ast, &n->block_item.defer_statement.block_or_statement, CTX_BLOCK_ITEM); - break; - case SPL_AST_VARDECL: - drop_node(ast, n->block_item.var_decl, CTX_DECL); - break; - case SPL_AST_CONSTDECL: - drop_node(ast, n->block_item.const_decl, CTX_DECL); - break; - case SPL_AST_TYPEDECL: - drop_node(ast, n->block_item.type_decl, CTX_DECL); - break; - case SPL_AST_EXPR_STATEMENT: - drop_node(ast, n->block_item.expr_statement, CTX_EXPR); - break; - default: - break; - } - break; - case CTX_EXPR: - switch (n->expr.op) { - case SPL_AST_PREFIX_EXPR: - drop_node(ast, n->expr.op_expr.left, CTX_PREFIX); - break; - case SPL_AST_POSTFIX_EXPR: - drop_node(ast, n->expr.op_expr.left, CTX_POSTFIX); - break; - case SPL_AST_PRIMARY_EXPR: - drop_node(ast, n->expr.op_expr.left, CTX_PRIMARY); - break; - default: - drop_node(ast, n->expr.op_expr.left, CTX_EXPR); - drop_node(ast, n->expr.op_expr.right, CTX_EXPR); - break; - } - break; - case CTX_PREFIX: - drop_node(ast, n->prefix_expr.postfix_expr, CTX_EXPR); - break; - case CTX_POSTFIX: - drop_node(ast, n->postfix_expr.primary_expr, CTX_PRIMARY); - if (n->postfix_expr.kind == SPL_AST_FIELD_EXPR) - free((void *)n->postfix_expr.field_expr); - switch (n->postfix_expr.kind) { - case SPL_AST_CALL_EXPR: - drop_vec(ast, &n->postfix_expr.call_expr, CTX_EXPR); - break; - case SPL_AST_INDEX_EXPR: - drop_node(ast, n->postfix_expr.index_expr, CTX_EXPR); - break; - case SPL_AST_SLICE_EXPR: - drop_node(ast, n->postfix_expr.slice_expr.begin, CTX_EXPR); - drop_node(ast, n->postfix_expr.slice_expr.end, CTX_EXPR); - break; - case SPL_AST_AS_EXPR: - drop_node(ast, n->postfix_expr.type_expr, CTX_TYPE_EXPR); - break; - default: - break; - } - break; - case CTX_PRIMARY: - switch (n->primary_expr.kind) { - case SPL_AST_STRING_LIT: - /* string_lit_expr 为解析出C 字符串副本,须释*/ - free((void *)n->primary_expr.string_lit_expr); - break; - case SPL_AST_ARGGREGATE_INIT: - free((void *)n->primary_expr.aggregate_init.name); - drop_vec(ast, &n->primary_expr.aggregate_init.expr, CTX_AGG_ITEM); - break; - case SPL_AST_EXPR_EXPR: - drop_node(ast, n->primary_expr.expr, CTX_EXPR); - break; - case SPL_AST_ARRAY_LIT: - drop_node(ast, n->primary_expr.array_lit_expr.type_expr, CTX_TYPE_EXPR); - drop_vec(ast, &n->primary_expr.array_lit_expr.expr_list, CTX_EXPR); - break; - case SPL_AST_BUILTIN_EXPR: - free((void *)n->primary_expr.builtin_expr.ident); - drop_vec(ast, &n->primary_expr.builtin_expr.expr_list, CTX_EXPR); - break; - case SPL_AST_BLOCK_EXPR: - drop_vec(ast, &n->primary_expr.block_expr, CTX_BLOCK_ITEM); - break; - case SPL_AST_IDENT: - free((void *)n->primary_expr.ident); - break; - default: - break; - } - break; - case CTX_PACKED: - free((void *)n->packed_expr.ident); - free((void *)n->packed_expr.bind_ident); - drop_node(ast, n->packed_expr.expr, CTX_EXPR); - break; - case CTX_AGG_ITEM: - free((void *)n->aggregate_init_item.ident); - drop_node(ast, n->aggregate_init_item.expr, CTX_EXPR); - break; - case CTX_TYPE_EXPR: - drop_vec(ast, &n->type_expr.type_prefixs, CTX_PREFIX_TYPE); - drop_vec(ast, &n->type_expr.attr_list, CTX_ATTR_ITEM); - if (n->type_expr.kind == SPL_AST_BASE_TYPE_FN) { - drop_vec(ast, &n->type_expr.fn_type.param_list, CTX_PARAM); - drop_node(ast, n->type_expr.fn_type.type_expr, CTX_TYPE_EXPR); - } else if (n->type_expr.kind == SPL_AST_TYPE_STRUCT || - n->type_expr.kind == SPL_AST_TYPE_UNION || - n->type_expr.kind == SPL_AST_TYPE_ENUM) { - drop_vec(ast, &n->type_expr.aggregate_list, CTX_DECL); - } else { - drop_vec(ast, &n->type_expr.type_path, CTX_TYPE_ATOM); - } - break; - case CTX_TYPE_ATOM: - free((void *)n->type_atom.ident); - break; - default: - break; - } -} - -/* ================================================================ - * valid(结构校验) - * ================================================================ */ - -static void validate_vec(spl_ast_t *ast, spl_ast_node_ref_vec_t *vec, walk_ctx_t ctx) { - for (usize i = 0; i < vec->size; i++) { - validate_node(ast, vec->data[i], ctx); - } -} - -static void validate_node(spl_ast_t *ast, spl_ast_node_ref_t ref, walk_ctx_t ctx) { - if (!ref) - return; - if (ref >= ast->buckets.size) { - printf("valid: invalid node reference %llu\n", (unsigned long long)ref); - return; - } - spl_ast_node_t *n = &ast->buckets.data[ref]; - switch (ctx) { - case CTX_CONTAINER: - validate_vec(ast, &n->container_item.members, CTX_DECL); - break; - case CTX_DECL: - switch (n->kind) { - case SPL_AST_FN_DECL: - case SPL_AST_FN_DEFINE: - if (!n->fn_decl.name) - printf("valid: function missing name\n"); - validate_vec(ast, &n->fn_decl.attr_list, CTX_ATTR_ITEM); - validate_vec(ast, &n->fn_decl.param_list, CTX_PARAM); - validate_node(ast, n->fn_decl.type_expr, CTX_TYPE_EXPR); - validate_vec(ast, &n->fn_decl.block, CTX_BLOCK_ITEM); - break; - case SPL_AST_TYPE_DECL: - if (!n->type_decl.name) - printf("valid: type declaration missing name\n"); - validate_node(ast, n->type_decl.type_expr, CTX_TYPE_EXPR); - break; - case SPL_AST_VAR_DECL: - if (!n->var_decl.name) - printf("valid: variable declaration missing name\n"); - validate_vec(ast, &n->var_decl.attr_list, CTX_ATTR_ITEM); - validate_node(ast, n->var_decl.type_expr, CTX_TYPE_EXPR); - validate_node(ast, n->var_decl.expr, CTX_EXPR); - break; - case SPL_AST_CONST_DECL: - if (!n->const_decl.name) - printf("valid: constant declaration missing name\n"); - validate_vec(ast, &n->const_decl.attr_list, CTX_ATTR_ITEM); - validate_node(ast, n->const_decl.type_expr, CTX_TYPE_EXPR); - validate_node(ast, n->const_decl.expr, CTX_EXPR); - break; - case SPL_AST_MEMBER_DECL: - if (!n->member_decl.name) - printf("valid: member declaration missing name\n"); - validate_vec(ast, &n->member_decl.attr_list, CTX_ATTR_ITEM); - validate_node(ast, n->member_decl.type_expr, CTX_TYPE_EXPR); - break; - default: - break; - } - break; - case CTX_ATTR_ITEM: - if (!n->attr_item.ident) - printf("valid: attribute missing name\n"); - validate_vec(ast, &n->attr_item.expr_list, CTX_EXPR); - break; - case CTX_PARAM: - validate_vec(ast, &n->param_decl.attr_list, CTX_ATTR_ITEM); - validate_node(ast, n->param_decl.type_expr, CTX_TYPE_EXPR); - break; - case CTX_BLOCK_ITEM: - if (n->kind == SPL_AST_EXPR) { - validate_node(ast, ref, CTX_EXPR); - break; - } - switch (n->block_item.kind) { - case SPL_AST_IF_STATEMENT: - validate_node(ast, n->block_item.if_statement.expr, CTX_EXPR); - validate_vec(ast, &n->block_item.if_statement.if_block, CTX_BLOCK_ITEM); - validate_vec(ast, &n->block_item.if_statement.else_block, CTX_BLOCK_ITEM); - break; - case SPL_AST_IFVAR_STATEMENT: - validate_node(ast, n->block_item.ifvar_statement.packed_expr, CTX_PACKED); - validate_vec(ast, &n->block_item.ifvar_statement.if_block, CTX_BLOCK_ITEM); - validate_vec(ast, &n->block_item.ifvar_statement.else_block, CTX_BLOCK_ITEM); - break; - case SPL_AST_WHILE_STATEMENT: - validate_node(ast, n->block_item.while_statement.expr, CTX_EXPR); - validate_vec(ast, &n->block_item.while_statement.while_block, CTX_BLOCK_ITEM); - break; - case SPL_AST_LOOP_STATEMENT: - validate_vec(ast, &n->block_item.loop_statement.loop_block, CTX_BLOCK_ITEM); - break; - case SPL_AST_FOR_STATEMENT: - validate_vec(ast, &n->block_item.for_statement.expr_vec, CTX_EXPR); - validate_vec(ast, &n->block_item.for_statement.block, CTX_BLOCK_ITEM); - break; - case SPL_AST_MATCH_STATEMENT: - validate_node(ast, n->block_item.match_statement.expr, CTX_EXPR); - validate_vec(ast, &n->block_item.match_statement.paced_exprs, CTX_PACKED); - validate_vec(ast, &n->block_item.match_statement.match_block, CTX_BLOCK_ITEM); - if (n->block_item.match_statement.paced_exprs.size != - n->block_item.match_statement.match_block.size) - printf("valid: match arm pattern/statement count mismatch\n"); - break; - case SPL_AST_RET_STATEMENT: - validate_node(ast, n->block_item.ret_statement.expr, CTX_EXPR); - break; - case SPL_AST_DEFER_STATEMENT: - validate_vec(ast, &n->block_item.defer_statement.block_or_statement, CTX_BLOCK_ITEM); - break; - case SPL_AST_VARDECL: - validate_node(ast, n->block_item.var_decl, CTX_DECL); - break; - case SPL_AST_CONSTDECL: - validate_node(ast, n->block_item.const_decl, CTX_DECL); - break; - case SPL_AST_TYPEDECL: - validate_node(ast, n->block_item.type_decl, CTX_DECL); - break; - case SPL_AST_EXPR_STATEMENT: - validate_node(ast, n->block_item.expr_statement, CTX_EXPR); - break; - default: - break; - } - break; - case CTX_EXPR: - switch (n->expr.op) { - case SPL_AST_PREFIX_EXPR: - validate_node(ast, n->expr.op_expr.left, CTX_PREFIX); - break; - case SPL_AST_POSTFIX_EXPR: - validate_node(ast, n->expr.op_expr.left, CTX_POSTFIX); - break; - case SPL_AST_PRIMARY_EXPR: - validate_node(ast, n->expr.op_expr.left, CTX_PRIMARY); - break; - default: - validate_node(ast, n->expr.op_expr.left, CTX_EXPR); - validate_node(ast, n->expr.op_expr.right, CTX_EXPR); - break; - } - break; - case CTX_PREFIX: - validate_node(ast, n->prefix_expr.postfix_expr, CTX_EXPR); - break; - case CTX_POSTFIX: - validate_node(ast, n->postfix_expr.primary_expr, CTX_PRIMARY); - switch (n->postfix_expr.kind) { - case SPL_AST_CALL_EXPR: - validate_vec(ast, &n->postfix_expr.call_expr, CTX_EXPR); - break; - case SPL_AST_INDEX_EXPR: - validate_node(ast, n->postfix_expr.index_expr, CTX_EXPR); - break; - case SPL_AST_SLICE_EXPR: - validate_node(ast, n->postfix_expr.slice_expr.begin, CTX_EXPR); - validate_node(ast, n->postfix_expr.slice_expr.end, CTX_EXPR); - break; - case SPL_AST_AS_EXPR: - validate_node(ast, n->postfix_expr.type_expr, CTX_TYPE_EXPR); - break; - default: - break; - } - break; - case CTX_PRIMARY: - switch (n->primary_expr.kind) { - case SPL_AST_IDENT: - if (!n->primary_expr.ident) - printf("valid: identifier missing name\n"); - break; - case SPL_AST_ARGGREGATE_INIT: - validate_vec(ast, &n->primary_expr.aggregate_init.expr, CTX_AGG_ITEM); - break; - case SPL_AST_EXPR_EXPR: - validate_node(ast, n->primary_expr.expr, CTX_EXPR); - break; - case SPL_AST_ARRAY_LIT: - validate_node(ast, n->primary_expr.array_lit_expr.type_expr, CTX_TYPE_EXPR); - validate_vec(ast, &n->primary_expr.array_lit_expr.expr_list, CTX_EXPR); - break; - case SPL_AST_BUILTIN_EXPR: - validate_vec(ast, &n->primary_expr.builtin_expr.expr_list, CTX_EXPR); - break; - case SPL_AST_BLOCK_EXPR: - validate_vec(ast, &n->primary_expr.block_expr, CTX_BLOCK_ITEM); - break; - default: - break; - } - break; - case CTX_PACKED: - validate_node(ast, n->packed_expr.expr, CTX_EXPR); - break; - case CTX_AGG_ITEM: - validate_node(ast, n->aggregate_init_item.expr, CTX_EXPR); - break; - case CTX_TYPE_EXPR: - validate_vec(ast, &n->type_expr.type_prefixs, CTX_PREFIX_TYPE); - validate_vec(ast, &n->type_expr.attr_list, CTX_ATTR_ITEM); - if (n->type_expr.kind == SPL_AST_BASE_TYPE_FN) { - validate_vec(ast, &n->type_expr.fn_type.param_list, CTX_PARAM); - validate_node(ast, n->type_expr.fn_type.type_expr, CTX_TYPE_EXPR); - } else if (n->type_expr.kind == SPL_AST_TYPE_STRUCT || - n->type_expr.kind == SPL_AST_TYPE_UNION || - n->type_expr.kind == SPL_AST_TYPE_ENUM) { - validate_vec(ast, &n->type_expr.aggregate_list, CTX_DECL); - } else { - validate_vec(ast, &n->type_expr.type_path, CTX_TYPE_ATOM); - } - break; - default: + case SPL_AST_TYPE_ENUM: + dump_vec(ast, node->type_expr.attr_list, stack); + dump_vec(ast, node->type_expr.aggregate_list, stack); + break; + + case SPL_AST_TYPE_VOID: + case SPL_AST_TYPE_BOOL: + case SPL_AST_TYPE_OPAQUE: + case SPL_AST_TYPE_I8: + case SPL_AST_TYPE_U8: + case SPL_AST_TYPE_I16: + case SPL_AST_TYPE_U16: + case SPL_AST_TYPE_I32: + case SPL_AST_TYPE_U32: + case SPL_AST_TYPE_I64: + case SPL_AST_TYPE_U64: + case SPL_AST_TYPE_ISIZE: + case SPL_AST_TYPE_USIZE: + case SPL_AST_TYPE__F32: + case SPL_AST_TYPE__F64: + case SPL_AST_TYPE_ANY: + case SPL_AST_TYPE_IDENT: + break; + + case SPL_AST__COMPTIME_STMT: + case SPL_AST__DIRECTIVE_BLOCK: + case SPL_AST_TRY_STATEMENT: + case SPL_AST_CATCH_STATEMENT: + case SPL_AST_ERRDEFER_STATEMEMT: + case SPL_AST_EXPR_STATEMENT: + case SPL_AST_BREAK_STATEMENT: + case SPL_AST_CONTINUE_STATEMENT: + break; + + case SPL_AST_COUNT: + UNREACHABLE(); break; } + (void)vec_pop(*stack); } diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index 39725b9..f989f21 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -2,31 +2,133 @@ #define __SPL_AST_H__ #include "../stage0/include/utils.h" +#include "spl_dbg.h" #include "spl_lexer.h" #include "spl_tok.h" -typedef enum { - SPL_AST_CONTAINER_ITEM, - SPL_AST_FN_DECL, - SPL_AST_FN_DEFINE, - SPL_AST_TYPE_DECL, - SPL_AST_VAR_DECL, - SPL_AST_CONST_DECL, - SPL_AST_MEMBER_DECL, - SPL_AST__COMPTIME_STMT, /*不实现*/ - SPL_AST__DIRECTIVE_BLOCK, /*不实现*/ +/* clang-format off */ +#define SPL_AST_KIND_TABLE \ + X(SPL_AST_NONE, V0, none) \ + X(SPL_AST_CONTAINER_ITEM, V0, container_item) \ + X(SPL_AST_FN_DECL, V0, fn_decl) \ + X(SPL_AST_FN_DEFINE, V0, fn_define) \ + X(SPL_AST_TYPE_DECL, V0, type_decl) \ + X(SPL_AST_VAR_DECL, V0, var_decl) \ + X(SPL_AST_CONST_DECL, V0, const_decl) \ + X(SPL_AST_MEMBER_DECL, V0, member_decl) \ + X(SPL_AST__COMPTIME_STMT, V0, comptime_stmt) \ + X(SPL_AST__DIRECTIVE_BLOCK, V0, directive_block) \ + X(SPL_AST_PARAM_DECL, V0, param_decl) \ + X(SPL_AST_ATTR_ITEM, V0, attr_item) \ + X(SPL_AST_ARGG_INIT_ITEM, V0, argg_init_item) \ + X(SPL_AST_IF_STATEMENT, V0, if_statement) \ + X(SPL_AST_IFVAR_STATEMENT, V0, ifvar_statement) \ + X(SPL_AST_WHILE_STATEMENT, V0, while_statement) \ + X(SPL_AST_LOOP_STATEMENT, V0, loop_statement) \ + X(SPL_AST_FOR_STATEMENT, V0, for_statement) \ + X(SPL_AST_MATCH_STATEMENT, V0, match_statement) \ + X(SPL_AST_RET_STATEMENT, V0, ret_statement) \ + X(SPL_AST_BREAK_STATEMENT, V0, break_statement) \ + X(SPL_AST_CONTINUE_STATEMENT, V0, continue_statement) \ + X(SPL_AST_DEFER_STATEMENT, V0, defer_statement) \ + X(SPL_AST_TRY_STATEMENT, V0, try_statement) \ + X(SPL_AST_CATCH_STATEMENT, V0, catch_statement) \ + X(SPL_AST_ERRDEFER_STATEMEMT, V0, errdefer_statement) \ + X(SPL_AST_EXPR_STATEMENT, V0, expr_statement) \ + X(SPL_AST_PACKED_EXPR, V0, packed_expr) \ + X(SPL_AST_ASSIGN_EXPR, V0, assign_expr) \ + X(SPL_AST_ASSIGN_ADD_EXPR, V0, assign_add_expr) \ + X(SPL_AST_ASSIGN_SUB_EXPR, V0, assign_sub_expr) \ + X(SPL_AST_ASSIGN_MUL_EXPR, V0, assign_mul_expr) \ + X(SPL_AST_ASSIGN_DIV_EXPR, V0, assign_div_expr) \ + X(SPL_AST_ASSIGN_MOD_EXPR, V0, assign_mod_expr) \ + X(SPL_AST_ASSIGN_AND_EXPR, V0, assign_and_expr) \ + X(SPL_AST_ASSIGN_OR_EXPR, V0, assign_or_expr) \ + X(SPL_AST_ASSIGN_XOR_EXPR, V0, assign_xor_expr) \ + X(SPL_AST_ASSIGN_LSHIFT_EXPR, V0, assign_lshift_expr) \ + X(SPL_AST_ASSIGN_USHIFT_EXPR, V0, assign_ushift_expr) \ + X(SPL_AST_BOOL_OR_EXPR, V0, bool_or_expr) \ + X(SPL_AST_BOOL_AND_EXPR, V0, bool_and_expr) \ + X(SPL_AST_BIT_OR_EXPR, V0, bit_or_expr) \ + X(SPL_AST_BIT_XOR_EXPR, V0, bit_xor_expr) \ + X(SPL_AST_BIT_AND_EXPR, V0, bit_and_expr) \ + X(SPL_AST_CMP_EQ_EXPR, V0, cmp_eq_expr) \ + X(SPL_AST_CMP_NE_EXPR, V0, cmp_ne_expr) \ + X(SPL_AST_CMP_LE_EXPR, V0, cmp_le_expr) \ + X(SPL_AST_CMP_GE_EXPR, V0, cmp_ge_expr) \ + X(SPL_AST_CMP_LT_EXPR, V0, cmp_lt_expr) \ + X(SPL_AST_CMP_GT_EXPR, V0, cmp_gt_expr) \ + X(SPL_AST_RANGE_EXPR, V0, range_expr) \ + X(SPL_AST_LSHIFT_EXPR, V0, lshift_expr) \ + X(SPL_AST_RSHIFT_EXPR, V0, rshift_expr) \ + X(SPL_AST_ADD_EXPR, V0, add_expr) \ + X(SPL_AST_SUB_EXPR, V0, sub_expr) \ + X(SPL_AST_MUL_EXPR, V0, mul_expr) \ + X(SPL_AST_DIV_EXPR, V0, div_expr) \ + X(SPL_AST_MOD_EXPR, V0, mod_expr) \ + X(SPL_AST_MINUS_EXPR, V0, minus_expr) \ + X(SPL_AST_NOT_EXPR, V0, not_expr) \ + X(SPL_AST_BIT_NOT_EXPR, V0, bit_not_expr) \ + X(SPL_AST_ADDRESS_EXPR, V0, address_expr) \ + X(SPL_AST_CALL_EXPR, V0, call_expr) \ + X(SPL_AST_FIELD_EXPR, V0, field_expr) \ + X(SPL_AST_DEREF_EXPR, V0, deref_expr) \ + X(SPL_AST_INDEX_EXPR, V0, index_expr) \ + X(SPL_AST_SLICE_EXPR, V0, slice_expr) \ + X(SPL_AST_AS_EXPR, V0, as_expr) \ + X(SPL_AST_EXPR_INTEGER_LIT, V0, integer_lit) \ + X(SPL_AST_EXPR_FLOAT_LIT, V0, float_lit) \ + X(SPL_AST_EXPR_CHAR_LIT, V0, char_lit) \ + X(SPL_AST_EXPR_STRING_LIT, V0, string_lit) \ + X(SPL_AST_EXPR_TRUE, V0, true_lit) \ + X(SPL_AST_EXPR_FALSE, V0, false_lit) \ + X(SPL_AST_EXPR_NULL, V0, null_lit) \ + X(SPL_AST_EXPR_UNDEFINED, V0, undefined_lit) \ + X(SPL_AST_EXPR_IDENT, V0, ident_expr) \ + X(SPL_AST_ARGGREGATE_INIT, V0, aggregate_init) \ + X(SPL_AST_EXPR_EXPR, V0, expr_expr) \ + X(SPL_AST_ARRAY_LIT, V0, array_lit) \ + X(SPL_AST_BUILTIN_EXPR, V0, builtin_expr) \ + X(SPL_AST_BLOCK_EXPR, V0, block_expr) \ + X(SPL_AST_BASE_TYPE_FN, V0, base_type_fn) \ + X(SPL_AST_BASE_TYPE_PATH, V0, base_type_path) \ + X(SPL_AST_TYPE_POINTER, V0, type_pointer) \ + X(SPL_AST_TYPE_ARRAY, V0, type_array) \ + X(SPL_AST_TYPE_SLICE, V0, type_slice) \ + X(SPL_AST_TYPE_STRUCT, V0, type_struct) \ + X(SPL_AST_TYPE_UNION, V0, type_union) \ + X(SPL_AST_TYPE_ENUM, V0, type_enum) \ + X(SPL_AST_TYPE_VOID, V0, type_void) \ + X(SPL_AST_TYPE_BOOL, V0, type_bool) \ + X(SPL_AST_TYPE_OPAQUE, V0, type_opaque) \ + X(SPL_AST_TYPE_I8, V0, type_i8) \ + X(SPL_AST_TYPE_U8, V0, type_u8) \ + X(SPL_AST_TYPE_I16, V0, type_i16) \ + X(SPL_AST_TYPE_U16, V0, type_u16) \ + X(SPL_AST_TYPE_I32, V0, type_i32) \ + X(SPL_AST_TYPE_U32, V0, type_u32) \ + X(SPL_AST_TYPE_I64, V0, type_i64) \ + X(SPL_AST_TYPE_U64, V0, type_u64) \ + X(SPL_AST_TYPE_ISIZE, V0, type_isize) \ + X(SPL_AST_TYPE_USIZE, V0, type_usize) \ + X(SPL_AST_TYPE__F32, V0, type_f32) \ + X(SPL_AST_TYPE__F64, V0, type_f64) \ + X(SPL_AST_TYPE_ANY, V0, type_any) \ + X(SPL_AST_TYPE_IDENT, V0, type_ident) \ - SPL_AST_BLOCK_ITEM, - SPL_AST_EXPR, - SPL_AST_TYPE_EXPR, - SPL_AST_ATTR_LIST, +/* clang-format on*/ + +typedef enum { +#ifdef X +#undef X +#endif + #define X(name, ...) name, + SPL_AST_KIND_TABLE +#undef X + SPL_AST_COUNT, } spl_ast_node_kind_t; -typedef struct { - const char *fname; - int line; - int col; -} spl_ast_loc_t; +const char *spl_ast_kind_name(spl_ast_node_kind_t kind); struct spl_ast_node; typedef struct spl_ast_node spl_ast_node_t; @@ -34,13 +136,12 @@ typedef usize spl_ast_node_ref_t; typedef VEC(spl_ast_node_ref_t) spl_ast_node_ref_vec_t; struct spl_ast_node { spl_ast_node_kind_t kind; - spl_ast_loc_t loc; + spl_dbg_node_t dbg; usize resolved_def_id; union { struct { spl_ast_node_ref_vec_t attr_list; /* attr_item */ - spl_ast_node_ref_t self; /* self */ spl_ast_node_ref_vec_t members; /* container_decl 列表 */ } container_item; @@ -54,7 +155,7 @@ struct spl_ast_node { const char *name; spl_ast_node_ref_vec_t param_list; /* param_decl */ spl_ast_node_ref_t type_expr; - spl_ast_node_ref_vec_t block; /* block_item */ + spl_ast_node_ref_vec_t block; /* 语句/尾表达式 */ } fn_decl; struct { spl_ast_node_ref_vec_t attr_list; /* attr_item */ @@ -77,149 +178,60 @@ struct spl_ast_node { const char *name; spl_ast_node_ref_t type_expr; spl_ast_node_ref_t expr; - } var_decl; - struct { - spl_ast_node_ref_vec_t attr_list; /* attr_item */ - spl_ast_node_ref_t type_expr; - const char *name; - spl_ast_node_ref_t expr; - } const_decl; + } var_const_decl; + /* 语句数据:kind 决定解释哪个成员 */ struct { - enum { - SPL_AST_IF_STATEMENT, - SPL_AST_IFVAR_STATEMENT, - SPL_AST_WHILE_STATEMENT, - SPL_AST_LOOP_STATEMENT, - SPL_AST_FOR_STATEMENT, - SPL_AST_MATCH_STATEMENT, - SPL_AST_RET_STATEMENT, - SPL_AST_BREAK_STATEMENT, - SPL_AST_CONTINUE_STATEMENT, - SPL_AST_DEFER_STATEMENT, - SPL_AST_VARDECL, - SPL_AST_CONSTDECL, - SPL_AST_TYPEDECL, - SPL_AST_EXPR_STATEMENT, - } kind; - union { - struct { - spl_ast_node_ref_t expr; - spl_ast_node_ref_vec_t if_block; /* block_item */ - spl_ast_node_ref_vec_t else_block; /* block_item */ - } if_statement; - struct { - spl_ast_node_ref_t packed_expr; - spl_ast_node_ref_vec_t if_block; /* block_item */ - spl_ast_node_ref_vec_t else_block; /* block_item */ - } ifvar_statement; - struct { - spl_ast_node_ref_t expr; - spl_ast_node_ref_vec_t while_block; /* block_item */ - } while_statement; - struct { - spl_ast_node_ref_vec_t loop_block; /* block_item */ - } loop_statement; - struct { - spl_ast_node_ref_vec_t expr_vec; - VEC(char *) ident_vec; - spl_ast_node_ref_vec_t block; /* block_item */ - } for_statement; - struct { - spl_ast_node_ref_t expr; - spl_ast_node_ref_vec_t paced_exprs; /* packed_expr */ - spl_ast_node_ref_vec_t match_block; /* block_item */ - } match_statement; - struct { - spl_ast_node_ref_t expr; - } ret_statement; - struct { - } break_statement; - struct { - } continue_statement; - struct { - spl_ast_node_ref_vec_t block_or_statement; /* block_item/statement */ - } defer_statement; - spl_ast_node_ref_t var_decl; - spl_ast_node_ref_t const_decl; - spl_ast_node_ref_t type_decl; - spl_ast_node_ref_t expr_statement; - }; - } block_item; + spl_ast_node_ref_t expr; + spl_ast_node_ref_vec_t if_block; /* 语句 */ + spl_ast_node_ref_vec_t else_block; /* 语句 */ + } if_statement; + struct { + spl_ast_node_ref_t packed_expr; + spl_ast_node_ref_vec_t if_block; /* 语句 */ + spl_ast_node_ref_vec_t else_block; /* 语句 */ + } ifvar_statement; + struct { + spl_ast_node_ref_t expr; + spl_ast_node_ref_vec_t while_block; /* 语句 */ + } while_statement; + struct { + spl_ast_node_ref_vec_t loop_block; /* 语句 */ + } loop_statement; + struct { + spl_ast_node_ref_vec_t expr_vec; + VEC(char *) ident_vec; + spl_ast_node_ref_vec_t block; /* 语句 */ + } for_statement; + struct { + spl_ast_node_ref_t expr; + spl_ast_node_ref_vec_t paced_exprs; /* packed_expr */ + spl_ast_node_ref_vec_t match_block; /* 语句 */ + } match_statement; + struct { + spl_ast_node_ref_t expr; + } ret_statement; + struct { + } break_statement; + struct { + } continue_statement; + struct { + spl_ast_node_ref_vec_t block_or_statement; /* 语句 */ + } defer_statement; + struct { const char *ident; const char *bind_ident; spl_ast_node_ref_t expr; } packed_expr; - struct { - enum { - SPL_AST_ASSIGN_EXPR, - SPL_AST_ASSIGN_ADD_EXPR, - SPL_AST_ASSIGN_sUB_EXPR, - SPL_AST_ASSIGN_MUL_EXPR, - SPL_AST_ASSIGN_DIV_EXPR, - SPL_AST_ASSIGN_MOD_EXPR, - SPL_AST_ASSIGN_AND_EXPR, - SPL_AST_ASSIGN_OR_EXPR, - SPL_AST_ASSIGN_XOR_EXPR, - SPL_AST_ASSIGN_LSHIFT_EXPR, - SPL_AST_ASSIGN_USHIFT_EXPR, - - SPL_AST_BOOLOR_EXPR, - SPL_AST_BOOLAND_EXPR, - SPL_AST_BITOR_EXPR, - SPL_AST_BITXOR_EXPR, - SPL_AST_BITAND_EXPR, - - SPL_AST_CMPEQ_EXPR, - SPL_AST_CMPNE_EXPR, - - SPL_AST_CMP_LE_EXPR, - SPL_AST_CMP_GE_EXPR, - SPL_AST_CMP_LT_EXPR, - SPL_AST_CMP_GT_EXPR, - - SPL_AST_RANGE_EXPR, - - SPL_AST_LSHIFT_EXPR, - SPL_AST_RSHIFT_EXPR, - - SPL_AST_ADD_EXPR, - SPL_AST_SUB_EXPR, - - SPL_AST_MUL_EXPR, - SPL_AST_DIV_EXPR, - SPL_AST_MOD_EXPR, - - SPL_AST_PREFIX_EXPR, /* left ref node */ - SPL_AST_POSTFIX_EXPR, /* left ref node */ - SPL_AST_PRIMARY_EXPR, /* left ref node */ - } op; - struct { - spl_ast_node_ref_t left; - spl_ast_node_ref_t right; - } op_expr; - } expr; + spl_ast_node_ref_t left; + spl_ast_node_ref_t right; + } op_expr; struct { - enum { - SPL_AST_MINUS_EXPR, - SPL_AST_BANG_EXPR, - SPL_AST_TILDE_EXPR, - SPL_AST_AMPERSAND_EXPR, - SPL_AST_ASTERISK_EXPR, - } kind; spl_ast_node_ref_t postfix_expr; } prefix_expr; struct { - enum { - SPL_AST_CALL_EXPR, - SPL_AST_FIELD_EXPR, - SPL_AST_DEREF_EXPR, - SPL_AST_INDEX_EXPR, - SPL_AST_SLICE_EXPR, - SPL_AST_AS_EXPR, - } kind; spl_ast_node_ref_t primary_expr; union { spl_ast_node_ref_vec_t call_expr; @@ -232,66 +244,53 @@ struct spl_ast_node { spl_ast_node_ref_t type_expr; }; } postfix_expr; + struct { - enum { - SPL_AST_INTEGER, - SPL_AST_FLOAT, - SPL_AST_CHAR_LIT, - SPL_AST_STRING_LIT, - SPL_AST_TRUE, - SPL_AST_FALSE, - SPL_AST_NULL, - SPL_AST_IDENT, - SPL_AST_ARGGREGATE_INIT, - SPL_AST_EXPR_EXPR, - SPL_AST_ARRAY_LIT, - SPL_AST_BUILTIN_EXPR, - SPL_AST_BLOCK_EXPR, - } kind; - union { - isize integer_expr; - double float_expr; - char char_lit_expr; - const char *string_lit_expr; /* parsed c string */ + isize integer_expr; + double float_expr; + char char_lit_expr; + const char *string_lit_expr; /* parsed c string */ + const char *ident; + + struct { + const char *name; + spl_ast_node_ref_vec_t expr; /* aggregate_init_item */ + } aggregate_init; + + spl_ast_node_ref_t expr; + struct { + isize integer; + spl_ast_node_ref_t type_expr; + spl_ast_node_ref_vec_t expr_list; + } array_lit_expr; + struct { const char *ident; - - struct { - const char *name; - spl_ast_node_ref_vec_t expr; /* aggregate_init_item */ - } aggregate_init; - - spl_ast_node_ref_t expr; - struct { - isize integer; - spl_ast_node_ref_t type_expr; - spl_ast_node_ref_vec_t expr_list; - } array_lit_expr; - struct { - const char *ident; - spl_ast_node_ref_vec_t expr_list; - } builtin_expr; - spl_ast_node_ref_vec_t block_expr; /* block_item */ - }; + spl_ast_node_ref_vec_t expr_list; + } builtin_expr; + spl_ast_node_ref_vec_t block_expr; /* 语句 */ } primary_expr; + struct { const char *ident; spl_ast_node_ref_t expr; } aggregate_init_item; struct { - spl_ast_node_ref_vec_t type_prefixs; /* prefix_type */ - spl_ast_node_ref_vec_t attr_list; /* attr_item */ - enum { - SPL_AST_BASE_TYPE_FN, - SPL_AST_BASE_TYPE_PATH, - SPL_AST_TYPE_STRUCT, - SPL_AST_TYPE_UNION, - SPL_AST_TYPE_ENUM, - } kind; - - const char *spl_base_type; + spl_ast_node_ref_vec_t attr_list; /* attr_item */ union { - spl_ast_node_ref_vec_t type_path; /* type_atom */ + struct { + VEC(const char *) ident_vec; + } type_path; + struct { + spl_ast_node_ref_t element; + spl_ast_node_ref_t size; + } array_type; + struct { + spl_ast_node_ref_t element; + } slice_type; + struct { + spl_ast_node_ref_t pointee; + } pointer_type; struct { spl_ast_node_ref_vec_t param_list; /* param_decl */ spl_ast_node_ref_t type_expr; @@ -299,42 +298,16 @@ struct spl_ast_node { spl_ast_node_ref_vec_t aggregate_list; /* container_decl */ }; } type_expr; - struct { - /* ASTERISK = 1, [] = 2, else = 0*/ - int pointer; - /* if array_size != 0 then pointer == 2 */ - int array_size; - } prefix_type; - struct { - enum { - SPL_AST_TYPE_VOID, - SPL_AST_TYPE_BOOL, - SPL_AST_TYPE_I8, - SPL_AST_TYPE_U8, - SPL_AST_TYPE_I16, - SPL_AST_TYPE_U16, - SPL_AST_TYPE_I32, - SPL_AST_TYPE_U32, - SPL_AST_TYPE_I64, - SPL_AST_TYPE_U64, - SPL_AST_TYPE_ISIZE, - SPL_AST_TYPE_USIZE, - SPL_AST_TYPE__F32, /*不实现*/ - SPL_AST_TYPE__F64, /*不实现*/ - SPL_AST_TYPE_PTR, - SPL_AST_TYPE_ANY, - SPL_AST_TYPE_IDENT, - } kind; - const char *ident; - } type_atom; }; }; typedef VEC(spl_ast_node_t) spl_ast_node_vec_t; +typedef VEC(char*)spl_ast_cstr_ref_vec_t; typedef struct { int parsed; spl_tok_vec_t input; - spl_ast_node_vec_t buckets; + spl_ast_node_vec_t node_buckets; + spl_ast_cstr_ref_vec_t str_buckets; spl_ast_node_ref_t root; } spl_ast_t; diff --git a/stage1/spl_dbg.h b/stage1/spl_dbg.h new file mode 100644 index 0000000..c5f2f15 --- /dev/null +++ b/stage1/spl_dbg.h @@ -0,0 +1,17 @@ +#ifndef __SPL_DBG_H__ +#define __SPL_DBG_H__ + +#include "spl_tok.h" + +typedef struct { + const char *dbg_name; + const char *fpath; + int line; + int col; +} spl_dbg_node_t; + +#define SPL_FATAL(tok, fmt, ...) \ + LOG_FATAL("fatal at %s:%zd:%zd " fmt, ((tok) && (tok)->fname ? (tok)->fname : ""), \ + ((tok) ? (tok)->line : 0), ((tok) ? (tok)->col : 0), ##__VA_ARGS__) + +#endif /* __SPL_DBG_H__ */ diff --git a/stage1/spl_ir.h b/stage1/spl_ir.h index 2776cee..4447846 100644 --- a/stage1/spl_ir.h +++ b/stage1/spl_ir.h @@ -2,8 +2,10 @@ #define __SPL_IR_H__ #include "../stage0/include/utils.h" +#include "spl_dbg.h" #include "spl_type.h" + /* clang-format off */ #define SPL_IR_FN_TABLE \ X(arith.add, V0, SPL_IR_ARITH_ADD) \ @@ -91,7 +93,7 @@ typedef usize spl_ir_func_ref_t; /* 0 is error */ typedef struct { spl_ir_kind_t kind; - usize src_ref; /* AST 节点 ref(调试行号用,ast2ir 注解) */ + spl_dbg_node_t dbg; union { struct { spl_type_id_t tid; @@ -238,24 +240,12 @@ typedef struct { } spl_ir_attr_t; typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_t; -/* 调试:函数内变量(名 → 内存位置)。alloca 节点或参数槽。 */ -typedef struct { - const char *name; /* 指向 AST 字符串,不拥有 */ - spl_ir_node_ref_t alloca; /* 非参数:alloca 节点 ref */ - spl_type_id_t tid; - int is_param; /* 参数则用 param_idx */ - usize param_idx; - usize offset; /* fp 字节偏移(LADDR imm 语义;ir2vm 填) */ -} spl_ir_dbg_var_t; -typedef VEC(spl_ir_dbg_var_t) spl_ir_dbg_var_vec_t; - typedef struct { const char *name; spl_ir_attr_t attr; spl_type_id_t fn_tid; spl_ir_node_vec_t nodes; spl_ir_node_ref_vec_t labels; - spl_ir_dbg_var_vec_t dbg_vars; /* 调试变量表(fp 偏移在 ir2vm 填) */ } spl_ir_func_t; typedef VEC(spl_ir_func_t) spl_ir_func_vec_t; diff --git a/stage1/spl_layout.c b/stage1/spl_layout.c new file mode 100644 index 0000000..e69de29 diff --git a/stage1/spl_layout.h b/stage1/spl_layout.h new file mode 100644 index 0000000..e69de29 diff --git a/stage1/spl_lexer.c b/stage1/spl_lexer.c index 2827bf0..67f52a8 100644 --- a/stage1/spl_lexer.c +++ b/stage1/spl_lexer.c @@ -1,4 +1,4 @@ -/* spl_lexer.c — SPL lexical analyzer */ +/* spl_lexer.c - SPL lexical analyzer */ #include "spl_lexer.h" #include "spl_tok.h" @@ -21,7 +21,7 @@ static spl_tok_type_t keyword_type(const char *ident, usize len) { return TOK_IDENT; } -/* Escape sequence decoder — returns the decoded character, +/* Escape sequence decoder - returns the decoded character, * advances *s past the escape sequence, returns 0 on success, * non-zero on error. */ int spl_decode_escape(const char **s, char *out) { @@ -85,7 +85,7 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) { const char *start = source + offset; char c = *start; - /* Skip whitespace (but not newlines — emit TOK_ENDLINE) */ + /* Skip whitespace (but not newlines - emit TOK_ENDLINE) */ if (c == ' ' || c == '\t' || c == '\r') { offset++; col++; diff --git a/stage1/spl_lexer.h b/stage1/spl_lexer.h index 9f5d218..c9303a3 100644 --- a/stage1/spl_lexer.h +++ b/stage1/spl_lexer.h @@ -1,4 +1,4 @@ -/* spl_lexer.h — 独立词法分析器 */ +/* spl_lexer.h - 独立词法分析器 */ #ifndef __SPL_LEXER_H__ #define __SPL_LEXER_H__ diff --git a/stage1/spl_tok.h b/stage1/spl_tok.h index a240c7b..cdea086 100644 --- a/stage1/spl_tok.h +++ b/stage1/spl_tok.h @@ -1,4 +1,4 @@ -/* spl_tok.h — Token type definitions (extracted from spl_lexer.h) */ +/* spl_tok.h - Token type definitions (extracted from spl_lexer.h) */ #ifndef __SPL_TOK_H__ #define __SPL_TOK_H__ @@ -6,31 +6,36 @@ /* clang-format off */ #define KEYWORD_TABLE \ - X(as , KW_AS , SPL_V0) \ - X(bool , KW_BOOL , SPL_V0) \ - X(break , KW_BREAK , SPL_V0) \ - X(comptime , KW_COMPTIME , SPL_V0) \ - X(const , KW_CONST , SPL_V0) \ - X(continue , KW_CONTINUE , SPL_V0) \ - X(defer , KW_DEFER , SPL_V0) \ - X(else , KW_ELSE , SPL_V0) \ - X(enum , KW_ENUM , SPL_V0) \ - X(false , KW_FALSE , SPL_V0) \ - X(fn , KW_FN , SPL_V0) \ - X(for , KW_FOR , SPL_V0) \ - X(if , KW_IF , SPL_V0) \ - X(loop , KW_LOOP , SPL_V0) \ - X(match , KW_MATCH , SPL_V0) \ - X(null , KW_NULL , SPL_V0) \ - X(ret , KW_RET , SPL_V0) \ - X(struct , KW_STRUCT , SPL_V0) \ - X(true , KW_TRUE , SPL_V0) \ - X(type , KW_TYPE , SPL_V0) \ - X(union , KW_UNION , SPL_V0) \ - X(var , KW_VAR , SPL_V0) \ - X(void , KW_VOID , SPL_V0) \ - X(while , KW_WHILE , SPL_V0) \ - X(_ , KW_ANY , SPL_V0) \ + X(as , KW_AS , SPL_V0) \ + X(bool , KW_BOOL , SPL_V0) \ + X(break , KW_BREAK , SPL_V0) \ + X(catch , KW_CATCH , SPL_V0) \ + X(comptime , KW_COMPTIME , SPL_V0) \ + X(const , KW_CONST , SPL_V0) \ + X(continue , KW_CONTINUE , SPL_V0) \ + X(defer , KW_DEFER , SPL_V0) \ + X(else , KW_ELSE , SPL_V0) \ + X(enum , KW_ENUM , SPL_V0) \ + X(errdefer , KW_ERRDEFER , SPL_V0) \ + X(false , KW_FALSE , SPL_V0) \ + X(fn , KW_FN , SPL_V0) \ + X(for , KW_FOR , SPL_V0) \ + X(if , KW_IF , SPL_V0) \ + X(loop , KW_LOOP , SPL_V0) \ + X(match , KW_MATCH , SPL_V0) \ + X(null , KW_NULL , SPL_V0) \ + X(ret , KW_RET , SPL_V0) \ + X(shape , WK_SHAPE , SPL_V0) \ + X(struct , KW_STRUCT , SPL_V0) \ + X(true , KW_TRUE , SPL_V0) \ + X(try , KW_TRY , SPL_V0) \ + X(type , KW_TYPE , SPL_V0) \ + X(undefined , KW_UNDEFINDED , SPL_V0) \ + X(union , KW_UNION , SPL_V0) \ + X(var , KW_VAR , SPL_V0) \ + X(void , KW_VOID , SPL_V0) \ + X(while , KW_WHILE , SPL_V0) \ + X(_ , KW_ANY , SPL_V0) \ // KEYWORD_TABLE #define TOKEN_TABLE \ diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 830bb02..237489c 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -58,7 +58,6 @@ typedef struct { spl_def_id_t def_id; spl_type_id_t type_id; usize scope_id; - int is_const; /* var_def 是否为 const 声明(只读) */ } spl_var_def_t; typedef VEC(spl_var_def_t) spl_var_def_vec_t; diff --git a/stage1/splc0.c b/stage1/splc0.c index d1486be..2ae683d 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -1,4 +1,4 @@ -/* splc0.c — SPL compiler CLI (stage 1, 引导用) +/* splc0.c - SPL compiler CLI (stage 1, 引导用) * * splc0 --dump tokens|ast|all dump 前端产物 * splc0 编译 (阶段 B 实现) @@ -73,79 +73,79 @@ static void dump_ast(const char *src, const char *fname) { spl_ast_drop(&ast); } -static void dump_sema(const char *src, const char *fname) { - spl_tok_vec_t toks = spl_lex(src, fname); - spl_ast_t ast; - spl_ast_init(&ast, &toks); - spl_ast_prase(&ast); - if (ast.parsed < 0) { - printf("parse failed, skip sema dump\n"); - spl_ast_drop(&ast); - return; - } - spl_ast_valid(&ast); - spl_sema_t sema; - spl_sema_init(&sema); - sema.ast = * - spl_sema_run(&sema); - spl_sema_check(&sema); - printf("Sema root_scope=%zu scopes=%zu errors=%d\n", sema.root_scope, sema.scopes.size, - sema.error_count); - for (usize i = 0; i < sema.scopes.size; i++) { - printf("scope[%zu] parent=%zu\n", i, sema.scopes.data[i].parent); - map_for(sema.scopes.data[i].symbols, mi) { - printf(" %s -> def#%zu\n", sema.scopes.data[i].symbols.data[mi].key, - sema.scopes.data[i].symbols.data[mi].val); - } - } - printf("TypeTable:\n"); - for (usize i = 0; i < sema.type.type_table.size; i++) { - printf(" id#%zu type=", i); - spl_type_pure_dump(&sema.type, i); - printf("\n"); - } - printf("DefTable:\n"); - for (usize i = 0; i < sema.type.def_table.size; i++) { - printf(" def#%zu ", i); - spl_type_def_dump(&sema.type, i); - printf("\n"); - } - spl_sema_drop(&sema); - spl_ast_drop(&ast); -} +// static void dump_sema(const char *src, const char *fname) { +// spl_tok_vec_t toks = spl_lex(src, fname); +// spl_ast_t ast; +// spl_ast_init(&ast, &toks); +// spl_ast_prase(&ast); +// if (ast.parsed < 0) { +// printf("parse failed, skip sema dump\n"); +// spl_ast_drop(&ast); +// return; +// } +// spl_ast_valid(&ast); +// spl_sema_t sema; +// spl_sema_init(&sema); +// sema.ast = * +// spl_sema_run(&sema); +// spl_sema_check(&sema); +// printf("Sema root_scope=%zu scopes=%zu errors=%d\n", sema.root_scope, sema.scopes.size, +// sema.error_count); +// for (usize i = 0; i < sema.scopes.size; i++) { +// printf("scope[%zu] parent=%zu\n", i, sema.scopes.data[i].parent); +// map_for(sema.scopes.data[i].symbols, mi) { +// printf(" %s -> def#%zu\n", sema.scopes.data[i].symbols.data[mi].key, +// sema.scopes.data[i].symbols.data[mi].val); +// } +// } +// printf("TypeTable:\n"); +// for (usize i = 0; i < sema.type.type_table.size; i++) { +// printf(" id#%zu type=", i); +// spl_type_pure_dump(&sema.type, i); +// printf("\n"); +// } +// printf("DefTable:\n"); +// for (usize i = 0; i < sema.type.def_table.size; i++) { +// printf(" def#%zu ", i); +// spl_type_def_dump(&sema.type, i); +// printf("\n"); +// } +// spl_sema_drop(&sema); +// spl_ast_drop(&ast); +// } -static void dump_ir(const char *src, const char *fname) { - spl_tok_vec_t toks = spl_lex(src, fname); - spl_ast_t ast; - spl_ast_init(&ast, &toks); - spl_ast_prase(&ast); - if (ast.parsed < 0) { - printf("parse failed, skip IR\n"); - spl_ast_drop(&ast); - return; - } - spl_ast_valid(&ast); - spl_sema_t sema; - spl_sema_init(&sema); - sema.ast = * - spl_sema_run(&sema); - spl_sema_check(&sema); - if (sema.error_count) { - printf("sema errors=%d, skip IR\n", sema.error_count); - spl_sema_drop(&sema); - spl_ast_drop(&ast); - return; - } - spl_ast2ir_t a2ir; - spl_ast2ir_init(&a2ir, &sema); - spl_ast2ir_run(&a2ir); - if (a2ir.err_count) - printf("ast2ir errors=%d\n", a2ir.err_count); - spl_ir_dump(&a2ir.ir, &sema.type); - spl_ast2ir_drop(&a2ir); - spl_sema_drop(&sema); - spl_ast_drop(&ast); -} +// static void dump_ir(const char *src, const char *fname) { +// spl_tok_vec_t toks = spl_lex(src, fname); +// spl_ast_t ast; +// spl_ast_init(&ast, &toks); +// spl_ast_prase(&ast); +// if (ast.parsed < 0) { +// printf("parse failed, skip IR\n"); +// spl_ast_drop(&ast); +// return; +// } +// spl_ast_valid(&ast); +// spl_sema_t sema; +// spl_sema_init(&sema); +// sema.ast = * +// spl_sema_run(&sema); +// spl_sema_check(&sema); +// if (sema.error_count) { +// printf("sema errors=%d, skip IR\n", sema.error_count); +// spl_sema_drop(&sema); +// spl_ast_drop(&ast); +// return; +// } +// spl_ast2ir_t a2ir; +// spl_ast2ir_init(&a2ir, &sema); +// spl_ast2ir_run(&a2ir); +// if (a2ir.err_count) +// printf("ast2ir errors=%d\n", a2ir.err_count); +// spl_ir_dump(&a2ir.ir, &sema.type); +// spl_ast2ir_drop(&a2ir); +// spl_sema_drop(&sema); +// spl_ast_drop(&ast); +// } static int cmd_dump(const char *flags, const char *path) { long len; @@ -160,25 +160,14 @@ static int cmd_dump(const char *flags, const char *path) { dump_tokens(src, path); if (do_ast) dump_ast(src, path); - if (do_sema) - dump_sema(src, path); - if (do_ir) - dump_ir(src, path); + // if (do_sema) + // dump_sema(src, path); + // if (do_ir) + // dump_ir(src, path); free(src); return 0; } -static spl_ast_node_t *ast_node_at(spl_ast_t *ast, spl_ast_node_ref_t ref) { - if (ref == 0 || ref >= ast->buckets.size) - return NULL; - return &ast->buckets.data[ref]; -} - -static int ast_line(spl_ast_t *ast, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = ast_node_at(ast, ref); - return n ? n->loc.line : 0; -} - /* -g:在 .sir 尾部追加 debug 段(文本:IR 行 + VAR 行),spl_cli -g 读取 */ static void gen_debug_map(const char *outpath, spl_ast_t *ast, const spl_ir_t *ir, const spl_ir2vm_t *ir2vm) { @@ -186,73 +175,74 @@ static void gen_debug_map(const char *outpath, spl_ast_t *ast, const spl_ir_t *i if (!f) return; fprintf(f, "SPLDBG\n"); - for (usize i = 0; i < ir2vm->fdbg.size; i++) { - const spl_ir2vm_fdbg_t *fd = &ir2vm->fdbg.data[i]; - if (fd->fid >= ir->funcs.size) - continue; - const spl_ir_func_t *fn = &ir->funcs.data[fd->fid]; - const char *fname = fn->name ? fn->name : "?"; - for (usize ref = 1; ref < fd->node_first_ip.size; ref++) { - usize ip = fd->node_first_ip.data[ref]; - if (ip == (usize)-1) - continue; - const spl_ir_node_t *n = &fn->nodes.data[ref]; - fprintf(f, "IR %zu %zu %d %s\n", ip, ref, ast_line(ast, n->src_ref), - spl_ir_kind_name(n->kind)); - } - for (usize j = 0; j < fn->dbg_vars.size; j++) { - const spl_ir_dbg_var_t *dv = &fn->dbg_vars.data[j]; - if (!dv->name) - continue; - fprintf(f, "VAR %s %s %zu %zu %d\n", fname, dv->name, dv->offset, dv->tid, - dv->is_param); - } - } + // for (usize i = 0; i < ir2vm->fdbg.size; i++) { + // const spl_ir2vm_fdbg_t *fd = &ir2vm->fdbg.data[i]; + // if (fd->fid >= ir->funcs.size) + // continue; + // const spl_ir_func_t *fn = &ir->funcs.data[fd->fid]; + // const char *fname = fn->name ? fn->name : "?"; + // for (usize ref = 1; ref < fd->node_first_ip.size; ref++) { + // usize ip = fd->node_first_ip.data[ref]; + // if (ip == (usize)-1) + // continue; + // const spl_ir_node_t *n = &fn->nodes.data[ref]; + // fprintf(f, "IR %zu %zu %d %s\n", ip, ref, ast_line(ast, n->src_ref), + // spl_ir_kind_name(n->kind)); + // } + // for (usize j = 0; j < fn->dbg_vars.size; j++) { + // const spl_ir_dbg_var_t *dv = &fn->dbg_vars.data[j]; + // if (!dv->name) + // continue; + // fprintf(f, "VAR %s %s %zu %zu %d\n", fname, dv->name, dv->offset, dv->tid, + // dv->is_param); + // } + // } fclose(f); } static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug) { - spl_tok_vec_t toks = spl_lex(src, fname); - spl_ast_t ast; - spl_ast_init(&ast, &toks); - spl_ast_prase(&ast); - if (ast.parsed < 0) { - printf("parse failed, no output\n"); - spl_ast_drop(&ast); - return 1; - } - spl_ast_valid(&ast); - spl_sema_t sema; - spl_sema_init(&sema); - sema.ast = * - spl_sema_run(&sema); - spl_sema_check(&sema); - if (sema.error_count) { - printf("sema errors=%d, no output\n", sema.error_count); - spl_sema_drop(&sema); - spl_ast_drop(&ast); - return 1; - } - spl_ast2ir_t a2ir; - spl_ast2ir_init(&a2ir, &sema); - spl_ast2ir_run(&a2ir); - if (a2ir.err_count) { - printf("ast2ir errors=%d, no output\n", a2ir.err_count); - spl_ast2ir_drop(&a2ir); - spl_sema_drop(&sema); - spl_ast_drop(&ast); - return 1; - } - spl_ir2vm_t ir2vm; - spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type); - int rc = spl_ir2vm_run(&ir2vm, outpath); - if (gen_debug && rc == 0) - gen_debug_map(outpath, &ast, &a2ir.ir, &ir2vm); - spl_ir2vm_drop(&ir2vm); - spl_ast2ir_drop(&a2ir); - spl_sema_drop(&sema); - spl_ast_drop(&ast); - return rc ? 1 : 0; + // spl_tok_vec_t toks = spl_lex(src, fname); + // spl_ast_t ast; + // spl_ast_init(&ast, &toks); + // spl_ast_prase(&ast); + // if (ast.parsed < 0) { + // printf("parse failed, no output\n"); + // spl_ast_drop(&ast); + // return 1; + // } + // spl_ast_valid(&ast); + // spl_sema_t sema; + // spl_sema_init(&sema); + // sema.ast = * + // spl_sema_run(&sema); + // spl_sema_check(&sema); + // if (sema.error_count) { + // printf("sema errors=%d, no output\n", sema.error_count); + // spl_sema_drop(&sema); + // spl_ast_drop(&ast); + // return 1; + // } + // spl_ast2ir_t a2ir; + // spl_ast2ir_init(&a2ir, &sema); + // spl_ast2ir_run(&a2ir); + // if (a2ir.err_count) { + // printf("ast2ir errors=%d, no output\n", a2ir.err_count); + // spl_ast2ir_drop(&a2ir); + // spl_sema_drop(&sema); + // spl_ast_drop(&ast); + // return 1; + // } + // spl_ir2vm_t ir2vm; + // spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type); + // int rc = spl_ir2vm_run(&ir2vm, outpath); + // if (gen_debug && rc == 0) + // gen_debug_map(outpath, &ast, &a2ir.ir, &ir2vm); + // spl_ir2vm_drop(&ir2vm); + // spl_ast2ir_drop(&a2ir); + // spl_sema_drop(&sema); + // spl_ast_drop(&ast); + // return rc ? 1 : 0; + return 0; } int main(int argc, char **argv) {