stage1 完成ast 定义sema

This commit is contained in:
zzy
2026-08-03 12:39:28 +08:00
parent a4ec5656d2
commit 74d7376039
19 changed files with 3857 additions and 137 deletions

8
.gitignore vendored
View File

@@ -2,3 +2,11 @@
!.gitignore
build/
*.sir
*.o
*.obj
*.exe
*.out

154
SPL.md
View File

@@ -6,8 +6,8 @@ SPL是一个从零构建的自举编译器项目。引导链:
```
stage0/spl_vm.c — SIR 虚拟机 (C 语言实现)
stage1/splc0.c — SPLSIR 编译器 (C 语言实现,引导用)
stage1/splc1.spl — SPLSIR 编译器 (SPL 语言实现,自举第一版)
stage1/splc0.c — SPL->SIR 编译器 (C 语言实现,引导用)
stage1/splc1.spl — SPL->SIR 编译器 (SPL 语言实现,自举第一版)
...将来...
```
@@ -84,25 +84,45 @@ ParamDecl
# ================================================================
TypeDecl
<- KEYWORD_type IDENTIFIER EQUAL TypeBody (* @packed type Vec = struct { ... } *)
<- KEYWORD_type IDENTIFIER EQUAL TypeExpr (* @packed type Vec = struct { ... } *)
TypeBody
<- KEYWORD_struct LBRACE AggregateBody RBRACE
/ KEYWORD_union LBRACE AggregateBody RBRACE
/ KEYWORD_enum LBRACE AggregateBody RBRACE
/ TypeExpr (* 别名 *)
MemberDecl
<- IDENTIFIER (COLON TypeExpr)? (COMMA / SEMICOLON)?
AggregateBody <- AggregateItem*
# ================================================================
# 类型表达式 (Type Expression, LL(1), 无左递归)
# ================================================================
AggregateItem
<- ContainerDeclaration
TypeExpr <- PrefixTypeOp* AttrList? TypeBase
TypeBase
<- FnTypeExpr
/ TypePath
/ KEYWORD_struct LBRACE ContainerDeclaration* RBRACE
/ KEYWORD_union LBRACE ContainerDeclaration* RBRACE
/ KEYWORD_enum LBRACE ContainerDeclaration* RBRACE
(* struct: 字段, 必须 IDENTIFIER : TypeExpr (语义层检查)
union: 联合体字段, 同上
enum: 变体, IDENTIFIER : TypeExpr 或 纯 IDENTIFIER (朴素变体) *)
MemberDecl
<- IDENTIFIER (COLON TypeExpr)? (COMMA / SEMICOLON)?
PrefixTypeOp (* LL(1): * / [ *)
<- ASTERISK
/ LBRACKET (RBRACKET / INTEGER RBRACKET) (* [] 或 [N] *)
FnTypeExpr <- KEYWORD_fn LPAREN TypeExprList? RPAREN TypeExpr
TypeExprList <- (TypeExpr COMMA)* TypeExpr?
TypePath <- TypeAtom (DOT TypeAtom)*
TypeAtom (* LL(1): 关键词 / IDENTIFIER / _ *)
<- KEYWORD_void / KEYWORD_bool
/ KEYWORD_i8 / KEYWORD_u8 / KEYWORD_i16 / KEYWORD_u16
/ KEYWORD_i32 / KEYWORD_u32 / KEYWORD_i64 / KEYWORD_u64
/ KEYWORD_isize / KEYWORD_usize
/ KEYWORD_f32 / KEYWORD_f64 / KEYWORD_ptr
/ UNDERSCORE
/ IDENTIFIER
# ================================================================
# 变量 / 常量
@@ -140,6 +160,7 @@ Statement (* LL(1): 14 分支互
/ ContinueStatement
/ DeferStatement
/ VarDecl
/ ConstDecl
/ TypeDecl
/ ExprStatement
@@ -175,12 +196,12 @@ ForStatement
MatchStatement <- KEYWORD_match Expr LBRACE MatchArm* RBRACE
MatchArm
<- MatchPat FAT_R_ARROW Statement
/ UNDERSCORE FAT_R_ARROW Statement
<- MatchPat (COMMA MatchPat)* FAT_R_ARROW Block
MatchPat (* LL(1): . / _ / Expr *)
<- DOT IDENTIFIER (LBRACKET IDENTIFIER RBRACKET)? (* 仅允许 .Item 或 .Item[bind] *)
/ Expr (* 字面量或变量常量 *)
/ UNDERSCORE
# ---- 跳转 ----
@@ -221,7 +242,7 @@ PrefixOp <- MINUS / BANG / TILDE / AMPERSAND / ASTERISK
PostfixExpr
<- PrimaryExpr
( LPAREN ExprList RPAREN (* 函数调用 *)
/ DOT IDENTIFIER (* 字段/方法 *)
/ DOT IDENTIFIER (* 字段 *)
/ DOT ASTERISK (* 解引用 *)
/ LBRACKET Expr RBRACKET (* 索引 *)
/ LBRACKET Expr DOT2 Expr? RBRACKET (* 切片 *)
@@ -240,6 +261,7 @@ PrimaryExpr
/ STRING_LITERAL
/ TRUE / FALSE / NULL_KW
/ IDENTIFIER (LBRACE StructInitList? RBRACE)? (* 变量引用 / 结构体字面量 *)
/ DOT LBRACE StructInitList? RBRACE (* 匿名聚合字面量 .{ .f = e } *)
/ LPAREN Expr RPAREN
/ ArrayLiteral
/ BuiltinExpr
@@ -254,38 +276,6 @@ StructInit <- DOT IDENTIFIER (EQUAL Expr)?
BuiltinExpr
<- (AT / SHARP) IDENTIFIER LPAREN ExprList? RPAREN (* @sizeof(T) / #runtime(x) *)
# ================================================================
# 类型表达式 (Type Expression, LL(1), 无左递归)
# ================================================================
TypeExpr <- PrefixTypeOp* TypeBase
TypeBase <- FnTypeExpr / TypePath
PrefixTypeOp (* LL(1): * / [ *)
<- ASTERISK
/ LBRACKET (RBRACKET / INTEGER RBRACKET) (* [] 或 [N] *)
FnTypeExpr <- KEYWORD_fn LPAREN TypeExprList? RPAREN TypeExpr
TypeExprList <- (TypeExpr COMMA)* TypeExpr?
TypePath <- TypeAtom (DOT TypeAtom)*
TypeAtom (* LL(1): 关键词 / IDENTIFIER / _ *)
<- KEYWORD_void / KEYWORD_bool
/ KEYWORD_i8 / KEYWORD_u8 / KEYWORD_i16 / KEYWORD_u16
/ KEYWORD_i32 / KEYWORD_u32 / KEYWORD_i64 / KEYWORD_u64
/ KEYWORD_isize / KEYWORD_usize
/ KEYWORD_f32 / KEYWORD_f64 / KEYWORD_ptr
/ UNDERSCORE
/ IDENTIFIER
(* *_ = "any pointer", 唯一支持自动类型提升和隐式转换的指针类型。
语义上 *_ 可赋值给任意 *T, 任意 *T 可赋值给 *_。
# ================================================================
# 运算符
# ================================================================
@@ -324,6 +314,11 @@ KEYWORD_enum <- 'enum' !IDENTIFIER_CHAR
KEYWORD_comptime <- 'comptime' !IDENTIFIER_CHAR
KEYWORD_void <- 'void' !IDENTIFIER_CHAR
KEYWORD_bool <- 'bool' !IDENTIFIER_CHAR
KEYWORD_isize <- 'isize' !IDENTIFIER_CHAR
KEYWORD_usize <- 'usize' !IDENTIFIER_CHAR
KEYWORD_ptr <- 'ptr' !IDENTIFIER_CHAR
(* desperate 未来采用 ixx uxx fxx 表达而非关键字,启动阶段使用固定关键字 *)
KEYWORD_i8 <- 'i8' !IDENTIFIER_CHAR
KEYWORD_u8 <- 'u8' !IDENTIFIER_CHAR
KEYWORD_i16 <- 'i16' !IDENTIFIER_CHAR
@@ -332,11 +327,8 @@ KEYWORD_i32 <- 'i32' !IDENTIFIER_CHAR
KEYWORD_u32 <- 'u32' !IDENTIFIER_CHAR
KEYWORD_i64 <- 'i64' !IDENTIFIER_CHAR
KEYWORD_u64 <- 'u64' !IDENTIFIER_CHAR
KEYWORD_isize <- 'isize' !IDENTIFIER_CHAR
KEYWORD_usize <- 'usize' !IDENTIFIER_CHAR
KEYWORD_f32 <- 'f32' !IDENTIFIER_CHAR
KEYWORD_f64 <- 'f64' !IDENTIFIER_CHAR
KEYWORD_ptr <- 'ptr' !IDENTIFIER_CHAR
TRUE <- 'true' !IDENTIFIER_CHAR
FALSE <- 'false' !IDENTIFIER_CHAR
@@ -355,7 +347,7 @@ COLON <- ':' DOT <- '.'
DOT2 <- '..' DOT3 <- '...'
AT <- '@' SHARP <- '#'
FAT_R_ARROW <- '=>' FAT_D_ARROW <- '<=>'
R_ARROW <- '<-' L_ARROW <- '->' D_ARROW '<->'
THIN_R_ARROW <- '<-' THIN_L_ARROW <- '->' THIN_D_ARROW '<->'
EQUAL <- '='
COLON_ASSIGN <- ':='
@@ -407,6 +399,18 @@ BLOCK_COMMENT <- '/*' (!'*/' .)* '*/'
eof <- !.
```
## TODO
```spl
// 约束关键字,语义是`类型子集形状`
type name = shape { ... }
// 默认字段
type name = struct { x: i32 = 0, }
// 默认参数
fn name(x: i32 = 0) { ... }
```
# SPL 语义规范
## 设计总则
@@ -442,15 +446,16 @@ DirectiveBlock @id { } / #id { } 为扩展占位,无预定义行为。未识
语义: 完全由语言版本或库注册决定。当前所有均视为未识别,产生警告 (宽松) 或错误 (严格)。
## 函数
text
AttrList? fn IDENTIFIER ( ParamDeclList ) TypeExpr? ( ; | Block )
参数: 全部不可变。需要可变时通过 *T 传递。
返回类型: 省略即 void。仅有 ; 表示外部声明。
调用: 实参与形参数量、类型必须完全匹配 (无隐式可变参数)。
执行: 新作用域 形参绑定实参 执行 Block 遇 ret expr 返回 (类型匹配),或 void 函数自然结束返回。
执行: 新作用域 -> 形参绑定实参 -> 执行 Block -> 遇 ret expr 返回 (类型匹配),或 void 函数自然结束返回。
## 类型声明与聚合体
### 别名
@@ -573,7 +578,7 @@ defer { ... }: 退出作用域时以后进先出执行。
浮点 f64布尔 bool。
null ?T 隐式转换。
null -> ?T 隐式转换。
### 运算符
算术/位运算: 操作数类型必须完全一致或由字面量推导,无隐式提升。
@@ -587,12 +592,12 @@ null → ?T 隐式转换。
- 数值 同类型
! bool bool
~ 整数 同类型
& 可寻址左值 *T
解引用仅有后缀形式 .*,无前缀 * 运算符。(*ptr) 不合法。
& 可寻址左值 \*T
解引用仅有后缀形式 .\*,无前缀 \* 运算符。(\*ptr) 不合法。
后缀运算符
运算 约束 说明
expr.* expr 为 *T 解引用,得 T 左值
expr.\* expr 为 \*T 解引用,得 T 左值
expr.field struct 或指针 指针时自动解引用一层再取字段
expr[i] 数组/切片/指针i 整数 元素左值
expr[a..b] 数组/切片/指针 切片操作,产生 []T内部设置 ptr 和 len
@@ -618,9 +623,9 @@ comptime { ... } / comptime expr;: 编译时求值,不可引用运行时变量
*_ 的特殊规则:
*T *_: 允许,必须警告。
*T -> *_: 允许,必须警告。
*_ *T: 允许,必须警告。
*_ -> *T: 允许,必须警告。
这些警告无法全局关闭,未来提供显式抑制。
@@ -628,7 +633,7 @@ comptime { ... } / comptime expr;: 编译时求值,不可引用运行时变量
整数字面量适配更大类型。
null ?T。
null -> ?T。
其余必须显式 as。
@@ -740,7 +745,7 @@ fn(参数类型列表) 返回类型
null 字面量只能出现在需要 ?T 的上下文中。
### 自定义聚合类型
### 聚合类型
struct: 字段连续排列 (可能有对齐填充),每个字段有自己的类型。赋值是逐字段拷贝。
union: 所有字段共享起始地址,大小等于最大字段 (加上对齐)。直接字段读取被视为不安全,需通过 match 解构。
@@ -750,16 +755,7 @@ enum: 带标签的联合体,每个变体可有载荷。大小实现定义,
## 类型分类
### 值类型 (复制语义)
所有基本标量类型,或者说底层寄存器类型 (整数、浮点、bool)
struct
数组 [N]T
切片 []T
区间 Range
赋值、传参会复制整个值。修改副本不影响原值。
`聚合类型` `数组 [N]T` `切片[]T` `区间Range` 赋值、传参会复制整个值。修改副本不影响原值。
### 引用/指针类型
\*T、\*_
@@ -802,15 +798,15 @@ bool 整数 否 —
以下用伪代码描述每个表达式类型的推断方法。若类型检查失败,则为编译错误。
### 字面量
INTEGER i32
INTEGER -> i32
FLOAT f64
FLOAT -> f64
true / false bool
true / false -> bool
null 必须从上下文推导出 ?T无法推导则报错。
null -> 必须从上下文推导出 ?T无法推导则报错。
字符串字面量 []u8 (具体待定)
字符串字面量 -> []u8 (具体待定)
### 二元运算
算术 e1 + e2、-、*、/、%:
@@ -953,8 +949,8 @@ ForRange 提供表达式列表 [E1, E2, ...]。as 后标识符列表 [v1, v2, ..
```
for my_slice, 0.. as elem, idx { ... }
// my_slice: []T elem: T
// 0..: Range 无界 idx: i64长度由 my_slice 决定
// my_slice: []T -> elem: T
// 0..: Range 无界 -> idx: i64长度由 my_slice 决定
```
## 类型系统限制
无隐式类型提升 (除字面量整数拓宽和数组到切片外)。

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,9 @@
#include "../stage0/include/utils.h"
#include "spl_lexer.h"
#include "spl_tok.h"
#include <math.h>
typedef enum {
SPL_AST_CONTAINER_MEMBER,
SPL_AST_CONTAINER_ITEM,
SPL_AST_FN_DECL,
SPL_AST_FN_DEFINE,
SPL_AST_TYPE_DECL,
@@ -37,7 +36,11 @@ struct spl_ast_node {
spl_ast_node_kind_t kind;
spl_ast_loc_t loc;
union {
spl_ast_node_ref_vec_t container_member;
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;
struct {
const char *ident;
@@ -58,18 +61,8 @@ struct spl_ast_node {
} param_decl;
struct {
spl_ast_node_ref_vec_t attr_list; /* attr_item */
const char *name;
enum {
SPL_AST_TYPE_STRUCT,
SPL_AST_TYPE_UNION,
SPL_AST_TYPE_ENUM,
SPL_AST_TYPE_TYPE_EXPR,
} kind;
union {
spl_ast_node_ref_t type_expr;
spl_ast_node_ref_t aggregate_list;
};
} type_decl;
struct {
spl_ast_node_ref_vec_t attr_list; /* attr_item */
@@ -103,6 +96,7 @@ struct spl_ast_node {
SPL_AST_CONTINUE_STATEMENT,
SPL_AST_DEFER_STATEMENT,
SPL_AST_VARDECL,
SPL_AST_CONSTDECL,
SPL_AST_TYPEDECL,
SPL_AST_EXPR_STATEMENT,
} kind;
@@ -131,8 +125,8 @@ struct spl_ast_node {
} for_statement;
struct {
spl_ast_node_ref_t expr;
spl_ast_node_ref_vec_t paced_exprs;
spl_ast_node_ref_vec_t statements;
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;
@@ -145,6 +139,7 @@ struct spl_ast_node {
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;
};
@@ -280,10 +275,13 @@ struct spl_ast_node {
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;
@@ -293,6 +291,7 @@ struct spl_ast_node {
spl_ast_node_ref_vec_t param_list; /* param_decl */
spl_ast_node_ref_t type_expr;
} fn_type;
spl_ast_node_ref_vec_t aggregate_list; /* container_decl */
};
} type_expr;
struct {

1
stage1/spl_ast2ir.c Normal file
View File

@@ -0,0 +1 @@
#include "spl_ast2ir.h"

4
stage1/spl_ast2ir.h Normal file
View File

@@ -0,0 +1,4 @@
#ifndef __SPL_AST2IR_H__
#define __SPL_AST2IR_H__
#endif /* __SPL_AST2IR_H__ */

26
stage1/spl_dumptree.c Normal file
View File

@@ -0,0 +1,26 @@
/* spl_dumptree.c 可配置的树形打印模块(只用基本 ASCII*/
#include "spl_dumptree.h"
#include <stdarg.h>
const spl_dumptree_style_t spl_dumptree_ascii_style = {
"| ",
"|-",
"`-",
" ",
};
void spl_dumptree_print(const spl_dumptree_style_t *st, const char *prefix, int is_last,
const char *fmt, ...) {
va_list ap;
printf("%s%s ", prefix, is_last ? st->last_branch : st->branch);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\n");
}
void spl_dumptree_child_prefix(const spl_dumptree_style_t *st, const char *prefix, int is_last,
char *out, size_t cap) {
snprintf(out, cap, "%s%s", prefix, is_last ? st->space : st->vertical);
}

31
stage1/spl_dumptree.h Normal file
View File

@@ -0,0 +1,31 @@
/* spl_dumptree.h 可配置的树形打印模块(只用基本 ASCII*/
#ifndef __SPL_DUMPTREE_H__
#define __SPL_DUMPTREE_H__
#include <stddef.h>
#include <stdio.h>
/* 可配置的缩进字符串 */
typedef struct {
const char *vertical; /* "| " */
const char *branch; /* "|-" */
const char *last_branch; /* "`-" */
const char *space; /* " " */
} spl_dumptree_style_t;
/* 默认 ASCII 风格 */
extern const spl_dumptree_style_t spl_dumptree_ascii_style;
/* 打印一行节点标签prefix + 分支符 + label
* prefix 已累积的缩进骨架(不含分支符)
* is_last 本节点是否为同级最后一个子节点
* fmt printf 风格 label */
void spl_dumptree_print(const spl_dumptree_style_t *st, const char *prefix, int is_last,
const char *fmt, ...);
/* 生成子节点的缩进骨架parent_prefix + (parent_is_last ? space : vertical) */
void spl_dumptree_child_prefix(const spl_dumptree_style_t *st, const char *prefix, int is_last,
char *out, size_t cap);
#endif /* __SPL_DUMPTREE_H__ */

View File

@@ -70,19 +70,39 @@
X(dbg.breakpoint, V0, SPL_IR_DBG_BREAKPOINT) \
X(dbg.declare, V0, SPL_IR_DBG_DECLARE)
typedef enum {
#ifdef X
#undef X
#endif
#define X(a, b, c) c,
SPL_IR_FN_TABLE
#undef X
} spl_ir_kind_t;
/* clang-format on */
typedef struct {
enum {
} kind;
spl_ir_kind_t kind;
} spl_ir_node_t;
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
typedef usize spl_ir_node_ref_t;
typedef VEC(spl_ir_node_ref_t) spl_ir_node_ref_vec_t;
typedef struct {
enum {
SPL_IR_ATTR_NONE,
SPL_IR_ATTR_LINK, /* 不实现 */
SPL_IR_ATTR_ABI, /* 只有 C ABI 支持 */
SPL_IR_ATTR_SYMBOL, /* 不实现 */
SPL_IR_ATTR_NAKED, /* 不实现 */
SPL_IR_ATTR_NOINLINE, /* 不实现 */
SPL_IR_ATTR_ALWAYSINLINE, /* 不实现 */
};
} spl_ir_attr_t;
typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_t;
typedef struct {
const char *name;
spl_ir_attr_t attr;
spl_ir_node_vec_t nodes;
spl_ir_node_ref_vec_t labels;
} spl_ir_func_t;

1
stage1/spl_sema.c Normal file
View File

@@ -0,0 +1 @@
#include "spl_sema.h"

33
stage1/spl_sema.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef __SPL_SEMA_H__
#define __SPL_SEMA_H__
#include "spl_ast.h"
#include "spl_type.h"
typedef usize spl_scope_id_t; /* 0 is error */
typedef struct {
spl_scope_id_t parent;
MAP(const char *, spl_type_id_t) symbols;
} spl_scope_node_t;
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
typedef struct {
spl_ast_t *ast;
spl_type_t type;
spl_scope_node_vec_t scopes;
spl_scope_id_t root_scope;
spl_scope_id_t current_scope;
int error_count;
} spl_sema_t;
void spl_sema_init(spl_sema_t *sema);
void spl_sema_drop(spl_sema_t *sema);
void spl_sema_run(spl_sema_t *sema);
spl_scope_id_t spl_sema_scope_alloc(spl_sema_t *sema);
bool spl_sema_scope_insert(spl_sema_t *sema, spl_scope_id_t id, const char *symbol_name,
spl_type_id_t symbol_val);
typedef VEC(const char *) spl_symbol_path_t;
spl_type_id_t spl_sema_scope_find(spl_sema_t *sema, spl_symbol_path_t path);
#endif /* __SPL_SEMA_H__ */

1
stage1/spl_type.c Normal file
View File

@@ -0,0 +1 @@
#include "spl_type.h"

116
stage1/spl_type.h Normal file
View File

@@ -0,0 +1,116 @@
#ifndef __SPL_TYPE_H__
#define __SPL_TYPE_H__
#include "../stage0/include/utils.h"
typedef usize spl_type_id_t; /* 0 is error */
typedef VEC(spl_type_id_t) spl_type_id_vec_t;
typedef struct {
enum {
SPL_TYPE_VOID,
SPL_TYPE_BOOL,
SPL_TYPE_INT,
SPL_TYPE_FLOAT,
SPL_TYPE_PTR,
SPL_TYPE_SLICE,
SPL_TYPE_ARRAY,
SPL_TYPE_STRUCT,
SPL_TYPE_UNION,
SPL_TYPE_ENUM,
SPL_TYPE_FN,
SPL_TYPE_ID,
} kind;
union {
struct {
usize bits;
int is_signed;
} int_type;
struct {
usize bits;
} float_type;
spl_type_id_t ptr_pointee;
spl_type_id_t slice_element;
struct {
spl_type_id_t element;
usize len;
} array_type;
spl_type_id_vec_t agg_field_types;
struct {
spl_type_id_vec_t variants;
spl_type_id_t tag_type;
} enum_type; // ADT
struct {
spl_type_id_vec_t params;
spl_type_id_t ret;
} fn_type;
spl_type_id_t type_id;
};
usize byte_size; /* 布局缓存 */
} spl_type_node_t;
typedef VEC(spl_type_node_t) spl_type_node_vec_t;
typedef struct {
const char *name;
spl_type_id_t type;
usize scope_id;
} spl_var_def_t;
typedef VEC(spl_var_def_t) spl_var_def_vec_t;
typedef struct {
enum {
SPL_DEF_NONE,
SPL_DEF_BUILTIN,
SPL_DEF_VAR,
SPL_DEF_FN_PARAMS,
SPL_DEF_AGG, // include enum variants
SPL_DEF_DISTINCT, // newtype
SPL_DEF_ALIAS, // sametypes
} kind;
union {
spl_var_def_t var_def;
spl_var_def_vec_t agg_def; // include enum variants
spl_var_def_vec_t fn_params_def;
spl_var_def_t type_def;
};
int source_loc;
enum {
SPL_FLAG_NONE,
} flag;
} spl_def_node_t;
typedef VEC(spl_def_node_t) spl_def_node_vec_t;
/*
SPL 设计是严格区分类型做到类型和名称无关即
type (类型名) = (匿名类型)
好处是递归使用可以直接操作类型名的映射的提前分配的匿名类型的id
*/
typedef struct {
spl_type_node_vec_t type_table;
spl_def_node_vec_t def_table; /* 使用type_id作为索引 */
} spl_type_t;
void spl_type_init(spl_type_t *type);
void spl_type_drop(spl_type_t *type);
void spl_type_def_dump(spl_type_t *type, spl_type_id_t id);
void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id);
// alloc 时两表平行 push, 保证索引同步
spl_type_id_t spl_type_alloc(spl_type_t *type);
spl_type_node_t *spl_type_node(spl_type_t *type, spl_type_id_t id);
spl_def_node_t *spl_type_def(spl_type_t *type, spl_type_id_t id);
spl_type_id_t spl_type_void(spl_type_t *type);
spl_type_id_t spl_type_bool(spl_type_t *type);
spl_type_id_t spl_type_int(spl_type_t *type, usize bits, int is_signed);
spl_type_id_t spl_type_float(spl_type_t *type, usize bits);
spl_type_id_t spl_type_ptr(spl_type_t *type, spl_type_id_t val);
spl_type_id_t spl_type_slice(spl_type_t *type, spl_type_id_t val);
spl_type_id_t spl_type_array(spl_type_t *type, spl_type_id_t val, usize len);
spl_type_id_t spl_type_tid(spl_type_t *type, spl_type_id_t val);
spl_type_id_t spl_type_agg(spl_type_t *type, spl_type_id_vec_t fields);
spl_type_id_t spl_type_enum(spl_type_t *type, spl_type_id_vec_t variants, spl_type_id_t tag);
spl_type_id_t spl_type_fn(spl_type_t *type, spl_type_id_vec_t params, spl_type_id_t ret);
#endif /* __SPL_TYPE_H__ */

View File

@@ -1,8 +1,19 @@
/* splc0.c — SPL compiler CLI */
/* splc0.c — SPL compiler CLI (stage 1, 引导用)
*
* splc0 --dump tokens|ast|all <file> dump 前端产物
* splc0 <in> <out> 编译 (阶段 B 实现)
*/
#define __SCC_LOG_IMPL_IMPORT_SRC__
#include "../stage0/include/utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "spl_ast.h"
#include "spl_lexer.h"
#include "spl_tok.h"
static char *read_file(const char *path, long *out_len) {
FILE *f = fopen(path, "rb");
if (!f) {
@@ -24,19 +35,68 @@ static char *read_file(const char *path, long *out_len) {
return buf;
}
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "Usage: splc0 [--dump <flags>] <in> [out]\n");
static const char *const tok_type_names[] = {
#define X(name, enum_name, dummy) #enum_name,
KEYWORD_TABLE
#undef X
#define X(name, enum_name, dummy) #enum_name,
TOKEN_TABLE
#undef X
};
static void dump_tokens(const char *src, const char *fname) {
spl_tok_vec_t toks = spl_lex(src, fname);
printf("tokens got (%zu)\n", toks.size);
for (usize i = 0; i < toks.size; i++) {
const spl_tok_t *t = &toks.data[i];
printf("[%s] %.*s (%zu:%zu)\n", tok_type_names[t->type], (int)t->len, t->lexeme, t->line,
t->col);
}
vec_free(toks);
}
static void dump_ast(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);
spl_ast_valid(&ast);
spl_ast_dump(&ast, ast.root);
spl_ast_drop(&ast);
}
static int cmd_dump(const char *flags, const char *path) {
long len;
char *src = read_file(path, &len);
if (!src)
return 1;
}
if (strcmp(argv[1], "--dump") == 0)
// return cmd_dump(argc - 2, argv + 2);
return 0;
if (strcmp(argv[1], "--help") == 0) {
printf("splc0 <in> <out> compile\n");
printf("splc0 --dump <f> <file> dump: tokens,cst,ast,ir,mcode,all\n");
return 0;
}
// return cmd_compile(argc - 1, argv + 1);
int do_tokens = strstr(flags, "tokens") != NULL || strcmp(flags, "all") == 0;
int do_ast = strstr(flags, "ast") != NULL || strcmp(flags, "all") == 0;
if (do_tokens)
dump_tokens(src, path);
if (do_ast)
dump_ast(src, path);
free(src);
return 0;
}
int main(int argc, char **argv) {
if (argc < 2) {
LOG_FATAL("Usage: splc0 [--dump <flags>] <in> [out]\n");
return 1;
}
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
LOG_INFO("splc0 <in> <out> compile (.spl -> .sir, 阶段 B)\n");
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,all\n");
return 0;
}
if (strcmp(argv[1], "--dump") == 0) {
if (argc < 4) {
LOG_INFO("splc0: --dump need <flags> <file>\n");
return 1;
}
return cmd_dump(argv[2], argv[3]);
}
LOG_FATAL("splc0: compile todo\n");
return 1;
}

View File

@@ -1,4 +1,4 @@
/* spc_vm.c 鈥?VM launcher for stage 1 */
/* spc_vm.c launcher for stage 1 */
#include "../stage0/spl_mcode.h"
#include "../stage0/spl_syscall.h"
@@ -57,13 +57,12 @@ int main(int argc, const char **argv) {
return 1;
}
spl_vm_set_trace(&vm, trace);
if (debug_addr) spl_vm_set_debug(&vm, 1);
if (debug_addr)
spl_vm_set_debug(&vm, 1);
int ret = spl_vm_run_until(&vm, 0);
spl_vm_drop(&vm);
spl_prog_drop(&prog);
if (ret < 0)
return (int)vm.exit_code;
return (int)vm.exit_code;
}

View File

@@ -24,8 +24,8 @@ type Expr = enum {
fn eval(self: *Expr) i32 {
match self {
.Int[val] => ret val,
.Add[.left = left, .right = right] => ret eval(left) + eval(right),
.Int[val] => { ret val; },
.Add[sub] => { ret eval(sub.left) + eval(sub.right); }
}
ret 0;
}
@@ -39,7 +39,7 @@ fn main() i32 {
/* enum 方法 + match */
var expr_l := Expr { .Int = 3 };
var expr_r := Expr { .Int = 4 };
var expr := Expr { .Add = { .left = expr_l, .right = expr_r } };
var expr := Expr { .Add = .{ .left = expr_l, .right = expr_r } };
var result := expr.eval(&expr);
vm_printf("eval result: %d\n", result);
if result != 7 { ret 1; }

View File

@@ -118,7 +118,7 @@ fn test_shape_match() i32 {
.Circle[r] => {
if r != 10 { ret 1; }
},
.Rect[.x = w, .y = h] => {
.Rect[p] => {
ret 2;
}
}
@@ -127,9 +127,9 @@ fn test_shape_match() i32 {
s = Shape { .Rect = Point { .x = 3, .y = 4 } };
match s {
.Circle[r] => { ret 3; },
.Rect[.x = w, .y = h] => {
if w != 3 { ret 4; }
if h != 4 { ret 5; }
.Rect[p] => {
if p.x != 3 { ret 4; }
if p.y != 4 { ret 5; }
}
}

View File

@@ -8,7 +8,7 @@ fn test_string() i32 {
* String test: str is []u8
* ============================ */
var data: *u8 = "hello";
var s: []u8 = { .ptr = data, .len = 5 };
var s: []u8 = .{ .ptr = data, .len = 5 };
if s.len != 5 { ret 100; }
if s[0] != 104 { ret 101; } /* 'h' */
@@ -147,7 +147,7 @@ fn main() i32 {
var data: [5]i32;
data[0] = 10; data[1] = 20; data[2] = 30; data[3] = 40; data[4] = 50;
var p: *i32 = &data[2];
var from_ptr: []i32 = { .ptr = p, .len = 2 };
var from_ptr: []i32 = .{ .ptr = p, .len = 2 };
var from_ptr2: []i32;
from_ptr2.ptr = p;
from_ptr2.len = 2;

View File

@@ -78,7 +78,7 @@ fn test_slice_in_struct() i32 {
raw[0] = 65; raw[1] = 66; raw[2] = 67; raw[3] = 68;
/* Bug fix: { .ptr = ..., .len = ... } inside struct literal */
var b: Buffer = Buffer { .data = { .ptr = &raw[0], .len = 4 }, .len = 4 };
var b: Buffer = Buffer { .data = .{ .ptr = &raw[0], .len = 4 }, .len = 4 };
if b.len != 4 { ret 1; }
if b.data[0] != 65 { ret 2; }
@@ -90,7 +90,7 @@ fn test_slice_in_struct() i32 {
if raw[0] != 90 { ret 5; }
/* Initialize with shorter slice */
var b2: Buffer = Buffer { .data = { .ptr = &raw[2], .len = 2 }, .len = 2 };
var b2: Buffer = Buffer { .data = .{ .ptr = &raw[2], .len = 2 }, .len = 2 };
if b2.len != 2 { ret 6; }
if b2.data[0] != 67 { ret 7; }
@@ -211,7 +211,7 @@ fn test_complex_nesting() i32 {
var bundle: Bundle = Bundle {
.name = &str_data[0],
.buf = Buffer { .data = { .ptr = &str_data[1], .len = 3 }, .len = 3 },
.buf = Buffer { .data = .{ .ptr = &str_data[1], .len = 3 }, .len = 3 },
.row = MatrixRow { .items = [4]i32{1, 2, 3, 4} },
.pt = Point { .x = -5, .y = 15 }
};
@@ -259,7 +259,7 @@ fn test_enum_complex() i32 {
.Inactive => {
ret 2;
},
.Pending[.x = px, .y = py] => {
.Pending[p] => {
ret 3;
}
}
@@ -270,7 +270,7 @@ fn test_enum_complex() i32 {
match s2 {
.Active[val] => {},
.Inactive => { is_inactive = 1; },
.Pending[.x = px, .y = py] => {}
.Pending[p] => {}
}
if is_inactive != 1 { ret 4; }
@@ -279,9 +279,9 @@ fn test_enum_complex() i32 {
match s3 {
.Active[val] => { ret 5; },
.Inactive => { ret 6; },
.Pending[.x = px, .y = py] => {
if px != 7 { ret 7; }
if py != 8 { ret 8; }
.Pending[p] => {
if p.x != 7 { ret 7; }
if p.y != 8 { ret 8; }
}
}