stage1 人工重构ast.c

This commit is contained in:
zzy
2026-08-12 10:29:38 +08:00
parent 314100afbc
commit b0e6b406ac
22 changed files with 1619 additions and 2895 deletions

75
SPL.md
View File

@@ -1,13 +1,13 @@
# SPL Self-bootstrapping/System Programming Language # SPL - Self-bootstrapping/System Programming Language
## 项目概述 ## 项目概述
SPL是一个从零构建的自举编译器项目。引导链: SPL是一个从零构建的自举编译器项目。引导链:
``` ```
stage0/spl_vm.c SIR 虚拟机 (C 语言实现) stage0/spl_vm.c - SIR 虚拟机 (C 语言实现)
stage1/splc0.c SPL->SIR 编译器 (C 语言实现,引导用) stage1/splc0.c - SPL->SIR 编译器 (C 语言实现,引导用)
stage1/splc1.spl SPL->SIR 编译器 (SPL 语言实现,自举第一版) stage1/splc1.spl - SPL->SIR 编译器 (SPL 语言实现,自举第一版)
...将来... ...将来...
``` ```
@@ -56,7 +56,7 @@ DirectiveBlock
<- DirectiveHead Block (* @init { } / #test { } *) <- DirectiveHead Block (* @init { } / #test { } *)
# ================================================================ # ================================================================
# comptime 编译期执行 / 断言 (仅容器层) # comptime - 编译期执行 / 断言 (仅容器层)
# ================================================================ # ================================================================
ComptimeStmt ComptimeStmt
@@ -88,6 +88,7 @@ TypeDecl
MemberDecl MemberDecl
<- IDENTIFIER (COLON TypeExpr)? (COMMA / SEMICOLON)? <- IDENTIFIER (COLON TypeExpr)? (COMMA / SEMICOLON)?
(* 聚合成员分隔: `,` 与 `;` 均可。当前 `;` 路径不稳定,测试以 `,` 为准,`;` 仅作兼容验证。 *)
# ================================================================ # ================================================================
# 类型表达式 (Type Expression, LL(1), 无左递归) # 类型表达式 (Type Expression, LL(1), 无左递归)
@@ -98,6 +99,7 @@ TypeExpr <- PrefixTypeOp* AttrList? TypeBase
TypeBase TypeBase
<- FnTypeExpr <- FnTypeExpr
/ TypePath / TypePath
/ KEYWORD_shape LBRACE ContainerDeclaration* RBRACE (* TODO *)
/ KEYWORD_struct LBRACE ContainerDeclaration* RBRACE / KEYWORD_struct LBRACE ContainerDeclaration* RBRACE
/ KEYWORD_union LBRACE ContainerDeclaration* RBRACE / KEYWORD_union LBRACE ContainerDeclaration* RBRACE
/ KEYWORD_enum LBRACE ContainerDeclaration* RBRACE / KEYWORD_enum LBRACE ContainerDeclaration* RBRACE
@@ -141,7 +143,7 @@ ConstDecl
# ================================================================ # ================================================================
# 块 / 语句层 (Block & Statement 仅函数体内) # 块 / 语句层 (Block & Statement - 仅函数体内)
# ================================================================ # ================================================================
Block <- LBRACE BlockItem* Expr? RBRACE Block <- LBRACE BlockItem* Expr? RBRACE
@@ -159,6 +161,9 @@ Statement (* LL(1): 14 分支互
/ BreakStatement / BreakStatement
/ ContinueStatement / ContinueStatement
/ DeferStatement / DeferStatement
/ TryStatement (* TODO *)
/ CatchStatement (* TODO *)
/ ErrDeferStatement (* TODO *)
/ VarDecl / VarDecl
/ ConstDecl / ConstDecl
/ TypeDecl / TypeDecl
@@ -234,8 +239,7 @@ ShiftExpr <- AddExpr ((L_ARROW2 / R_ARROW2) AddExpr)*
AddExpr <- MulExpr ((PLUS / MINUS) MulExpr)* AddExpr <- MulExpr ((PLUS / MINUS) MulExpr)*
MulExpr <- PrefixExpr ((ASTERISK / SLASH / PERCENT) PrefixExpr)* MulExpr <- PrefixExpr ((ASTERISK / SLASH / PERCENT) PrefixExpr)*
PrefixExpr <- PrefixOp* PostfixExpr 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_LITERAL <- "'" (CHAR_PLAIN / CHAR_ESCAPE) "'"
CHAR_PLAIN <- [^\\'\n] CHAR_PLAIN <- [^\\'\n]
CHAR_ESCAPE <- '\\' [ntr\\'"0] CHAR_ESCAPE <- '\\' [ntr\\'"0]
/ '\\x' [0-9a-fA-F] [0-9a-fA-F]
STRING_LITERAL <- '"' (STRING_CHUNK)* '"' STRING_LITERAL <- '"' (STRING_CHUNK)* '"'
STRING_CHUNK <- [^\\"\n]+ / '\\' [ntr\\'"0] STRING_CHUNK <- [^\\"\n]+ / '\\' [ntr\\'"0]
/ '\\x' [0-9a-fA-F] [0-9a-fA-F]
LINE_COMMENT <- '//' [^\n]* LINE_COMMENT <- '//' [^\n]*
BLOCK_COMMENT <- '/*' (!'*/' .)* '*/' BLOCK_COMMENT <- '/*' (BLOCK_COMMENT / !'*/' .)* '*/' (* 支持嵌套 *)
eof <- !. eof <- !.
``` ```
## 当前阶段暂不支持stage1 引导实现限制)
以下语法/特性在当前引导阶段**暂不实现**,使用时报编译错误("not implemented")。
实现推进时按序补齐,并同步更新本清单与测试。
- **comptime 语句**: `comptime { }` / `comptime expr;`spl_ast.c 报 "not implemented: comptime statement"
- **f32 类型**: `var x: f32` 变量声明暂不可用(缺 float 转换指令f64 字面量->f32 需截断),见 BUGS.md #1f64 类型已完整支持
- **@ / # 指令块**: `@init { }` / `#test { }`spl_ast.c 报 "not implemented: @/# directive block"
- **嵌套类型路径构造**: 类型体内嵌套类型可定义,但 `Shape.Inner { ... }` 的路径构造未实现
## TODO ## TODO
```spl
// 约束关键字,语义是`类型子集形状`
type name = shape { ... } type name = shape { ... }
// 默认字段 // 默认字段
@@ -443,7 +457,20 @@ DirectiveBlock @id { } / #id { } 为扩展占位,无预定义行为。未识
@name(args) / #name(args): 内置调用,出现在表达式位置。 @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 ### struct
字段必须 name: Type不可省略。名称唯一。 字段必须 name: Type不可省略。名称唯一。
@@ -798,13 +825,13 @@ T (任意) T 是 无 相同类型
*_ *T 是 警告: “不安全的指针重解释” *_ *T 是 警告: “不安全的指针重解释”
[N]T []T 是 无 数组到切片强制转换 [N]T []T 是 无 数组到切片强制转换
整数字面量 整数类型 U 是 (若值在 U 范围内) 无 字面量自动拓宽 (含字符 'c' 视为 u8) 整数字面量 整数类型 U 是 (若值在 U 范围内) 无 字面量自动拓宽 (含字符 'c' 视为 u8)
i32 i64 否 需显式 as i64防止意外 i32 i64 否 - 需显式 as i64防止意外
i64 i32 否 窄化必须显式 i64 i32 否 - 窄化必须显式
null *T / []T 是 无 空指针/空切片初始化、比较、赋值、聚合字段 null *T / []T 是 无 空指针/空切片初始化、比较、赋值、聚合字段
浮点字面量 f32 是 (值可表示则) 无 浮点字面量 f32 是 (值可表示则) 无
f64 f32 否 窄化需显式 f64 f32 否 - 窄化需显式
bool 整数 否 bool 整数 否 -
整数 bool 否 整数 bool 否 -
注: 注:
@@ -1179,11 +1206,11 @@ CONSTANT ← INTEGER | FLOAT | STRING | 'true' | 'false' | 'null' | 'undefine
标记附加在函数定义前,用逗号分隔。所有标记均不影响 IR 控制流语义,仅向后端传递元数据。 标记附加在函数定义前,用逗号分隔。所有标记均不影响 IR 控制流语义,仅向后端传递元数据。
标记 参数 含义 使用场景 标记 参数 含义 使用场景
!link("export") 符号对外可见 库的公开 API !link("export") - 符号对外可见 库的公开 API
!link("import") 符号来自外部模块 调用外部库 !link("import") - 符号来自外部模块 调用外部库
!link("weak") 弱符号 可被覆盖的默认实现 !link("weak") - 弱符号 可被覆盖的默认实现
!abi("C") 调用约定名称 指定跨函数调用的 ABI 与 C 代码交互 !abi("C") 调用约定名称 指定跨函数调用的 ABI 与 C 代码交互
!symbol("name") 字符串 自定义导出符号名 避免名称混淆 !symbol("name") 字符串 自定义导出符号名 避免名称混淆
!naked 无函数序言/尾声 中断向量、系统调用包装 !naked - 无函数序言/尾声 中断向量、系统调用包装
!noinline 禁止内联 调试或特殊性能需求 !noinline - 禁止内联 调试或特殊性能需求
!alwaysinline 总是内联 简单的包装函数 !alwaysinline - 总是内联 简单的包装函数

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/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 argparse
import hashlib import hashlib
@@ -304,13 +304,13 @@ def clean():
print(f" CLEAN {BUILD_DIR}") print(f" CLEAN {BUILD_DIR}")
def list_targets(desc): def list_targets(desc):
print("Executables (.c .o exe):") print("Executables (.c -> .o -> exe):")
for name, sources in desc.get("exe", {}).items(): for name, sources in desc.get("exe", {}).items():
print(f" {name}") print(f" {name}")
for s in sources: for s in sources:
print(f" {s}") print(f" {s}")
if desc.get("spl"): 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(): for name, info in desc["spl"].items():
pl_name = info.get("pipeline", "-") pl_name = info.get("pipeline", "-")
print(f" {name} pipeline={pl_name} src={info['src']}") print(f" {name} pipeline={pl_name} src={info['src']}")
@@ -366,7 +366,7 @@ def main():
save_cache(cache) save_cache(cache)
return rc return rc
# Pipeline: build compiler compile .spl run via runner # Pipeline: build compiler -> compile .spl -> run via runner
if args.command == "pipeline": if args.command == "pipeline":
desc = load_desc(); cache = load_cache() desc = load_desc(); cache = load_cache()
pl = desc.get("pipeline", {}).get(args.name) 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(compiler, desc, cache, False): return 1
if not build(runner, 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] sir_name = "pipeline_" + hashlib.sha256(str(src_path).encode()).hexdigest()[:8]
if not compile_spl(sir_name, args.src, compiler, desc, cache, False): if not compile_spl(sir_name, args.src, compiler, desc, cache, False):
return 1 return 1

View File

@@ -5,19 +5,19 @@ vm = [
] ]
splc0_part = [ splc0_part = [
"stage1/spl_ir.c", # "stage1/spl_ir.c",
"stage1/spl_ast.c", "stage1/spl_ast.c",
"stage1/spl_lexer.c", "stage1/spl_lexer.c",
"stage1/spl_dumptree.c", "stage1/spl_dumptree.c",
"stage1/spl_type.c", # "stage1/spl_type.c",
"stage1/spl_sema.c", # "stage1/spl_sema.c",
"stage1/spl_ast2ir.c", # "stage1/spl_builtin.c",
"stage1/spl_ir2vm.c", # "stage1/spl_ast2ir.c",
# "stage1/spl_ir2vm.c",
] ]
exe = { exe = {
"spl_cli": ["stage0/spl_cli.c"] + vm, "spl_cli": ["stage0/spl_cli.c"] + vm,
"splc_cli": ["stage1/splc_cli.c"] + vm,
"splc0": ["stage1/splc0.c"] + vm + splc0_part, "splc0": ["stage1/splc0.c"] + vm + splc0_part,
"test": ["stage0/test_spl_vm.c"] + vm, "test": ["stage0/test_spl_vm.c"] + vm,
"spl_disasm": ["stage0/spl_disasm.c"] + vm, "spl_disasm": ["stage0/spl_disasm.c"] + vm,
@@ -25,23 +25,23 @@ exe = {
pipeline = { pipeline = {
"splc0b": {"compiler": "splc0", "runner": "spl_cli"}, "splc0b": {"compiler": "splc0", "runner": "spl_cli"},
"splc0r": {"compiler": "splc0", "runner": "splc_cli"}, "splc0r": {"compiler": "splc0", "runner": "spl_cli"},
"splc0d": {"compiler": "splc0", "runner": "spl_disasm"}, "splc0d": {"compiler": "splc0", "runner": "spl_disasm"},
"splc1b": {"compiler": "splc0", "runner": "splc_cli"}, "splc1b": {"compiler": "splc0", "runner": "spl_cli"},
"splc1r": {"compiler": "splc1", "runner": "splc_cli"}, "splc1r": {"compiler": "splc1", "runner": "spl_cli"},
"splc1d": {"compiler": "splc1", "runner": "spl_disasm"}, "splc1d": {"compiler": "splc1", "runner": "spl_disasm"},
"splc2b": {"compiler": "splc1", "runner": "splc_cli"}, "splc2b": {"compiler": "splc1", "runner": "spl_cli"},
"splc2r": {"compiler": "splc2", "runner": "splc_cli"}, "splc2r": {"compiler": "splc2", "runner": "spl_cli"},
"splc2d": {"compiler": "splc2", "runner": "spl_disasm"}, "splc2d": {"compiler": "splc2", "runner": "spl_disasm"},
"splc3b": {"compiler": "splc2", "runner": "splc_cli"}, "splc3b": {"compiler": "splc2", "runner": "spl_cli"},
"splc3r": {"compiler": "splc3", "runner": "splc_cli"}, "splc3r": {"compiler": "splc3", "runner": "spl_cli"},
"splc3d": {"compiler": "splc3", "runner": "spl_disasm"}, "splc3d": {"compiler": "splc3", "runner": "spl_disasm"},
"splc4b": {"compiler": "splc3", "runner": "splc_cli"}, "splc4b": {"compiler": "splc3", "runner": "spl_cli"},
"splc4r": {"compiler": "splc4", "runner": "splc_cli"}, "splc4r": {"compiler": "splc4", "runner": "spl_cli"},
"splc4d": {"compiler": "splc4", "runner": "spl_disasm"}, "splc4d": {"compiler": "splc4", "runner": "spl_disasm"},
} }

View File

@@ -14,7 +14,7 @@
#include <stdlib.h> #include <stdlib.h>
#define log_vsnprintf vsnprintf #define log_vsnprintf vsnprintf
#define log_puts puts #define log_puts puts
#define log_abort abort #define log_abort() exit(1)
#endif #endif
#ifdef __GNUC__ // GCC, Clang #ifdef __GNUC__ // GCC, Clang

View File

@@ -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] <file.sir> [args...] * Usage: spl_cli [options] <file.sir> [args...]
* -d, --debug stack-canary checks * -d, --debug stack-canary checks

View File

@@ -1,4 +1,4 @@
/* spl_disasm.c SIR bytecode disassembler /* spl_disasm.c - SIR bytecode disassembler
* *
* Usage: spl_disasm <file.sir> * Usage: spl_disasm <file.sir>
*/ */

View File

@@ -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): * 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) * [HEADER] magic(8) nfuncs(8) ninsns(8) nnatives(8) nstrs(8) ndata(8)

View File

@@ -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, * All syscalls validate nargs, cast spl_val_t args to the expected C types,
* execute, and return the result as spl_val_t. * execute, and return the result as spl_val_t.
@@ -23,7 +23,7 @@
* Each SYSCALL_N macro: * Each SYSCALL_N macro:
* 1. Validates nargs (prints error and returns -1 on mismatch) * 1. Validates nargs (prints error and returns -1 on mismatch)
* 2. Casts args[n] from spl_val_t to the specified C type via * 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 * 3. Evaluates the expression and returns the result as spl_val_t
* ================================================================= */ * ================================================================= */
@@ -80,34 +80,34 @@
* OS syscalls * 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)) 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)) 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()) 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)) 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)) 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)) 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)) 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)) 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)) 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) { static spl_val_t vm_fsize(int nargs, spl_val_t *args) {
CHECK_NARGS("vm_fsize", 1); CHECK_NARGS("vm_fsize", 1);
FILE *f = (FILE *)(uintptr_t)args[0]; FILE *f = (FILE *)(uintptr_t)args[0];
@@ -122,7 +122,7 @@ SYSCALL_0(vm_stdin, stdin)
SYSCALL_0(vm_stdout, stdout) SYSCALL_0(vm_stdout, stdout)
SYSCALL_0(vm_stderr, stderr) 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) { static spl_val_t vm_read_file(int nargs, spl_val_t *args) {
CHECK_NARGS("vm_read_file", 1); CHECK_NARGS("vm_read_file", 1);
const char *path = (const char *)(uintptr_t)args[0]; 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; 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)) 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)) 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)) 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)) 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)) 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)) 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) { 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 * These let SPL code create isolated sub-VMs, load compiled .sir
* programs into them, push arguments, call functions, and run. * 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) { static spl_val_t vm_new(int nargs, spl_val_t *args) {
CHECK_NARGS("vm_new", 0); CHECK_NARGS("vm_new", 0);
(void)args; (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; 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) { static spl_val_t vm_drop(int nargs, spl_val_t *args) {
CHECK_NARGS("vm_drop", 1); CHECK_NARGS("vm_drop", 1);
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; 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; 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) { static spl_val_t vm_load(int nargs, spl_val_t *args) {
CHECK_NARGS("vm_load", 2); CHECK_NARGS("vm_load", 2);
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; 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; 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) { static spl_val_t vm_push(int nargs, spl_val_t *args) {
CHECK_NARGS("vm_push", 2); CHECK_NARGS("vm_push", 2);
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; 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; 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 * Args (3): vm, function_name, nargs
* The arguments should already be on the sub-VM's stack via vm_push. * 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; 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)) SYSCALL_1(vm_run, spl_vm_t *, spl_vm_run_until(a1, 0))
/* ================================================================= /* =================================================================

View File

@@ -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.) * Provides I/O native functions (putchar, getchar, file ops, etc.)
* that compiled SPL programs can call via NCALL. * that compiled SPL programs can call via NCALL.

View File

@@ -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 * Implements the spl_vm.h API with macro-based type dispatch to
* eliminate repetitive per-type switch cases. * 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 * 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) * signed and unsigned at the same bit-width)
* DIV_REM_S signed division / remainder * DIV_REM_S - signed division / remainder
* DIV_REM_U unsigned division / remainder * DIV_REM_U - unsigned division / remainder
* CMP_ALL EQ / NE (bitwise compare, also handles floats) * CMP_ALL - EQ / NE (bitwise compare, also handles floats)
* CMP_S signed ordering (<, <=, >, >=) * CMP_S - signed ordering (<, <=, >, >=)
* CMP_U unsigned ordering * CMP_U - unsigned ordering
* ================================================================ */ * ================================================================ */
#define ARITH_BINOP(OP) \ #define ARITH_BINOP(OP) \
@@ -177,7 +177,7 @@ static int spl_type_size(spl_type_t t) {
PUSH(_r); \ PUSH(_r); \
} while (0) } while (0)
/* signed division / remainder all types cast to signed */ /* signed division / remainder - all types cast to signed */
#define DIV_REM_S(OP) \ #define DIV_REM_S(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_val_t _b = POP(), _a = POP(); \
@@ -280,7 +280,7 @@ static int spl_type_size(spl_type_t t) {
PUSH(_r); \ PUSH(_r); \
} while (0) } while (0)
/* CMP_ALL equality comparisons (all types, floats via memcpy) */ /* CMP_ALL - equality comparisons (all types, floats via memcpy) */
#define CMP_ALL(OP) \ #define CMP_ALL(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_val_t _b = POP(), _a = POP(); \
@@ -334,7 +334,7 @@ static int spl_type_size(spl_type_t t) {
PUSH(_r); \ PUSH(_r); \
} while (0) } 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) \ #define CMP_S(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_val_t _b = POP(), _a = POP(); \
@@ -388,7 +388,7 @@ static int spl_type_size(spl_type_t t) {
PUSH(_r); \ PUSH(_r); \
} while (0) } 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) \ #define CMP_U(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ 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 * 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; return -1;
} }
/* 断点:即将执行的指令命中 ip 断点 暂停(返回 2 /* 断点:即将执行的指令命中 ip 断点 -> 暂停(返回 2
* skip_bp 置位时执行当前指令continue 越过当前断点)。 */ * skip_bp 置位时执行当前指令continue 越过当前断点)。 */
if (ip_breakpoint_hit(vm)) { if (ip_breakpoint_hit(vm)) {
if (vm->skip_bp) { if (vm->skip_bp) {

View File

@@ -1,4 +1,4 @@
/* spl_vm.h SIR interpreter */ /* spl_vm.h - SIR interpreter */
#ifndef __SPL_VM_H__ #ifndef __SPL_VM_H__
#define __SPL_VM_H__ #define __SPL_VM_H__

File diff suppressed because it is too large Load Diff

View File

@@ -2,31 +2,133 @@
#define __SPL_AST_H__ #define __SPL_AST_H__
#include "../stage0/include/utils.h" #include "../stage0/include/utils.h"
#include "spl_dbg.h"
#include "spl_lexer.h" #include "spl_lexer.h"
#include "spl_tok.h" #include "spl_tok.h"
typedef enum { /* clang-format off */
SPL_AST_CONTAINER_ITEM, #define SPL_AST_KIND_TABLE \
SPL_AST_FN_DECL, X(SPL_AST_NONE, V0, none) \
SPL_AST_FN_DEFINE, X(SPL_AST_CONTAINER_ITEM, V0, container_item) \
SPL_AST_TYPE_DECL, X(SPL_AST_FN_DECL, V0, fn_decl) \
SPL_AST_VAR_DECL, X(SPL_AST_FN_DEFINE, V0, fn_define) \
SPL_AST_CONST_DECL, X(SPL_AST_TYPE_DECL, V0, type_decl) \
SPL_AST_MEMBER_DECL, X(SPL_AST_VAR_DECL, V0, var_decl) \
SPL_AST__COMPTIME_STMT, /*不实现*/ X(SPL_AST_CONST_DECL, V0, const_decl) \
SPL_AST__DIRECTIVE_BLOCK, /*不实现*/ 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, /* clang-format on*/
SPL_AST_EXPR,
SPL_AST_TYPE_EXPR, typedef enum {
SPL_AST_ATTR_LIST, #ifdef X
#undef X
#endif
#define X(name, ...) name,
SPL_AST_KIND_TABLE
#undef X
SPL_AST_COUNT,
} spl_ast_node_kind_t; } spl_ast_node_kind_t;
typedef struct { const char *spl_ast_kind_name(spl_ast_node_kind_t kind);
const char *fname;
int line;
int col;
} spl_ast_loc_t;
struct spl_ast_node; struct spl_ast_node;
typedef struct spl_ast_node spl_ast_node_t; 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; typedef VEC(spl_ast_node_ref_t) spl_ast_node_ref_vec_t;
struct spl_ast_node { struct spl_ast_node {
spl_ast_node_kind_t kind; spl_ast_node_kind_t kind;
spl_ast_loc_t loc; spl_dbg_node_t dbg;
usize resolved_def_id; usize resolved_def_id;
union { union {
struct { struct {
spl_ast_node_ref_vec_t attr_list; /* attr_item */ 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 列表 */ spl_ast_node_ref_vec_t members; /* container_decl 列表 */
} container_item; } container_item;
@@ -54,7 +155,7 @@ struct spl_ast_node {
const char *name; const char *name;
spl_ast_node_ref_vec_t param_list; /* param_decl */ spl_ast_node_ref_vec_t param_list; /* param_decl */
spl_ast_node_ref_t type_expr; 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; } fn_decl;
struct { struct {
spl_ast_node_ref_vec_t attr_list; /* attr_item */ spl_ast_node_ref_vec_t attr_list; /* attr_item */
@@ -77,149 +178,60 @@ struct spl_ast_node {
const char *name; const char *name;
spl_ast_node_ref_t type_expr; spl_ast_node_ref_t type_expr;
spl_ast_node_ref_t expr; spl_ast_node_ref_t expr;
} var_decl; } var_const_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;
/* 语句数据kind 决定解释哪个成员 */
struct { struct {
enum { spl_ast_node_ref_t expr;
SPL_AST_IF_STATEMENT, spl_ast_node_ref_vec_t if_block; /* 语句 */
SPL_AST_IFVAR_STATEMENT, spl_ast_node_ref_vec_t else_block; /* 语句 */
SPL_AST_WHILE_STATEMENT, } if_statement;
SPL_AST_LOOP_STATEMENT, struct {
SPL_AST_FOR_STATEMENT, spl_ast_node_ref_t packed_expr;
SPL_AST_MATCH_STATEMENT, spl_ast_node_ref_vec_t if_block; /* 语句 */
SPL_AST_RET_STATEMENT, spl_ast_node_ref_vec_t else_block; /* 语句 */
SPL_AST_BREAK_STATEMENT, } ifvar_statement;
SPL_AST_CONTINUE_STATEMENT, struct {
SPL_AST_DEFER_STATEMENT, spl_ast_node_ref_t expr;
SPL_AST_VARDECL, spl_ast_node_ref_vec_t while_block; /* 语句 */
SPL_AST_CONSTDECL, } while_statement;
SPL_AST_TYPEDECL, struct {
SPL_AST_EXPR_STATEMENT, spl_ast_node_ref_vec_t loop_block; /* 语句 */
} kind; } loop_statement;
union { struct {
struct { spl_ast_node_ref_vec_t expr_vec;
spl_ast_node_ref_t expr; VEC(char *) ident_vec;
spl_ast_node_ref_vec_t if_block; /* block_item */ spl_ast_node_ref_vec_t block; /* 语句 */
spl_ast_node_ref_vec_t else_block; /* block_item */ } for_statement;
} if_statement; struct {
struct { spl_ast_node_ref_t expr;
spl_ast_node_ref_t packed_expr; spl_ast_node_ref_vec_t paced_exprs; /* packed_expr */
spl_ast_node_ref_vec_t if_block; /* block_item */ spl_ast_node_ref_vec_t match_block; /* 语句 */
spl_ast_node_ref_vec_t else_block; /* block_item */ } match_statement;
} ifvar_statement; struct {
struct { spl_ast_node_ref_t expr;
spl_ast_node_ref_t expr; } ret_statement;
spl_ast_node_ref_vec_t while_block; /* block_item */ struct {
} while_statement; } break_statement;
struct { struct {
spl_ast_node_ref_vec_t loop_block; /* block_item */ } continue_statement;
} loop_statement; struct {
struct { spl_ast_node_ref_vec_t block_or_statement; /* 语句 */
spl_ast_node_ref_vec_t expr_vec; } defer_statement;
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;
struct { struct {
const char *ident; const char *ident;
const char *bind_ident; const char *bind_ident;
spl_ast_node_ref_t expr; spl_ast_node_ref_t expr;
} packed_expr; } packed_expr;
struct { struct {
enum { spl_ast_node_ref_t left;
SPL_AST_ASSIGN_EXPR, spl_ast_node_ref_t right;
SPL_AST_ASSIGN_ADD_EXPR, } op_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;
struct { 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; spl_ast_node_ref_t postfix_expr;
} prefix_expr; } prefix_expr;
struct { 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; spl_ast_node_ref_t primary_expr;
union { union {
spl_ast_node_ref_vec_t call_expr; spl_ast_node_ref_vec_t call_expr;
@@ -232,66 +244,53 @@ struct spl_ast_node {
spl_ast_node_ref_t type_expr; spl_ast_node_ref_t type_expr;
}; };
} postfix_expr; } postfix_expr;
struct { struct {
enum { isize integer_expr;
SPL_AST_INTEGER, double float_expr;
SPL_AST_FLOAT, char char_lit_expr;
SPL_AST_CHAR_LIT, const char *string_lit_expr; /* parsed c string */
SPL_AST_STRING_LIT, const char *ident;
SPL_AST_TRUE,
SPL_AST_FALSE, struct {
SPL_AST_NULL, const char *name;
SPL_AST_IDENT, spl_ast_node_ref_vec_t expr; /* aggregate_init_item */
SPL_AST_ARGGREGATE_INIT, } aggregate_init;
SPL_AST_EXPR_EXPR,
SPL_AST_ARRAY_LIT, spl_ast_node_ref_t expr;
SPL_AST_BUILTIN_EXPR, struct {
SPL_AST_BLOCK_EXPR, isize integer;
} kind; spl_ast_node_ref_t type_expr;
union { spl_ast_node_ref_vec_t expr_list;
isize integer_expr; } array_lit_expr;
double float_expr; struct {
char char_lit_expr;
const char *string_lit_expr; /* parsed c string */
const char *ident; const char *ident;
spl_ast_node_ref_vec_t expr_list;
struct { } builtin_expr;
const char *name; spl_ast_node_ref_vec_t block_expr; /* 语句 */
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 */
};
} primary_expr; } primary_expr;
struct { struct {
const char *ident; const char *ident;
spl_ast_node_ref_t expr; spl_ast_node_ref_t expr;
} aggregate_init_item; } aggregate_init_item;
struct { struct {
spl_ast_node_ref_vec_t type_prefixs; /* prefix_type */ spl_ast_node_ref_vec_t attr_list; /* attr_item */
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;
union { 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 { struct {
spl_ast_node_ref_vec_t param_list; /* param_decl */ spl_ast_node_ref_vec_t param_list; /* param_decl */
spl_ast_node_ref_t type_expr; 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 */ spl_ast_node_ref_vec_t aggregate_list; /* container_decl */
}; };
} type_expr; } 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(spl_ast_node_t) spl_ast_node_vec_t;
typedef VEC(char*)spl_ast_cstr_ref_vec_t;
typedef struct { typedef struct {
int parsed; int parsed;
spl_tok_vec_t input; 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_node_ref_t root;
} spl_ast_t; } spl_ast_t;

17
stage1/spl_dbg.h Normal file
View File

@@ -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 : "<null>"), \
((tok) ? (tok)->line : 0), ((tok) ? (tok)->col : 0), ##__VA_ARGS__)
#endif /* __SPL_DBG_H__ */

View File

@@ -2,8 +2,10 @@
#define __SPL_IR_H__ #define __SPL_IR_H__
#include "../stage0/include/utils.h" #include "../stage0/include/utils.h"
#include "spl_dbg.h"
#include "spl_type.h" #include "spl_type.h"
/* clang-format off */ /* clang-format off */
#define SPL_IR_FN_TABLE \ #define SPL_IR_FN_TABLE \
X(arith.add, V0, SPL_IR_ARITH_ADD) \ X(arith.add, V0, SPL_IR_ARITH_ADD) \
@@ -91,7 +93,7 @@ typedef usize spl_ir_func_ref_t; /* 0 is error */
typedef struct { typedef struct {
spl_ir_kind_t kind; spl_ir_kind_t kind;
usize src_ref; /* AST 节点 ref调试行号用ast2ir 注解) */ spl_dbg_node_t dbg;
union { union {
struct { struct {
spl_type_id_t tid; spl_type_id_t tid;
@@ -238,24 +240,12 @@ typedef struct {
} spl_ir_attr_t; } spl_ir_attr_t;
typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_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 { typedef struct {
const char *name; const char *name;
spl_ir_attr_t attr; spl_ir_attr_t attr;
spl_type_id_t fn_tid; spl_type_id_t fn_tid;
spl_ir_node_vec_t nodes; spl_ir_node_vec_t nodes;
spl_ir_node_ref_vec_t labels; spl_ir_node_ref_vec_t labels;
spl_ir_dbg_var_vec_t dbg_vars; /* 调试变量表fp 偏移在 ir2vm 填) */
} spl_ir_func_t; } spl_ir_func_t;
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t; typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;

0
stage1/spl_layout.c Normal file
View File

0
stage1/spl_layout.h Normal file
View File

View File

@@ -1,4 +1,4 @@
/* spl_lexer.c SPL lexical analyzer */ /* spl_lexer.c - SPL lexical analyzer */
#include "spl_lexer.h" #include "spl_lexer.h"
#include "spl_tok.h" #include "spl_tok.h"
@@ -21,7 +21,7 @@ static spl_tok_type_t keyword_type(const char *ident, usize len) {
return TOK_IDENT; 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, * advances *s past the escape sequence, returns 0 on success,
* non-zero on error. */ * non-zero on error. */
int spl_decode_escape(const char **s, char *out) { 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; const char *start = source + offset;
char c = *start; 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') { if (c == ' ' || c == '\t' || c == '\r') {
offset++; offset++;
col++; col++;

View File

@@ -1,4 +1,4 @@
/* spl_lexer.h 独立词法分析器 */ /* spl_lexer.h - 独立词法分析器 */
#ifndef __SPL_LEXER_H__ #ifndef __SPL_LEXER_H__
#define __SPL_LEXER_H__ #define __SPL_LEXER_H__

View File

@@ -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__ #ifndef __SPL_TOK_H__
#define __SPL_TOK_H__ #define __SPL_TOK_H__
@@ -6,31 +6,36 @@
/* clang-format off */ /* clang-format off */
#define KEYWORD_TABLE \ #define KEYWORD_TABLE \
X(as , KW_AS , SPL_V0) \ X(as , KW_AS , SPL_V0) \
X(bool , KW_BOOL , SPL_V0) \ X(bool , KW_BOOL , SPL_V0) \
X(break , KW_BREAK , SPL_V0) \ X(break , KW_BREAK , SPL_V0) \
X(comptime , KW_COMPTIME , SPL_V0) \ X(catch , KW_CATCH , SPL_V0) \
X(const , KW_CONST , SPL_V0) \ X(comptime , KW_COMPTIME , SPL_V0) \
X(continue , KW_CONTINUE , SPL_V0) \ X(const , KW_CONST , SPL_V0) \
X(defer , KW_DEFER , SPL_V0) \ X(continue , KW_CONTINUE , SPL_V0) \
X(else , KW_ELSE , SPL_V0) \ X(defer , KW_DEFER , SPL_V0) \
X(enum , KW_ENUM , SPL_V0) \ X(else , KW_ELSE , SPL_V0) \
X(false , KW_FALSE , SPL_V0) \ X(enum , KW_ENUM , SPL_V0) \
X(fn , KW_FN , SPL_V0) \ X(errdefer , KW_ERRDEFER , SPL_V0) \
X(for , KW_FOR , SPL_V0) \ X(false , KW_FALSE , SPL_V0) \
X(if , KW_IF , SPL_V0) \ X(fn , KW_FN , SPL_V0) \
X(loop , KW_LOOP , SPL_V0) \ X(for , KW_FOR , SPL_V0) \
X(match , KW_MATCH , SPL_V0) \ X(if , KW_IF , SPL_V0) \
X(null , KW_NULL , SPL_V0) \ X(loop , KW_LOOP , SPL_V0) \
X(ret , KW_RET , SPL_V0) \ X(match , KW_MATCH , SPL_V0) \
X(struct , KW_STRUCT , SPL_V0) \ X(null , KW_NULL , SPL_V0) \
X(true , KW_TRUE , SPL_V0) \ X(ret , KW_RET , SPL_V0) \
X(type , KW_TYPE , SPL_V0) \ X(shape , WK_SHAPE , SPL_V0) \
X(union , KW_UNION , SPL_V0) \ X(struct , KW_STRUCT , SPL_V0) \
X(var , KW_VAR , SPL_V0) \ X(true , KW_TRUE , SPL_V0) \
X(void , KW_VOID , SPL_V0) \ X(try , KW_TRY , SPL_V0) \
X(while , KW_WHILE , SPL_V0) \ X(type , KW_TYPE , SPL_V0) \
X(_ , KW_ANY , 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 // KEYWORD_TABLE
#define TOKEN_TABLE \ #define TOKEN_TABLE \

View File

@@ -58,7 +58,6 @@ typedef struct {
spl_def_id_t def_id; spl_def_id_t def_id;
spl_type_id_t type_id; spl_type_id_t type_id;
usize scope_id; usize scope_id;
int is_const; /* var_def 是否为 const 声明(只读) */
} spl_var_def_t; } spl_var_def_t;
typedef VEC(spl_var_def_t) spl_var_def_vec_t; typedef VEC(spl_var_def_t) spl_var_def_vec_t;

View File

@@ -1,4 +1,4 @@
/* splc0.c SPL compiler CLI (stage 1, 引导用) /* splc0.c - SPL compiler CLI (stage 1, 引导用)
* *
* splc0 --dump tokens|ast|all <file> dump 前端产物 * splc0 --dump tokens|ast|all <file> dump 前端产物
* splc0 <in> <out> 编译 (阶段 B 实现) * splc0 <in> <out> 编译 (阶段 B 实现)
@@ -73,79 +73,79 @@ static void dump_ast(const char *src, const char *fname) {
spl_ast_drop(&ast); spl_ast_drop(&ast);
} }
static void dump_sema(const char *src, const char *fname) { // static void dump_sema(const char *src, const char *fname) {
spl_tok_vec_t toks = spl_lex(src, fname); // spl_tok_vec_t toks = spl_lex(src, fname);
spl_ast_t ast; // spl_ast_t ast;
spl_ast_init(&ast, &toks); // spl_ast_init(&ast, &toks);
spl_ast_prase(&ast); // spl_ast_prase(&ast);
if (ast.parsed < 0) { // if (ast.parsed < 0) {
printf("parse failed, skip sema dump\n"); // printf("parse failed, skip sema dump\n");
spl_ast_drop(&ast); // spl_ast_drop(&ast);
return; // return;
} // }
spl_ast_valid(&ast); // spl_ast_valid(&ast);
spl_sema_t sema; // spl_sema_t sema;
spl_sema_init(&sema); // spl_sema_init(&sema);
sema.ast = &ast; // sema.ast = &ast;
spl_sema_run(&sema); // spl_sema_run(&sema);
spl_sema_check(&sema); // spl_sema_check(&sema);
printf("Sema root_scope=%zu scopes=%zu errors=%d\n", sema.root_scope, sema.scopes.size, // printf("Sema root_scope=%zu scopes=%zu errors=%d\n", sema.root_scope, sema.scopes.size,
sema.error_count); // sema.error_count);
for (usize i = 0; i < sema.scopes.size; i++) { // for (usize i = 0; i < sema.scopes.size; i++) {
printf("scope[%zu] parent=%zu\n", i, sema.scopes.data[i].parent); // printf("scope[%zu] parent=%zu\n", i, sema.scopes.data[i].parent);
map_for(sema.scopes.data[i].symbols, mi) { // map_for(sema.scopes.data[i].symbols, mi) {
printf(" %s -> def#%zu\n", sema.scopes.data[i].symbols.data[mi].key, // printf(" %s -> def#%zu\n", sema.scopes.data[i].symbols.data[mi].key,
sema.scopes.data[i].symbols.data[mi].val); // sema.scopes.data[i].symbols.data[mi].val);
} // }
} // }
printf("TypeTable:\n"); // printf("TypeTable:\n");
for (usize i = 0; i < sema.type.type_table.size; i++) { // for (usize i = 0; i < sema.type.type_table.size; i++) {
printf(" id#%zu type=", i); // printf(" id#%zu type=", i);
spl_type_pure_dump(&sema.type, i); // spl_type_pure_dump(&sema.type, i);
printf("\n"); // printf("\n");
} // }
printf("DefTable:\n"); // printf("DefTable:\n");
for (usize i = 0; i < sema.type.def_table.size; i++) { // for (usize i = 0; i < sema.type.def_table.size; i++) {
printf(" def#%zu ", i); // printf(" def#%zu ", i);
spl_type_def_dump(&sema.type, i); // spl_type_def_dump(&sema.type, i);
printf("\n"); // printf("\n");
} // }
spl_sema_drop(&sema); // spl_sema_drop(&sema);
spl_ast_drop(&ast); // spl_ast_drop(&ast);
} // }
static void dump_ir(const char *src, const char *fname) { // static void dump_ir(const char *src, const char *fname) {
spl_tok_vec_t toks = spl_lex(src, fname); // spl_tok_vec_t toks = spl_lex(src, fname);
spl_ast_t ast; // spl_ast_t ast;
spl_ast_init(&ast, &toks); // spl_ast_init(&ast, &toks);
spl_ast_prase(&ast); // spl_ast_prase(&ast);
if (ast.parsed < 0) { // if (ast.parsed < 0) {
printf("parse failed, skip IR\n"); // printf("parse failed, skip IR\n");
spl_ast_drop(&ast); // spl_ast_drop(&ast);
return; // return;
} // }
spl_ast_valid(&ast); // spl_ast_valid(&ast);
spl_sema_t sema; // spl_sema_t sema;
spl_sema_init(&sema); // spl_sema_init(&sema);
sema.ast = &ast; // sema.ast = &ast;
spl_sema_run(&sema); // spl_sema_run(&sema);
spl_sema_check(&sema); // spl_sema_check(&sema);
if (sema.error_count) { // if (sema.error_count) {
printf("sema errors=%d, skip IR\n", sema.error_count); // printf("sema errors=%d, skip IR\n", sema.error_count);
spl_sema_drop(&sema); // spl_sema_drop(&sema);
spl_ast_drop(&ast); // spl_ast_drop(&ast);
return; // return;
} // }
spl_ast2ir_t a2ir; // spl_ast2ir_t a2ir;
spl_ast2ir_init(&a2ir, &sema); // spl_ast2ir_init(&a2ir, &sema);
spl_ast2ir_run(&a2ir); // spl_ast2ir_run(&a2ir);
if (a2ir.err_count) // if (a2ir.err_count)
printf("ast2ir errors=%d\n", a2ir.err_count); // printf("ast2ir errors=%d\n", a2ir.err_count);
spl_ir_dump(&a2ir.ir, &sema.type); // spl_ir_dump(&a2ir.ir, &sema.type);
spl_ast2ir_drop(&a2ir); // spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema); // spl_sema_drop(&sema);
spl_ast_drop(&ast); // spl_ast_drop(&ast);
} // }
static int cmd_dump(const char *flags, const char *path) { static int cmd_dump(const char *flags, const char *path) {
long len; long len;
@@ -160,25 +160,14 @@ static int cmd_dump(const char *flags, const char *path) {
dump_tokens(src, path); dump_tokens(src, path);
if (do_ast) if (do_ast)
dump_ast(src, path); dump_ast(src, path);
if (do_sema) // if (do_sema)
dump_sema(src, path); // dump_sema(src, path);
if (do_ir) // if (do_ir)
dump_ir(src, path); // dump_ir(src, path);
free(src); free(src);
return 0; 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 读取 */ /* -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, static void gen_debug_map(const char *outpath, spl_ast_t *ast, const spl_ir_t *ir,
const spl_ir2vm_t *ir2vm) { 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) if (!f)
return; return;
fprintf(f, "SPLDBG\n"); fprintf(f, "SPLDBG\n");
for (usize i = 0; i < ir2vm->fdbg.size; i++) { // for (usize i = 0; i < ir2vm->fdbg.size; i++) {
const spl_ir2vm_fdbg_t *fd = &ir2vm->fdbg.data[i]; // const spl_ir2vm_fdbg_t *fd = &ir2vm->fdbg.data[i];
if (fd->fid >= ir->funcs.size) // if (fd->fid >= ir->funcs.size)
continue; // continue;
const spl_ir_func_t *fn = &ir->funcs.data[fd->fid]; // const spl_ir_func_t *fn = &ir->funcs.data[fd->fid];
const char *fname = fn->name ? fn->name : "?"; // const char *fname = fn->name ? fn->name : "?";
for (usize ref = 1; ref < fd->node_first_ip.size; ref++) { // for (usize ref = 1; ref < fd->node_first_ip.size; ref++) {
usize ip = fd->node_first_ip.data[ref]; // usize ip = fd->node_first_ip.data[ref];
if (ip == (usize)-1) // if (ip == (usize)-1)
continue; // continue;
const spl_ir_node_t *n = &fn->nodes.data[ref]; // 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), // fprintf(f, "IR %zu %zu %d %s\n", ip, ref, ast_line(ast, n->src_ref),
spl_ir_kind_name(n->kind)); // spl_ir_kind_name(n->kind));
} // }
for (usize j = 0; j < fn->dbg_vars.size; j++) { // for (usize j = 0; j < fn->dbg_vars.size; j++) {
const spl_ir_dbg_var_t *dv = &fn->dbg_vars.data[j]; // const spl_ir_dbg_var_t *dv = &fn->dbg_vars.data[j];
if (!dv->name) // if (!dv->name)
continue; // continue;
fprintf(f, "VAR %s %s %zu %zu %d\n", fname, dv->name, dv->offset, dv->tid, // fprintf(f, "VAR %s %s %zu %zu %d\n", fname, dv->name, dv->offset, dv->tid,
dv->is_param); // dv->is_param);
} // }
} // }
fclose(f); fclose(f);
} }
static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug) { 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_tok_vec_t toks = spl_lex(src, fname);
spl_ast_t ast; // spl_ast_t ast;
spl_ast_init(&ast, &toks); // spl_ast_init(&ast, &toks);
spl_ast_prase(&ast); // spl_ast_prase(&ast);
if (ast.parsed < 0) { // if (ast.parsed < 0) {
printf("parse failed, no output\n"); // printf("parse failed, no output\n");
spl_ast_drop(&ast); // spl_ast_drop(&ast);
return 1; // return 1;
} // }
spl_ast_valid(&ast); // spl_ast_valid(&ast);
spl_sema_t sema; // spl_sema_t sema;
spl_sema_init(&sema); // spl_sema_init(&sema);
sema.ast = &ast; // sema.ast = &ast;
spl_sema_run(&sema); // spl_sema_run(&sema);
spl_sema_check(&sema); // spl_sema_check(&sema);
if (sema.error_count) { // if (sema.error_count) {
printf("sema errors=%d, no output\n", sema.error_count); // printf("sema errors=%d, no output\n", sema.error_count);
spl_sema_drop(&sema); // spl_sema_drop(&sema);
spl_ast_drop(&ast); // spl_ast_drop(&ast);
return 1; // return 1;
} // }
spl_ast2ir_t a2ir; // spl_ast2ir_t a2ir;
spl_ast2ir_init(&a2ir, &sema); // spl_ast2ir_init(&a2ir, &sema);
spl_ast2ir_run(&a2ir); // spl_ast2ir_run(&a2ir);
if (a2ir.err_count) { // if (a2ir.err_count) {
printf("ast2ir errors=%d, no output\n", a2ir.err_count); // printf("ast2ir errors=%d, no output\n", a2ir.err_count);
spl_ast2ir_drop(&a2ir); // spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema); // spl_sema_drop(&sema);
spl_ast_drop(&ast); // spl_ast_drop(&ast);
return 1; // return 1;
} // }
spl_ir2vm_t ir2vm; // spl_ir2vm_t ir2vm;
spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type); // spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type);
int rc = spl_ir2vm_run(&ir2vm, outpath); // int rc = spl_ir2vm_run(&ir2vm, outpath);
if (gen_debug && rc == 0) // if (gen_debug && rc == 0)
gen_debug_map(outpath, &ast, &a2ir.ir, &ir2vm); // gen_debug_map(outpath, &ast, &a2ir.ir, &ir2vm);
spl_ir2vm_drop(&ir2vm); // spl_ir2vm_drop(&ir2vm);
spl_ast2ir_drop(&a2ir); // spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema); // spl_sema_drop(&sema);
spl_ast_drop(&ast); // spl_ast_drop(&ast);
return rc ? 1 : 0; // return rc ? 1 : 0;
return 0;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {