From 98b35a98e36d494f60e3b778be0e2ded3a29addd Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Tue, 8 Sep 2026 13:14:29 +0800 Subject: [PATCH] =?UTF-8?q?stage1=20=E6=96=B0=E7=9A=84ast=E7=BB=93?= =?UTF-8?q?=E6=9E=84=20=E4=BD=BF=E7=94=A8pest=E6=8F=8F=E8=BF=B0=E8=AF=AD?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gramma.pest | 384 +++++ nob.c | 194 ++- nob.h | 1 + nob_popen.h | 54 + stage1/spl_ast.c | 3560 +++++++++++++++++++++++++------------------- stage1/spl_ast.h | 665 ++++++--- stage1/spl_dbg.h | 6 +- stage1/spl_lexer.c | 163 +- stage1/spl_tok.h | 15 +- stage1/spl_type.c | 312 ++-- stage1/spl_type.h | 50 +- stage1/splc0.c | 108 +- 12 files changed, 3344 insertions(+), 2168 deletions(-) create mode 100644 gramma.pest create mode 100644 nob_popen.h diff --git a/gramma.pest b/gramma.pest new file mode 100644 index 0000000..9f61f35 --- /dev/null +++ b/gramma.pest @@ -0,0 +1,384 @@ +// 顶层容器 +Root = { SOI ~ ContainerMembers ~ EOI } +ContainerMembers = { ExternalHeaderList ~ (ContainerDeclaration ~ (COMMA | SEMICOLON)*)* } + +HeaderItem = { (AT | SHARP) ~ IDENTIFIER ~ (LPAREN ~ ExprList? ~ RPAREN)? } +HeaderList = { HeaderItem* } +DeclHeader = { HeaderList? ~ KEYWORD_pub? } +ExternalHeaderItem = { (AT | SHARP) ~ BANG ~ IDENTIFIER ~ (LPAREN ~ ExprList? ~ RPAREN)? } +ExternalHeaderList = { ExternalHeaderItem* } + +BindingIdent = { IDENTIFIER | UNDERSCORE } + +ContainerDeclaration = { + FnDecl + | VarDecl + | ConstDecl + | TypeDecl + | MemberDecl + | ComptimeDecl + | HeaderList ~ Block +} + +ComptimeDecl = { KEYWORD_comptime ~ (Block | Expr) } + +// 函数声明(可带 comptime 前缀,支持修饰符) +FnDecl = { + DeclHeader ~ KEYWORD_comptime? ~ KEYWORD_fn ~ IDENTIFIER ~ LPAREN ~ ParamDeclList ~ RPAREN ~ (COLON ~ TypeExpr)? ~ (SEMICOLON | Block) +} + +ParamDeclList = { (ParamDecl ~ COMMA)* ~ (ParamDecl | DOT3)? } +ParamDecl = { HeaderList? ~ BindingIdent ~ COLON ~ TypeExpr } + +// 变量声明(支持修饰符、元组解构与类型推导) +VarDecl = { DeclHeader ~ KEYWORD_var ~ VarBody } +ConstDecl = { DeclHeader ~ KEYWORD_const ~ VarBody } +VarBody = { VarPattern ~ (COLON ~ TypeExpr)? ~ (EQUAL ~ Expr)? } + +// 类型声明(支持修饰符) +TypeDecl = { DeclHeader ~ KEYWORD_type ~ IDENTIFIER ~ EQUAL ~ TypeExpr } + +// 容器成员(支持修饰符) +MemberDecl = { DeclHeader ~ IDENTIFIER ~ (COLON ~ TypeExpr)? ~ (EQUAL ~ Expr)? } + +// 变量声明左值模式(允许单独标识符) +VarPattern = { VarPatternAtom ~ (COMMA ~ VarPatternAtom)* } +VarPatternAtom = { + BindingIdent + | DOT ~ IDENTIFIER ~ (LBRACKET ~ VarPattern ~ RBRACKET)? + | LPAREN ~ VarPattern ~ RPAREN +} + +// 匹配模式(不允许单独标识符) +MatchPattern = { MatchPatternAtom ~ (COMMA ~ MatchPatternAtom)* } +MatchPatternAtom = { + UNDERSCORE + | Expr + | DOT ~ IDENTIFIER ~ (LBRACKET ~ MatchPattern ~ RBRACKET)? + | LPAREN ~ MatchPattern ~ RPAREN +} + +// 块内语句 +Block = { LBRACE ~ Statement* ~ Expr? ~ RBRACE } +Statement = { + RetStatement + | BreakStatement + | ContinueStatement + | DeferStatement + | DeclStatement + | ExprStatement + | ComptimeStatement +} + +// 声明语句(内部声明已包含 HeaderList) +DeclStatement = { (VarDecl | ConstDecl | TypeDecl) ~ (COMMA | SEMICOLON)? } +ExprStatement = { Expr ~ (COMMA | SEMICOLON)? } +ComptimeStatement = { ComptimeDecl ~ (COMMA | SEMICOLON)? } + +RetStatement = { KEYWORD_ret ~ Expr? ~ (COMMA | SEMICOLON)? } +BreakStatement = { KEYWORD_break ~ Label? ~ Expr? ~ (COMMA | SEMICOLON)? } +ContinueStatement = { KEYWORD_continue ~ Label? ~ (COMMA | SEMICOLON)? } +DeferStatement = { KEYWORD_defer ~ (Block | Statement) ~ (COMMA | SEMICOLON)? } + +// 标签定义($ 前缀) +Label = { DOLLAR ~ IDENTIFIER } + +// ============ 表达式 ============ + +Expr = { AssignExpr } + +AssignExpr = { BoolOrExpr ~ (AssignOp ~ AssignExpr)? } +BoolOrExpr = { BoolAndExpr ~ (BOOL_OR ~ BoolAndExpr)* } +BoolAndExpr = { BitOrExpr ~ (BOOL_AND ~ BitOrExpr)* } +BitOrExpr = { BitXorExpr ~ (PIPE ~ BitXorExpr)* } +BitXorExpr = { BitAndExpr ~ (CARET ~ BitAndExpr)* } +BitAndExpr = { CmpEqExpr ~ (AMPERSAND ~ CmpEqExpr)* } +CmpEqExpr = { CmpExpr ~ ((EQ_EQ | BANG_EQUAL) ~ CmpExpr)* } +CmpExpr = { ArrowExpr ~ ((L_ARROW_EQ | L_ARROW | R_ARROW_EQ | R_ARROW) ~ ArrowExpr)* } + +ArrowExpr = { RangeExpr ~ ((THIN_R_ARROW | THIN_L_ARROW | FAT_D_ARROW | THIN_D_ARROW) ~ RangeExpr)* } + +RangeExpr = { ShiftExpr ~ (DOT2 ~ ShiftExpr?)? } +ShiftExpr = { AddExpr ~ ((L_ARROW2_EQ | L_ARROW2 | R_ARROW2_EQ | R_ARROW2) ~ AddExpr)* } +AddExpr = { MulExpr ~ ((PLUS | MINUS) ~ MulExpr)* } +MulExpr = { PrefixExpr ~ ((ASTERISK | SLASH | PERCENT) ~ PrefixExpr)* } +PrefixExpr = { PrefixOp* ~ PostfixExpr } +PrefixOp = { MINUS | BANG | TILDE | AMPERSAND } + +PostfixExpr = { + PrimaryExpr ~ (LPAREN ~ ExprList ~ RPAREN | DOT ~ IDENTIFIER | DOT ~ ASTERISK | LBRACKET ~ Expr ~ RBRACKET | LBRACKET ~ Expr ~ DOT2 ~ Expr? ~ RBRACKET | KEYWORD_as ~ TypeExpr)* +} + +ExprList = { (Expr ~ COMMA)* ~ Expr? } + +PrimaryExpr = { + FLOAT_LITERAL + | INTEGER_LITERAL + | CHAR_LITERAL + | STRING_LITERAL + | KEYWORD_true + | KEYWORD_false + | KEYWORD_null + | TupleLiteral + | AggregateLiteral + | AnonymousAggregateLiteral + | ArrayLiteral + | AnonymousArrayLiteral + | ComptimeCallExpr // @name(args) + + | IDENTIFIER + | Block + | IfExpr + | IfVarExpr + | WhileExpr + | LoopExpr + | ForExpr + | MatchExpr + | FnTypeExpr +} + +TupleLiteral = { ParenExpr } + +// ============ 聚合字面量 ============ + +AggregateLiteral = { IDENTIFIER ~ LBRACE ~ StructInitList? ~ RBRACE } +AnonymousAggregateLiteral = { DOT ~ LBRACE ~ StructInitList? ~ RBRACE } + +StructInitList = { StructInit ~ ((COMMA | SEMICOLON) ~ StructInit)* ~ (COMMA | SEMICOLON)? } +StructInit = { DOT ~ IDENTIFIER ~ (EQUAL ~ Expr)? } + +// ============ 数组/切片字面量 ============ +ArrayLiteral = { + // 切片字面量: []T[1,2,3] + // 数组字面量: [N]T[1,2,3] 或 [_]T[1,2,3] + LBRACKET ~ (INTEGER_LITERAL | UNDERSCORE)? ~ RBRACKET ~ TypeExpr ~ LBRACKET ~ ExprList? ~ RBRACKET +} + +AnonymousArrayLiteral = { + DOT ~ LBRACKET ~ ExprList? ~ RBRACKET +} + +// ============ 类型表达式(独立,限制语法) ============ +TypeExpr = { HeaderList? ~ TypePrefixExpr } + +TypePrefixExpr = { ASTERISK* ~ TypePostfixExpr } + +TypePostfixExpr = { + TypePrimary ~ (LPAREN ~ TypeExprList ~ RPAREN | DOT ~ IDENTIFIER | LBRACKET ~ TypeExpr ~ RBRACKET | KEYWORD_as ~ TypeExpr)* +} + +TypePrimary = { + IDENTIFIER + | KEYWORD_i8 + | KEYWORD_u8 + | KEYWORD_i16 + | KEYWORD_u16 + | KEYWORD_i32 + | KEYWORD_u32 + | KEYWORD_i64 + | KEYWORD_u64 + | KEYWORD_f32 + | KEYWORD_f64 + | KEYWORD_isize + | KEYWORD_usize + | KEYWORD_bool + | KEYWORD_void + | KEYWORD_ptr + | FnTypeExpr + | AggregateTypeExpr + | TypeParenExpr + | ArrayTypeExpr +} + +ArrayTypeExpr = { + LBRACKET ~ RBRACKET ~ TypeExpr + | LBRACKET ~ (INTEGER_LITERAL | UNDERSCORE) ~ RBRACKET ~ TypeExpr +} + +TypeParenExpr = { + LPAREN ~ RPAREN + | LPAREN ~ TypeExpr ~ COMMA ~ (TypeExpr ~ COMMA)* ~ TypeExpr? ~ RPAREN + | LPAREN ~ TypeExpr ~ RPAREN +} + +TypeExprList = { (TypeExpr ~ COMMA)* ~ TypeExpr? } + +FnTypeExpr = { KEYWORD_comptime? ~ KEYWORD_fn ~ LPAREN ~ TypeExprList? ~ RPAREN ~ (COLON ~ TypeExpr)? } + +AggregateTypeExpr = { (KEYWORD_struct | KEYWORD_union | KEYWORD_enum | KEYWORD_shape) ~ LBRACE ~ ContainerMembers ~ RBRACE } + +// ============ 控制流 ============ +IfExpr = { KEYWORD_if ~ Expr ~ Block ~ (KEYWORD_else ~ (Block | IfExpr | IfVarExpr))? } +IfVarExpr = { KEYWORD_if ~ VarBody ~ Block ~ (KEYWORD_else ~ (Block | IfExpr | IfVarExpr))? } + +WhileExpr = { Label? ~ KEYWORD_while ~ Expr ~ Block ~ (KEYWORD_else ~ (Block | Expr))? } +LoopExpr = { Label? ~ KEYWORD_loop ~ Block } +ForExpr = { Label? ~ KEYWORD_for ~ Expr ~ (COMMA ~ Expr)* ~ KEYWORD_as ~ BindingIdent ~ (COMMA ~ BindingIdent)* ~ Block ~ (KEYWORD_else ~ (Block | Expr))? } + +MatchExpr = { KEYWORD_match ~ Expr ~ LBRACE ~ MatchArm* ~ RBRACE } +MatchArm = { MatchPattern ~ (COMMA ~ MatchPattern)* ~ FAT_R_ARROW ~ Block } + +// ============ 其他表达式 ============ +ComptimeCallExpr = { AT ~ IDENTIFIER ~ LPAREN ~ ExprList? ~ RPAREN } +ParenExpr = { + + | LPAREN ~ Expr ~ COMMA ~ (Expr ~ COMMA)* ~ Expr? ~ RPAREN + | LPAREN ~ Expr ~ RPAREN +} + +// ============ Token 定义 ============ +AssignOp = { EQUAL | PLUS_EQ | MINUS_EQ | ASTERISK_EQ | SLASH_EQ | PERCENT_EQ | AMPERSAND_EQ | PIPE_EQ | CARET_EQ | L_ARROW2_EQ | R_ARROW2_EQ } +BOOL_OR = { PIPE ~ PIPE } +BOOL_AND = { AMPERSAND ~ AMPERSAND } +EQ_EQ = { EQUAL ~ EQUAL } +BANG_EQUAL = { BANG ~ EQUAL } + +keyword_suffix = _{ !(ASCII_ALPHANUMERIC | "_") } +KEYWORD_fn = @{ "fn" ~ keyword_suffix } +KEYWORD_type = @{ "type" ~ keyword_suffix } +KEYWORD_pub = @{ "pub" ~ keyword_suffix } +KEYWORD_var = @{ "var" ~ keyword_suffix } +KEYWORD_const = @{ "const" ~ keyword_suffix } +KEYWORD_if = @{ "if" ~ keyword_suffix } +KEYWORD_else = @{ "else" ~ keyword_suffix } +KEYWORD_while = @{ "while" ~ keyword_suffix } +KEYWORD_loop = @{ "loop" ~ keyword_suffix } +KEYWORD_for = @{ "for" ~ keyword_suffix } +KEYWORD_as = @{ "as" ~ keyword_suffix } +KEYWORD_match = @{ "match" ~ keyword_suffix } +KEYWORD_ret = @{ "ret" ~ keyword_suffix } +KEYWORD_break = @{ "break" ~ keyword_suffix } +KEYWORD_continue = @{ "continue" ~ keyword_suffix } +KEYWORD_defer = @{ "defer" ~ keyword_suffix } +KEYWORD_shape = @{ "shape" ~ keyword_suffix } +KEYWORD_struct = @{ "struct" ~ keyword_suffix } +KEYWORD_union = @{ "union" ~ keyword_suffix } +KEYWORD_enum = @{ "enum" ~ keyword_suffix } +KEYWORD_comptime = @{ "comptime" ~ keyword_suffix } +KEYWORD_void = @{ "void" ~ keyword_suffix } +KEYWORD_bool = @{ "bool" ~ keyword_suffix } +KEYWORD_isize = @{ "isize" ~ keyword_suffix } +KEYWORD_usize = @{ "usize" ~ keyword_suffix } +KEYWORD_ptr = @{ "ptr" ~ keyword_suffix } +KEYWORD_true = @{ "true" ~ keyword_suffix } +KEYWORD_false = @{ "false" ~ keyword_suffix } +KEYWORD_null = @{ "null" ~ keyword_suffix } +KEYWORD_undefined = @{ "undefined" ~ keyword_suffix } +KEYWORD_i8 = @{ "i8" ~ keyword_suffix } +KEYWORD_u8 = @{ "u8" ~ keyword_suffix } +KEYWORD_i16 = @{ "i16" ~ keyword_suffix } +KEYWORD_u16 = @{ "u16" ~ keyword_suffix } +KEYWORD_i32 = @{ "i32" ~ keyword_suffix } +KEYWORD_u32 = @{ "u32" ~ keyword_suffix } +KEYWORD_i64 = @{ "i64" ~ keyword_suffix } +KEYWORD_u64 = @{ "u64" ~ keyword_suffix } +KEYWORD_f32 = @{ "f32" ~ keyword_suffix } +KEYWORD_f64 = @{ "f64" ~ keyword_suffix } + +FAT_D_ARROW = { "<=>" } +THIN_D_ARROW = { "<->" } +L_ARROW2_EQ = { "<<=" } +R_ARROW2_EQ = { ">>=" } +DOT3 = { "..." } +THIN_R_ARROW = { "<-" } +THIN_L_ARROW = { "->" } +L_ARROW_EQ = { "<=" } +R_ARROW_EQ = { ">=" } +L_ARROW2 = { "<<" } +R_ARROW2 = { ">>" } +FAT_R_ARROW = { "=>" } +PLUS_EQ = { "+=" } +MINUS_EQ = { "-=" } +ASTERISK_EQ = { "*=" } +SLASH_EQ = { "/=" } +PERCENT_EQ = { "%=" } +AMPERSAND_EQ = { "&=" } +PIPE_EQ = { "|=" } +CARET_EQ = { "^=" } +DOT2 = { ".." } +LPAREN = { "(" } +RPAREN = { ")" } +LBRACKET = { "[" } +RBRACKET = { "]" } +LBRACE = { "{" } +RBRACE = { "}" } +COMMA = { "," } +SEMICOLON = { ";" } +COLON = { ":" } +DOT = { "." } +AT = { "@" } +SHARP = { "#" } +DOLLAR = { "$" } +EQUAL = { "=" } +PLUS = { "+" } +MINUS = { "-" } +ASTERISK = { "*" } +SLASH = { "/" } +PERCENT = { "%" } +AMPERSAND = { "&" } +PIPE = { "|" } +CARET = { "^" } +TILDE = { "~" } +BANG = { "!" } +L_ARROW = { "<" } +R_ARROW = { ">" } +UNDERSCORE = { "_" } + +keyword = _{ + KEYWORD_fn + | KEYWORD_type + | KEYWORD_var + | KEYWORD_const + | KEYWORD_if + | KEYWORD_else + | KEYWORD_while + | KEYWORD_loop + | KEYWORD_for + | KEYWORD_as + | KEYWORD_match + | KEYWORD_ret + | KEYWORD_break + | KEYWORD_continue + | KEYWORD_defer + | KEYWORD_shape + | KEYWORD_struct + | KEYWORD_union + | KEYWORD_enum + | KEYWORD_comptime + | KEYWORD_void + | KEYWORD_bool + | KEYWORD_true + | KEYWORD_false + | KEYWORD_null + | KEYWORD_undefined + | KEYWORD_i8 + | KEYWORD_u8 + | KEYWORD_i16 + | KEYWORD_u16 + | KEYWORD_i32 + | KEYWORD_u32 + | KEYWORD_i64 + | KEYWORD_u64 + | KEYWORD_f32 + | KEYWORD_f64 + | KEYWORD_isize + | KEYWORD_usize + | KEYWORD_ptr +} +IDENTIFIER = @{ + !(keyword ~ !(ASCII_ALPHANUMERIC | "_")) ~ (ASCII_ALPHA | "_" ~ (ASCII_ALPHANUMERIC | "_")) ~ (ASCII_ALPHANUMERIC | "_")* +} + +INTEGER_LITERAL = { DECIMAL | HEX | BINARY | OCTAL | "0" } +DECIMAL = { ASCII_NONZERO_DIGIT ~ (ASCII_DIGIT | "_")* } +HEX = { "0" ~ ("x" | "X") ~ ASCII_HEX_DIGIT ~ (ASCII_HEX_DIGIT | "_")* } +BINARY = { "0" ~ ("b" | "B") ~ ASCII_BIN_DIGIT ~ (ASCII_BIN_DIGIT | "_")* } +OCTAL = { "0" ~ ("o" | "O") ~ ASCII_OCT_DIGIT ~ (ASCII_OCT_DIGIT | "_")* } +FLOAT_LITERAL = { ASCII_DIGIT ~ "." ~ ASCII_DIGIT ~ (ASCII_DIGIT | "_")* } +CHAR_LITERAL = { "'" ~ (!"'" ~ ANY) ~ "'" } +STRING_LITERAL = { "\"" ~ ANY* ~ "\"" } + +COMMENT = _{ LINE_COMMENT | BLOCK_COMMENT } +LINE_COMMENT = { "//" ~ (!"\n" ~ ANY)* } +BLOCK_COMMENT = { "/*" ~ ANY* ~ "*/" } +WHITESPACE = _{ " " | "\t" | "\r" | "\n" } diff --git a/nob.c b/nob.c index 6214383..15140a1 100644 --- a/nob.c +++ b/nob.c @@ -1,9 +1,11 @@ -#undef UNICODE -#define NOB_IMPLEMENTATION #define SPL_CFLAGS "-Wall", "-Wextra", "-O0", "-g", "-D_CRT_SECURE_NO_WARNINGS" #define nob_cc_flags(cmd) nob_cmd_append(cmd, SPL_CFLAGS) +#undef UNICODE +#define NOB_IMPLEMENTATION #include "nob.h" +#undef NOB_IMPLEMENTATION +#include "nob_popen.h" #ifdef _WIN32 #include #endif @@ -15,28 +17,38 @@ // object files get rebuilt. static const char *CFLAGS_STAMP = BUILD_FOLDER ".cflags"; +/* clang-format off */ #define VM_SRCS "stage0/spl_mcode.c", "stage0/spl_syscall.c", "stage0/spl_vm.c" static const char *spl_cli_srcs[] = {"stage0/spl_cli.c", VM_SRCS}; static const char *test_srcs[] = {"stage0/test_spl_vm.c", VM_SRCS}; static const char *splc0_srcs[] = { - "stage1/splc0.c", "stage0/spl_mcode.c", "stage1/spl_ast.c", "stage1/spl_lexer.c", - "stage1/spl_dumptree.c", "stage1/spl_type.c", "stage1/spl_sema.c", "stage1/spl_ir.c", - "stage1/spl_ast2ir.c", "stage1/spl_ir2vm.c", + "stage1/splc0.c", + "stage1/spl_lexer.c", + "stage1/spl_ast.c", + "stage1/spl_dumptree.c", + "stage1/spl_type.c", + "stage1/spl_sema.c", + // "stage1/spl_ir.c", + // "stage1/spl_ast2ir.c", + // "stage1/spl_ir2vm.c", + // "stage0/spl_mcode.c", }; +/* clang-format on */ + typedef struct { const char *name; const char **srcs; size_t srcs_count; -} Exe_Target; +} target_t; -static Exe_Target exe_targets[] = { +static target_t exe_targets[] = { {"spl_cli", spl_cli_srcs, NOB_ARRAY_LEN(spl_cli_srcs)}, {"test", test_srcs, NOB_ARRAY_LEN(test_srcs)}, {"splc0", splc0_srcs, NOB_ARRAY_LEN(splc0_srcs)}, }; -static const Exe_Target *find_exe_target(const char *name) { +static const target_t *find_exe_target(const char *name) { for (size_t i = 0; i < NOB_ARRAY_LEN(exe_targets); ++i) { if (strcmp(exe_targets[i].name, name) == 0) { return &exe_targets[i]; @@ -105,7 +117,7 @@ static bool build_object(const char *src) { return nob_cmd_run(&cmd); } -static bool link_exe(const Exe_Target *target) { +static bool link_exe(const target_t *target) { const char *exe = nob_temp_sprintf(BUILD_FOLDER "%s", target->name); const char **objs = (const char **)nob_temp_alloc(sizeof(const char *) * target->srcs_count); for (size_t i = 0; i < target->srcs_count; ++i) { @@ -129,7 +141,7 @@ static bool link_exe(const Exe_Target *target) { } static bool build_target(const char *name) { - const Exe_Target *target = find_exe_target(name); + const target_t *target = find_exe_target(name); if (target == NULL) { nob_log(NOB_ERROR, "unknown target `%s`", name); return false; @@ -152,6 +164,143 @@ static bool build_all(void) { return true; } +static void parse_expect(const char *name, Nob_Cmd_Result *expect) { + Nob_String_Builder sb = {0}; + nob_read_entire_file(name, &sb); + Nob_String_View sv = nob_sb_to_sv(sb); + while (sv.count > 0) { + Nob_String_View line = nob_sv_chop_by_delim(&sv, '\n'); + line = nob_sv_trim_left(line); // 去掉前导空格 + + if (!nob_sv_starts_with(line, nob_sv_from_cstr("//"))) { + break; + } + + Nob_String_View rest = nob_sv_from_parts(line.data + 2, line.count - 2); + rest = nob_sv_trim_left(rest); + + if (rest.count == 0) + continue; + + if (nob_sv_starts_with(rest, nob_sv_from_cstr("Expect"))) { + break; + } + rest = nob_sv_from_parts(rest.data + 6, rest.count - 6); + rest = nob_sv_trim_left(rest); + + // 按 '=' 分割 + Nob_String_View key = nob_sv_chop_by_delim(&rest, '='); + key = nob_sv_trim(key); + Nob_String_View value = nob_sv_trim(rest); + + if (nob_sv_eq(key, nob_sv_from_cstr("retcode"))) { + int val = 0; + for (size_t i = 0; i < value.count && isdigit(value.data[i]); ++i) { + val = val * 10 + (value.data[i] - '0'); + } + expect->exit_code = val; + } else if (nob_sv_eq(key, nob_sv_from_cstr("stdout"))) { + } + } +} + +static bool test_once(const char *fname) { + const char *compiler_path = "splc0"; + const char *cli_path = "spl_cli"; + const char *target_sir = BUILD_FOLDER "test.sir"; + + Nob_Cmd cmd = {0}; + if (!build_target(compiler_path)) { + return 1; + } + cmd.count = 0; + + nob_cmd_append(&cmd, nob_temp_sprintf(BUILD_FOLDER "%s", compiler_path)); + nob_cmd_append(&cmd, fname, target_sir); + if (!nob_cmd_run(&cmd)) { + return false; + } + + if (!build_target(cli_path)) { + return 1; + } + cmd.count = 0; + nob_cmd_append(&cmd, nob_temp_sprintf(BUILD_FOLDER "%s", cli_path)); + nob_cmd_append(&cmd, target_sir); + nob_cmd_run(&cmd); + + Nob_Cmd_Result result = {0}; + + Nob_String_Builder cmd_str = {0}; + nob_cmd_render(cmd, &cmd_str); + nob_sb_append_null(&cmd_str); + nob_cmd_capture_popen(cmd_str.items, &result); + // Expect retcode = number + + Nob_Cmd_Result expect = {0}; + parse_expect(fname, &expect); + + if (expect.exit_code != result.exit_code) { + nob_log(NOB_ERROR, "Expect code `%d`, Result code `%d`\n", expect.exit_code, + result.exit_code); + return false; + } + + nob_cmd_result_free(result); + return true; +} + +static bool test_once_ast(const char *fname) { + const char *target_name = "splc0"; + if (!prepare_build()) + return 1; + if (!build_target(target_name)) + return 1; + Nob_Cmd cmd = {0}; + nob_cmd_append(&cmd, nob_temp_sprintf(BUILD_FOLDER "%s", target_name)); + nob_cmd_append(&cmd, "--dump", "ast", fname, BUILD_FOLDER "t.sir"); + return nob_cmd_run(&cmd); +} + +static bool test_once_sema(const char *fname) { + const char *target_name = "splc0"; + if (!prepare_build()) + return 1; + if (!build_target(target_name)) + return 1; + Nob_Cmd cmd = {0}; + nob_cmd_append(&cmd, nob_temp_sprintf(BUILD_FOLDER "%s", target_name)); + nob_cmd_append(&cmd, "--dump", "sema", fname, BUILD_FOLDER "t.sir"); + return nob_cmd_run(&cmd); +} + +typedef bool (*test_fn_t)(const char *fname); +static bool run_test(Nob_Files *files, test_fn_t test_once) { + const char *test_folder = "./tests/stage1/"; + + Nob_File_Paths paths = {0}; + nob_read_entire_dir(test_folder, &paths); + for (int i = 0; i < files->count; i += 1) { + for (int j = 0; j < paths.count; j += 1) { + String_View sv = sv_from_cstr(paths.items[j]); + // printf("--- test " SV_Fmt " ---\n", SV_Arg(sv)); + if (!strstr(paths.items[j], files->items[i])) { + continue; + } + const char *tname = nob_temp_sprintf("%s%s", test_folder, paths.items[j]); + printf("--- test %s ---\n", tname); + if (test_once(tname) == false) + return false; + } + } + + if (!prepare_build()) { + return 1; + } + + return true; +} + static bool delete_walk_entry(Nob_Walk_Entry entry) { return nob_delete_file(entry.path); } static bool delete_directory_recursively(const char *dir_path) { @@ -225,13 +374,24 @@ int main(int argc, char **argv) { } if (strcmp(command_name, "test") == 0) { - if (!prepare_build()) - return 1; - if (!build_target("test")) - return 1; - Nob_Cmd cmd = {0}; - nob_cmd_append(&cmd, BUILD_FOLDER "test"); - return nob_cmd_run(&cmd) ? 0 : 1; + Nob_Files files = {0}; + test_fn_t tfn = test_once; + if (argc > 0) { + const char *mode_name = nob_shift(argv, argc); + if (strcmp(mode_name, "ast") == 0) { + tfn = test_once_ast; + } else if (strcmp(mode_name, "sema") == 0) { + tfn = test_once_sema; + } else { + da_append(&files, mode_name); + } + } + + while (argc > 0) { + da_append(&files, nob_shift(argv, argc)); + } + + return run_test(&files, tfn) ? 0 : 1; } if (strcmp(command_name, "clean") == 0) { diff --git a/nob.h b/nob.h index 12b847e..d6d629c 100644 --- a/nob.h +++ b/nob.h @@ -1,3 +1,4 @@ +// clang-format off /* nob - v3.10.0 - Public Domain - https://github.com/tsoding/nob.h This library is the next generation of the [NoBuild](https://github.com/tsoding/nobuild) idea. diff --git a/nob_popen.h b/nob_popen.h new file mode 100644 index 0000000..bd4c850 --- /dev/null +++ b/nob_popen.h @@ -0,0 +1,54 @@ +#ifndef __NOB_POPEN_H__ +#define __NOB_POPEN_H__ + +#include "nob.h" + +typedef struct { + Nob_String_Builder out; // stdout 内容 + int exit_code; // 实际退出码 + bool ok; // 是否成功启动 +} Nob_Cmd_Result; + +typedef struct { + const char **items; + int capacity; + int count; +} Nob_Files; + +// 运行命令,捕获 stdout 和退出码(不支持 stdin 和 stderr) +bool nob_cmd_capture_popen(const char *tname, Nob_Cmd_Result *res) { + memset(res, 0, sizeof(*res)); + +#ifdef _WIN32 + FILE *fp = _popen(tname, "r"); +#else + FILE *fp = popen(tname, "r"); +#endif + + if (!fp) { + nob_log(NOB_ERROR, "popen failed"); + return false; + } + + // 读取输出到 String_Builder + char buffer[4096]; + while (fgets(buffer, sizeof(buffer), fp)) { + nob_sb_append_cstr(&res->out, buffer); + } + + // 获取退出码 +#ifdef _WIN32 + res->exit_code = _pclose(fp); +#else + res->exit_code = pclose(fp); + if (WIFEXITED(res->exit_code)) + res->exit_code = WEXITSTATUS(res->exit_code); +#endif + + res->ok = true; + return true; +} + +#define nob_cmd_result_free(res) nob_sb_free((res).out) + +#endif /* __NOB_POPEN_H__ */ diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index 4c22f22..e9af6e3 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -3,6 +3,12 @@ #include "spl_dumptree.h" #include "spl_tok.h" +#define MOVE_VEC(dst, src) \ + do { \ + (dst) = (src); \ + vec_init(src); \ + } while (0) + static char *sdupn(const char *s, usize n) { char *r = malloc(n + 1); if (!r) @@ -23,12 +29,38 @@ const char *spl_ast_kind_name(spl_ast_node_kind_t kind) { return "?"; } +const char *spl_binary_op_name(spl_binary_op_t op) { + static const char *const names[] = { +#define X(a, b, c, name) #name, + SPL_BINARY_OP_TABLE +#undef X + }; + if ((usize)op < sizeof(names) / sizeof(names[0])) + return names[op]; + return "?"; +} + +const char *spl_unary_op_name(spl_unary_op_t op) { + switch (op) { + case SPL_UNARY_OP_MINUS: + return "neg"; + case SPL_UNARY_OP_NOT: + return "not"; + case SPL_UNARY_OP_BIT_NOT: + return "bitnot"; + case SPL_UNARY_OP_ADDRESS: + return "addr"; + default: + 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; + int stop_agg; } parser_t; static inline int is_trivia(spl_tok_type_t t) { return t == TOK_ENDLINE || t == TOK_LINE_COMMENT; } @@ -59,6 +91,7 @@ static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const spl_ast_node_t n = {0}; n.kind = kind; n.resolved_def_id = 0; + n.resolved_type_id = 0; if (tok) { n.dbg.dbg_name = spl_ast_kind_name(kind); n.dbg.fname = tok->fname; @@ -69,51 +102,66 @@ static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const 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, +static char *intern_string(spl_ast_t *ast, const char *s, usize len) { + char *copy = sdupn(s, len); + if (!copy) + return NULL; + vec_push(ast->str_buckets, copy); + return copy; +} + +#define SET_STR_FIELD(ast, field, tok) \ + do { \ + (field) = intern_string(ast, (tok)->lexeme, (tok)->len); \ + } while (0) + +static spl_ast_node_ref_t mk_bin(parser_t *p, const spl_tok_t *loc, spl_binary_op_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; + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_BINARY, loc); + spl_ast_node_t *node = node_at(p->ast, ref); + node->binary.op = op; + node->binary.left = left; + node->binary.right = right; + return ref; +} + +static spl_ast_node_ref_t mk_unary(parser_t *p, const spl_tok_t *loc, spl_unary_op_t op, + spl_ast_node_ref_t operand) { + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_UNARY, loc); + spl_ast_node_t *node = node_at(p->ast, ref); + node->unary.op = op; + node->unary.operand = operand; return 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_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_type_comptime_call(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); -static spl_ast_node_ref_t parse_bool_or(parser_t *p); -static spl_ast_node_ref_t parse_bool_and(parser_t *p); -static spl_ast_node_ref_t parse_bit_or(parser_t *p); -static spl_ast_node_ref_t parse_bit_xor(parser_t *p); -static spl_ast_node_ref_t parse_bit_and(parser_t *p); -static spl_ast_node_ref_t parse_cmp_eq(parser_t *p); -static spl_ast_node_ref_t parse_cmp(parser_t *p); -static spl_ast_node_ref_t parse_range(parser_t *p); -static spl_ast_node_ref_t parse_shift(parser_t *p); -static spl_ast_node_ref_t parse_add(parser_t *p); -static spl_ast_node_ref_t parse_mul(parser_t *p); +static spl_ast_node_ref_t parse_var_pattern(parser_t *p); +static spl_ast_node_ref_t parse_match_pattern(parser_t *p); + static spl_ast_node_ref_t parse_prefix(parser_t *p); static spl_ast_node_ref_t parse_postfix(parser_t *p); static spl_ast_node_ref_t parse_primary(parser_t *p); -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_vec_t parse_aggregate_fields(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_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); -static spl_ast_node_ref_t parse_match(parser_t *p); -static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *paced_vec, - spl_ast_node_ref_vec_t *block_vec); -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_comptime_call(parser_t *p); +static spl_ast_node_ref_t parse_if_expr(parser_t *p); +static spl_ast_node_ref_t parse_while_expr(parser_t *p); +static spl_ast_node_ref_t parse_loop_expr(parser_t *p); +static spl_ast_node_ref_t parse_for_expr(parser_t *p); +static spl_ast_node_ref_t parse_match_expr(parser_t *p); +static spl_ast_node_ref_t parse_ret_stmt(parser_t *p); +static spl_ast_node_ref_t parse_break_stmt(parser_t *p); +static spl_ast_node_ref_t parse_continue_stmt(parser_t *p); +static spl_ast_node_ref_t parse_defer_stmt(parser_t *p); +static spl_ast_node_ref_t parse_comptime_stmt(parser_t *p); +static spl_ast_node_ref_t parse_label(parser_t *p); static isize parse_int_literal(const spl_tok_t *t) { char buf[128]; @@ -123,7 +171,6 @@ static isize parse_int_literal(const spl_tok_t *t) { buf[j++] = t->lexeme[i]; } buf[j] = 0; - /* strtoll base 0 不认 0b/0o 前缀:单独处理 */ if (j >= 3 && buf[0] == '0' && (buf[1] == 'b' || buf[1] == 'B')) return (isize)strtoll(buf + 2, NULL, 2); if (j >= 3 && buf[0] == '0' && (buf[1] == 'o' || buf[1] == 'O')) @@ -152,29 +199,29 @@ static char parse_char_literal(const spl_tok_t *t) { return c; } -static char *parse_string_literal(const spl_tok_t *t) { - const char *p = t->lexeme + 1; +static char *parse_string_literal(parser_t *p, const spl_tok_t *t) { + const char *src = t->lexeme + 1; const char *end = t->lexeme + t->len - 1; - char *out = (char *)malloc(t->len + 1); - if (!out) + usize cap = t->len + 1; + char *tmp = malloc(cap); + if (!tmp) return NULL; - char *o = out; - while (p < end) { + char *dst = tmp; + while (src < end) { char c; - if (spl_decode_escape(&p, &c) == 0) { - *o++ = c; + if (spl_decode_escape(&src, &c) == 0) { + *dst++ = c; } else { - /* 非法转义:宽松保留原字符 */ - *o++ = *p; - p++; + *dst++ = *src; + src++; } } - *o = 0; - return out; + *dst = '\0'; + char *interned = intern_string(p->ast, tmp, dst - tmp); + free(tmp); + return interned; } -// 起始判定 - static int can_start_expr(spl_tok_type_t t) { switch (t) { case TOK_INT_LITERAL: @@ -184,17 +231,24 @@ static int can_start_expr(spl_tok_type_t t) { case KW_TRUE: case KW_FALSE: case KW_NULL: + case KW_UNDEFINED: case TOK_IDENT: case TOK_AT: case TOK_SHARP: case TOK_L_PAREN: case TOK_L_BRACKET: case TOK_L_BRACE: + case TOK_DOT: case TOK_SUB: case TOK_NOT: case TOK_BIT_NOT: case TOK_AND: case TOK_MUL: + case KW_IF: + case KW_WHILE: + case KW_LOOP: + case KW_FOR: + case KW_MATCH: return 1; default: return 0; @@ -222,47 +276,59 @@ static int can_start_statement(spl_tok_type_t t) { } } -// 容器层声明 +static void parse_tag_list(parser_t *p, spl_ast_node_ref_vec_t *out, int is_external) { + while (!p->failed) { + const spl_tok_t *t = peek(p); + if (!t || (t->type != TOK_AT && t->type != TOK_SHARP)) + return; -static void parse_attr_list(parser_t *p, spl_ast_node_ref_vec_t *out) { - const spl_tok_t *t = NULL; - while (1) { - t = peek(p); - if (!t) - return; - if (t->type != TOK_AT && t->type != TOK_SHARP) - return; + int is_at = (t->type == TOK_AT); advance(p); + + if (is_external) { + t = peek(p); + if (!t || t->type != TOK_NOT) { + SPL_FATAL(t, "expected '!' in external tag"); + return; + } + advance(p); + } + t = peek(p); if (!t || t->type != TOK_IDENT) { - SPL_FATAL(t, "expected identifier after attribute"); + SPL_FATAL(t, "expected tag name"); return; } advance(p); - 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); + + spl_ast_node_ref_t ref = + new_node(p, is_external ? SPL_AST_EXTERNAL_TAG_ITEM : SPL_AST_TAG_ITEM, t); + spl_ast_node_t *tag = node_at(p->ast, ref); + tag->tag_item.is_at = is_at; + tag->tag_item.is_external = is_external; + SET_STR_FIELD(p->ast, tag->tag_item.name, t); + t = peek(p); - if (t != NULL && t->type == TOK_L_PAREN) { + if (t && 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; + tag->tag_item.args = parse_expr_list(p); t = peek(p); - if (t == NULL || t->type != TOK_R_PAREN) { - SPL_FATAL(t, "expected ')' to close attribute args"); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in tag args"); + return; } advance(p); - return; } vec_push(*out, ref); } } static void parse_param_list(parser_t *p, spl_ast_node_ref_vec_t *out) { - while (1) { + while (!p->failed) { const spl_tok_t *t = peek(p); - if (!t) { + if (!t) break; - } + if (t->type == TOK_R_PAREN) { break; } else if (t->type == TOK_AT || t->type == TOK_SHARP || t->type == TOK_IDENT) { @@ -275,7 +341,6 @@ static void parse_param_list(parser_t *p, spl_ast_node_ref_vec_t *out) { } break; } else if (t->type == TOK_ELLIPSIS) { - // 变长参数: 追加 name=NULL、type_expr=NULL 的空 param_decl advance(p); spl_ast_node_ref_t pd = new_node(p, SPL_AST_PARAM_DECL, t); node_at(p->ast, pd)->param_decl.name = NULL; @@ -285,13 +350,15 @@ static void parse_param_list(parser_t *p, spl_ast_node_ref_vec_t *out) { advance(p); break; } else if (t->type == KW_VOID) { - // fn(void): 无参写法 advance(p); t = peek(p); - Assert(t && t->type == TOK_R_PAREN); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' after void"); + } break; } else { - UNREACHABLE(); + SPL_FATAL(t, "unexpected token in parameter list"); + break; } } } @@ -299,16 +366,17 @@ static void parse_param_list(parser_t *p, spl_ast_node_ref_vec_t *out) { 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); + parse_tag_list(p, &attr_list, 0); + const spl_tok_t *name = peek(p); - if (!name || name->type != TOK_IDENT) { - SPL_FATAL(name, "expected parameter name"); + if (!name || (name->type != TOK_IDENT && name->type != KW_UNDERSCORE)) { + SPL_FATAL(name, "expected parameter name or '_'"); return 0; } advance(p); const spl_tok_t *t = peek(p); - if (t == NULL || t->type != TOK_COLON) { + if (!t || t->type != TOK_COLON) { SPL_FATAL(t, "expected ':' in parameter declaration"); return 0; } @@ -316,15 +384,17 @@ static spl_ast_node_ref_t parse_param_decl_impl(parser_t *p) { spl_ast_node_ref_t type_expr = parse_type_expr(p); 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; + spl_ast_node_t *param = node_at(p->ast, ref); + MOVE_VEC(param->param_decl.attr_list, attr_list); + SET_STR_FIELD(p->ast, param->param_decl.name, name); // 若为下划线则存储 "_" + param->param_decl.type_expr = type_expr; return ref; } -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_fn_decl(parser_t *p, spl_ast_node_ref_vec_t tag_list) { const spl_tok_t *kw = peek(p); - Assert(kw && kw->type == KW_FN); + if (!kw || kw->type != KW_FN) + return 0; advance(p); const spl_tok_t *name = peek(p); @@ -335,55 +405,55 @@ static spl_ast_node_ref_t parse_fn_decl(parser_t *p, spl_ast_node_ref_vec_t attr advance(p); const spl_tok_t *t = peek(p); - if (t == NULL || t->type != TOK_L_PAREN) { + if (!t || 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); + spl_ast_node_ref_vec_t params; + vec_init(params); + parse_param_list(p, ¶ms); t = peek(p); - if (t == NULL || t->type != TOK_R_PAREN) { + if (!t || 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_t block = 0; - int has_body = 0; - + spl_ast_node_ref_t ret_type = 0; t = peek(p); - Assert(t != NULL); - if (t->type != TOK_SEMICOLON && t->type != TOK_L_BRACE) { - type_expr = parse_type_expr(p); + if (t && t->type == TOK_COLON) { + advance(p); + ret_type = parse_type_expr(p); t = peek(p); } - if (t && t->type == TOK_SEMICOLON) { + spl_ast_node_ref_t body = 0; + if (t && t->type == TOK_L_BRACE) { + body = parse_block(p); + } else if (t && t->type == TOK_SEMICOLON) { advance(p); - } else if (t && t->type == TOK_L_BRACE) { - block = parse_block(p); - has_body = 1; } else { - SPL_FATAL(t, "function declaration must end with ';' or a block"); + SPL_FATAL(t, "function declaration must end with ';' or block"); + return 0; } - 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); - node_at(p->ast, ref)->fn_decl.param_list = param_list; - node_at(p->ast, ref)->fn_decl.type_expr = type_expr; - node_at(p->ast, ref)->fn_decl.block = block; + spl_ast_node_ref_t ref = new_node(p, SPL_AST_FN_DECL, kw); + spl_ast_node_t *fn = node_at(p->ast, ref); + MOVE_VEC(fn->fn_decl.tag_list, tag_list); + fn->fn_decl.is_comptime = 0; + SET_STR_FIELD(p->ast, fn->fn_decl.name, name); + fn->fn_decl.params = params; /* params 局部变量,直接转移 */ + fn->fn_decl.ret_type = ret_type; + fn->fn_decl.body = body; return ref; } -static spl_ast_node_ref_t parse_type_decl(parser_t *p, spl_ast_node_ref_vec_t attr_list) { - (void)attr_list; +static spl_ast_node_ref_t parse_type_decl(parser_t *p, spl_ast_node_ref_vec_t tag_list) { const spl_tok_t *kw = peek(p); - Assert(kw && kw->type == KW_TYPE); + if (!kw || kw->type != KW_TYPE) + return 0; advance(p); const spl_tok_t *name = peek(p); @@ -394,70 +464,79 @@ static spl_ast_node_ref_t parse_type_decl(parser_t *p, spl_ast_node_ref_vec_t at advance(p); const spl_tok_t *t = peek(p); - if (t == NULL || t->type != TOK_ASSIGN) { + if (!t || 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; + spl_ast_node_t *td = node_at(p->ast, ref); + MOVE_VEC(td->type_decl.attr_list, tag_list); + SET_STR_FIELD(p->ast, td->type_decl.name, name); + td->type_decl.type_expr = parse_type_expr(p); + t = peek(p); if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) { advance(p); - } else { - SPL_WARN(t, "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) { - const spl_tok_t *name = peek(p); - Assert(name && name->type == TOK_IDENT); +static spl_ast_node_ref_t parse_var_const_decl(parser_t *p, spl_ast_node_ref_vec_t tag_list, + int is_const) { + const spl_tok_t *kw = peek(p); + if (!kw) + return 0; + if (is_const && kw->type != KW_CONST) + return 0; + if (!is_const && kw->type != KW_VAR) + return 0; advance(p); - const spl_tok_t *t = NULL; + spl_ast_node_ref_t pattern = parse_var_pattern(p); + if (!pattern) + return 0; + spl_ast_node_ref_t type_expr = 0; - t = peek(p); + spl_ast_node_ref_t init_expr = 0; + 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); + init_expr = parse_expr(p); + } + } else if (t && t->type == TOK_ASSIGN) { + advance(p); + init_expr = parse_expr(p); } - spl_ast_node_ref_t ref = new_node(p, SPL_AST_MEMBER_DECL, name); - 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_ast_node_ref_t ref = new_node(p, is_const ? SPL_AST_CONST_DECL : SPL_AST_VAR_DECL, kw); + spl_ast_node_t *vc = node_at(p->ast, ref); + MOVE_VEC(vc->var_const_decl.attr_list, tag_list); + vc->var_const_decl.pattern = pattern; + vc->var_const_decl.type = type_expr; + vc->var_const_decl.init_expr = init_expr; + t = peek(p); - if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) { + if (t && t->type == TOK_SEMICOLON) { advance(p); - } else { - SPL_WARN(t, "need comma or semicolon with member decl"); } return ref; } -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); - +static spl_ast_node_ref_t parse_member_decl(parser_t *p, spl_ast_node_ref_vec_t tag_list) { const spl_tok_t *name = peek(p); - if (!name || name->type != TOK_IDENT) { - SPL_FATAL(name ? name : kw, "expected variable name"); + if (!name || name->type != TOK_IDENT) return 0; - } advance(p); spl_ast_node_ref_t type_expr = 0; - spl_ast_node_ref_t expr = 0; + spl_ast_node_ref_t init_expr = 0; const spl_tok_t *t = peek(p); if (t && t->type == TOK_COLON) { advance(p); @@ -465,1221 +544,224 @@ static spl_ast_node_ref_t parse_var_const_decl(parser_t *p, spl_ast_node_ref_vec 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"); + init_expr = parse_expr(p); } - } else if (t && t->type == TOK_COLON_ASSIGN) { + } else if (t && t->type == TOK_ASSIGN) { advance(p); - expr = parse_expr(p); + init_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; + spl_ast_node_ref_t ref = new_node(p, SPL_AST_MEMBER_DECL, name); + spl_ast_node_t *md = node_at(p->ast, ref); + MOVE_VEC(md->member_decl.attr_list, tag_list); + SET_STR_FIELD(p->ast, md->member_decl.name, name); + md->member_decl.type_expr = type_expr; + md->member_decl.init_expr = init_expr; + t = peek(p); - if (t && t->type == TOK_SEMICOLON) { + if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) { advance(p); - } else { - SPL_WARN(t, "need semicolon in decl var/const"); } return ref; } +static spl_ast_node_ref_t parse_comptime_decl(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_COMPTIME) + return 0; + advance(p); + + spl_ast_node_ref_t body = 0; + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_L_BRACE) { + body = parse_block(p); + } else { + body = parse_expr(p); + } + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_COMPTIME_DECL, kw); + node_at(p->ast, ref)->comptime_decl.body = body; + return ref; +} + 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_ast_node_ref_vec_t tag_list; + vec_init(tag_list); + parse_tag_list(p, &tag_list, 0); /* 只解析普通 tag */ + const spl_tok_t *t = peek(p); if (!t || t->type == TOK_EOF) { - SPL_FATAL(t, "unexpected end of file"); - return 0; - } - if (t->type == TOK_L_BRACE) { - /* DirectiveBlock(@init {} / #test {}):不实现 */ - SPL_FATAL(t, "not implemented: @/# directive block"); + vec_free(tag_list); return 0; } + switch (t->type) { case KW_FN: - return parse_fn_decl(p, attr_list); + return parse_fn_decl(p, tag_list); case KW_TYPE: - return parse_type_decl(p, attr_list); + return parse_type_decl(p, tag_list); case KW_VAR: - return parse_var_const_decl(p, attr_list, false); + return parse_var_const_decl(p, tag_list, 0); case KW_CONST: - return parse_var_const_decl(p, attr_list, true); + return parse_var_const_decl(p, tag_list, 1); case TOK_IDENT: - return parse_member_decl(p, attr_list); + return parse_member_decl(p, tag_list); case KW_COMPTIME: - SPL_FATAL(t, "not implemented: comptime statement"); - return 0; + vec_free(tag_list); /* comptime decl 不使用 tag_list */ + return parse_comptime_decl(p); + case TOK_L_BRACE: { + spl_ast_node_ref_t block = parse_block(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TOP_LEVEL_BLOCK, t); + spl_ast_node_t *tb = node_at(p->ast, ref); + MOVE_VEC(tb->top_level_block.tag_list, tag_list); + tb->top_level_block.block = block; + return ref; + } default: SPL_FATAL(t, "unrecognized declaration"); + vec_free(tag_list); return 0; } } -// 语句 - -static spl_ast_node_ref_t parse_block(parser_t *p) { - spl_ast_node_ref_vec_t vec; - vec_init(vec); - const spl_tok_t *t = peek(p); - if (t == NULL || t->type != TOK_L_BRACE) { - SPL_FATAL(t, "expected '{'"); - return 0; - } - advance(p); - while (!p->failed) { - t = peek(p); - if (!t || t->type == TOK_EOF) { - SPL_FATAL(t, "block missing '}'"); - return 0; - } - if (t->type == TOK_R_BRACE) { - advance(p); - break; - } - if (can_start_statement(t->type)) { - spl_ast_node_ref_t s = parse_statement(p); - if (s) { - vec_push(vec, s); - } else { - UNREACHABLE(); - } - } else if (can_start_expr(t->type)) { - spl_ast_node_ref_t e = parse_expr(p); - t = peek(p); - if (t && t->type == TOK_SEMICOLON) { - advance(p); - vec_push(vec, e); - } else { - // Tail expretion - UNREACHABLE(); - } - } else { - SPL_FATAL(t, "unrecognized statement"); - } - } - spl_ast_node_ref_t block_expr_ref = new_node(p, SPL_AST_BLOCK_EXPR, t); // FIXME t not here - node_at(p->ast, block_expr_ref)->primary_expr.block_expr = vec; - return block_expr_ref; -} - -static spl_ast_node_ref_t parse_statement(parser_t *p) { +static spl_ast_node_ref_t parse_var_pattern_atom(parser_t *p) { const spl_tok_t *t = peek(p); if (!t) return 0; - switch (t->type) { - case KW_IF: - return parse_if(p); - case KW_WHILE: - return parse_while(p); - case KW_LOOP: - return parse_loop(p); - case KW_FOR: - return parse_for(p); - case KW_MATCH: - return parse_match(p); - case KW_RET: - return parse_ret(p); - case KW_BREAK: - return parse_break(p); - case KW_CONTINUE: - return parse_continue(p); - case KW_DEFER: - return parse_defer(p); - case KW_VAR: { - spl_ast_node_ref_vec_t al; - vec_init(al); - return parse_var_const_decl(p, al, false); - } - case KW_CONST: { - spl_ast_node_ref_vec_t al; - vec_init(al); - return parse_var_const_decl(p, al, true); - } - case KW_TYPE: { - spl_ast_node_ref_vec_t al; - vec_init(al); - return parse_type_decl(p, al); - } - case KW_COMPTIME: - SPL_FATAL(t, "not implemented: comptime statement"); - return 0; - default: - SPL_FATAL(t, "unrecognized statement"); - return 0; - } -} -static spl_ast_node_ref_t parse_if(parser_t *p) { - const spl_tok_t *kw = peek(p); - Assert(kw && kw->type == KW_IF); - advance(p); - - int is_ifvar = false; - char *bind = NULL; - const spl_tok_t *name = NULL; - const spl_tok_t *t = peek(p); - if (t && t->type == KW_VAR) { - advance(p); - 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); - 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_t if_block = parse_block(p); - spl_ast_node_ref_t else_block = 0; - t = peek(p); - if (t && t->type == KW_ELSE) { - advance(p); - t = peek(p); - if (t && t->type == KW_IF) { - spl_ast_node_ref_vec_t elseif_block; - vec_init(elseif_block); - vec_push(elseif_block, parse_if(p)); - else_block = new_node(p, SPL_AST_BLOCK_EXPR, t); // FIXME t not here - node_at(p->ast, else_block)->primary_expr.block_expr = elseif_block; - } else { - else_block = parse_block(p); - } - } - - 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) { - 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_t block = parse_block(p); - 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) { - const spl_tok_t *kw = peek(p); - Assert(kw && kw->type == KW_LOOP); - advance(p); - spl_ast_node_ref_t block = parse_block(p); - 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) { - 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); - - // 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; - - const spl_tok_t *t = peek(p); - if (t == NULL || t->type != KW_AS) { - SPL_FATAL(t, "expected 'as' in for"); - return 0; - } - 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)->for_statement.ident_vec, sdupn(t->lexeme, t->len)); - while (peek(p) && peek(p)->type == TOK_COMMA) { - advance(p); - 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)->for_statement.ident_vec, sdupn(t->lexeme, t->len)); - } - spl_ast_node_ref_t fblock = parse_block(p); - node_at(p->ast, s)->for_statement.block = fblock; - return s; -} - -static spl_ast_node_ref_t parse_match(parser_t *p) { - 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--; - - 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) { - t = peek(p); - if (!t || t->type == TOK_EOF) { - SPL_FATAL(t, "match missing '}'"); - break; - } - if (t->type == TOK_R_BRACE) { - advance(p); - break; - } - if (!parse_match_arm(p, &paced_vec, &stmt_vec)) - break; - t = peek(p); - if (t && t->type == TOK_COMMA) - advance(p); - } - 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; - - spl_ast_node_ref_t stmt_block = new_node(p, SPL_AST_BLOCK_EXPR, t); // FIXME t not here - node_at(p->ast, stmt_block)->primary_expr.block_expr = stmt_vec; - node_at(p->ast, s)->match_statement.match_block = stmt_block; - return s; -} - -static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *paced_vec, - spl_ast_node_ref_vec_t *block_vec) { - const spl_tok_t *t = peek(p); - if (!t) - return 0; - spl_ast_node_ref_vec_t modes; - vec_init(modes); - while (1) { - const spl_tok_t *mt = peek(p); - if (!mt) { - SPL_FATAL(mt, "invalid match arm pattern"); - return 0; - } - 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); - const spl_tok_t *name = peek(p); - if (!name || name->type != TOK_IDENT) { - 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); - const spl_tok_t *b = peek(p); - if (!b || b->type != TOK_IDENT) { - 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); - - 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) { - 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); - } - } 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 { - SPL_FATAL(mt, "invalid match arm pattern"); - return 0; - } - vec_push(modes, pk); - if (peek(p) && peek(p)->type == TOK_COMMA) { - advance(p); - continue; - } - break; - } - - 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_t body = parse_block(p); - for (usize i = 0; i < modes.size; i++) { - vec_push(*paced_vec, modes.data[i]); - vec_push(*block_vec, body); - } - vec_free(modes); - return 1; -} - -static spl_ast_node_ref_t parse_ret(parser_t *p) { - const spl_tok_t *kw = peek(p); - Assert(kw && kw->type == KW_RET); - advance(p); - spl_ast_node_ref_t expr = 0; - - const spl_tok_t *t = peek(p); - if (t && can_start_expr(t->type)) - expr = parse_expr(p); - t = peek(p); - if (t && t->type == TOK_SEMICOLON) - advance(p); - 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) { - 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); - return new_node(p, SPL_AST_BREAK_STATEMENT, kw); -} - -static spl_ast_node_ref_t parse_continue(parser_t *p) { - 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); - return new_node(p, SPL_AST_CONTINUE_STATEMENT, kw); -} - -static spl_ast_node_ref_t parse_defer(parser_t *p) { - 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); - - const spl_tok_t *t = peek(p); - // FIXME parse maybe error - if (t && t->type == TOK_L_BRACE) { - vec_push(vec, parse_block(p)); - } else if (t && can_start_statement(t->type)) { - spl_ast_node_ref_t st = parse_statement(p); - if (st) - vec_push(vec, st); - } else { - spl_ast_node_ref_t e = parse_expr(p); - t = peek(p); - if (t && t->type == TOK_SEMICOLON) - advance(p); - vec_push(vec, e); - } - 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 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; - case TOK_ASSIGN_MUL: - return SPL_AST_ASSIGN_MUL_EXPR; - case TOK_ASSIGN_DIV: - return SPL_AST_ASSIGN_DIV_EXPR; - case TOK_ASSIGN_MOD: - return SPL_AST_ASSIGN_MOD_EXPR; - case TOK_ASSIGN_AND: - return SPL_AST_ASSIGN_AND_EXPR; - case TOK_ASSIGN_OR: - return SPL_AST_ASSIGN_OR_EXPR; - case TOK_ASSIGN_XOR: - return SPL_AST_ASSIGN_XOR_EXPR; - case TOK_ASSIGN_L_SH: - return SPL_AST_ASSIGN_LSHIFT_EXPR; - case TOK_ASSIGN_R_SH: - return SPL_AST_ASSIGN_RSHIFT_EXPR; - default: - return SPL_AST_COUNT; - } -} - -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; - 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); - return mk_bin(p, t, op, left, right); -} - -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) { - 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_BOOL_OR_EXPR, left, right); - } - return left; -} - -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) { - 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_BOOL_AND_EXPR, left, right); - } - return left; -} - -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) { - 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_BIT_OR_EXPR, left, right); - } - return left; -} - -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) { - 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_BIT_XOR_EXPR, left, right); - } - return left; -} - -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) { - 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_BIT_AND_EXPR, left, right); - } - return left; -} - -static spl_ast_node_ref_t parse_cmp_eq(parser_t *p) { - spl_ast_node_ref_t left = parse_cmp(p); - while (!p->failed) { - 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_CMP_EQ_EXPR; - else if (t->type == TOK_NEQ) - op = SPL_AST_CMP_NE_EXPR; - } - if (op == SPL_AST_COUNT) - break; - advance(p); - spl_ast_node_ref_t right = parse_cmp(p); - left = mk_bin(p, t, op, left, right); - } - return left; -} - -static spl_ast_node_ref_t parse_cmp(parser_t *p) { - spl_ast_node_ref_t left = parse_range(p); - while (!p->failed) { - 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; - else if (t->type == TOK_GT) - op = SPL_AST_CMP_GT_EXPR; - else if (t->type == TOK_LE) - op = SPL_AST_CMP_LE_EXPR; - else if (t->type == TOK_GE) - op = SPL_AST_CMP_GE_EXPR; - } - if (op == SPL_AST_COUNT) - break; - advance(p); - spl_ast_node_ref_t right = parse_range(p); - left = mk_bin(p, t, op, left, right); - } - return left; -} - -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; - const spl_tok_t *t = peek(p); - if (t && t->type == TOK_RANGE) { - advance(p); - spl_ast_node_ref_t right = 0; /* a.. 无右端点 */ - if (peek(p) && can_start_expr(peek(p)->type)) - right = parse_shift(p); - left = mk_bin(p, t, SPL_AST_RANGE_EXPR, left, right); - } - return left; -} - -static spl_ast_node_ref_t parse_shift(parser_t *p) { - spl_ast_node_ref_t left = parse_add(p); - while (!p->failed) { - 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 == SPL_AST_COUNT) - break; - advance(p); - spl_ast_node_ref_t right = parse_add(p); - left = mk_bin(p, t, op, left, right); - } - return left; -} - -static spl_ast_node_ref_t parse_add(parser_t *p) { - spl_ast_node_ref_t left = parse_mul(p); - while (!p->failed) { - 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 == SPL_AST_COUNT) - break; - advance(p); - spl_ast_node_ref_t right = parse_mul(p); - left = mk_bin(p, t, op, left, right); - } - return left; -} - -static spl_ast_node_ref_t parse_mul(parser_t *p) { - spl_ast_node_ref_t left = parse_prefix(p); - while (!p->failed) { - 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; - else if (t->type == TOK_DIV) - op = SPL_AST_DIV_EXPR; - else if (t->type == TOK_MOD) - op = SPL_AST_MOD_EXPR; - } - if (op == SPL_AST_COUNT) - break; - advance(p); - spl_ast_node_ref_t right = parse_prefix(p); - left = mk_bin(p, t, op, left, right); - } - return left; -} - -static spl_ast_node_ref_t parse_prefix(parser_t *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); - } - 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; -} - -static spl_ast_node_ref_t parse_postfix(parser_t *p) { - spl_ast_node_ref_t expr = parse_primary(p); - while (!p->failed) { - 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_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; - - t = peek(p); - if (t == NULL || t->type != TOK_R_PAREN) { - SPL_FATAL(t, "expected ')' in call"); - return expr; - } - advance(p); - expr = pf; - } else if (t->type == TOK_DOT) { - advance(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_DEREF_EXPR, t); - node_at(p->ast, pf)->postfix_expr.primary_expr = expr; - expr = pf; - } else if (n && n->type == TOK_IDENT) { - advance(p); - 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 = pf; - } else { - SPL_FATAL(n, "expected identifier or '*' after '.'"); - break; - } - } else if (t->type == TOK_L_BRACKET) { - advance(p); - 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); - - t = peek(p); - if (t == NULL || t->type != TOK_R_BRACKET) { - SPL_FATAL(t, "expected ']' in slice"); - return 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 = pf; - } else { - t = peek(p); - if (t == NULL || t->type != TOK_R_BRACKET) { - SPL_FATAL(t, "expected ']' in index"); - return 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 = 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_AS_EXPR, t); - node_at(p->ast, pf)->postfix_expr.primary_expr = expr; - node_at(p->ast, pf)->postfix_expr.type_expr = te; - expr = pf; - } else { - break; - } - } - return 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; - 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; // 尾逗号宽容 - vec_push(vec, parse_expr(p)); - } - return 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); - - 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) { - t = peek(p); - if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF) - break; - - t = peek(p); - if (t == NULL || t->type != TOK_DOT) { - SPL_FATAL(t, "expected '.' in struct init"); - return agg_vec; - } - advance(p); - - 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); - node_at(p->ast, item)->aggregate_init_item.expr = ae; - } - vec_push(agg_vec, item); - if (peek(p) && peek(p)->type == TOK_COMMA) { - advance(p); - continue; - } - break; - } - 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) { - const spl_tok_t *t = peek(p); - if (!t) { - SPL_FATAL(t, "unexpected expression start"); - return 0; - } - switch (t->type) { - case TOK_INT_LITERAL: { - advance(p); - 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 pr; - } - case TOK_FLOAT_LITERAL: { - advance(p); - 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 pr; - } - case TOK_CHAR_LITERAL: { - advance(p); - 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 pr; - } - case TOK_STRING_LITERAL: { - advance(p); - 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 pr; - } - case KW_TRUE: { - advance(p); - return new_node(p, SPL_AST_EXPR_TRUE, t); - } - case KW_FALSE: { - advance(p); - return new_node(p, SPL_AST_EXPR_FALSE, t); - } - case KW_NULL: { - advance(p); - 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) { - spl_ast_node_ref_vec_t agg_vec = parse_aggregate_init_body(p); - 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 pr; - } - 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 pr; - } - case TOK_DOT: { - advance(p); - const spl_tok_t *nx = peek(p); - if (nx && nx->type == TOK_L_BRACE && !p->stop_agg) { - spl_ast_node_ref_vec_t agg_vec = parse_aggregate_init_body(p); - 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 pr; - } - SPL_FATAL(t, "unexpected '.' in expression"); - return 0; - } - case KW_ANY: - SPL_FATAL(t, "unexpected '_' in expression"); - return 0; - case TOK_AT: - case TOK_SHARP: - return parse_builtin(p); - case TOK_L_PAREN: { - advance(p); - spl_ast_node_ref_t e = parse_expr(p); - - t = peek(p); - if (t == NULL || t->type != TOK_R_PAREN) { - SPL_FATAL(t, "expected ')' in parenthesized expression"); - return e; - } - advance(p); - return e; - } - case TOK_L_BRACKET: - return parse_array_literal(p); - case TOK_L_BRACE: { - spl_ast_node_ref_t pr = parse_block(p); - return pr; - } - default: - SPL_FATAL(t, "unrecognized expression"); - return 0; - } -} - -static spl_ast_node_ref_t parse_builtin(parser_t *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) { - SPL_FATAL(name, "expected builtin name"); - return 0; - } - advance(p); - - 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); - - t = peek(p); - if (t == NULL || t->type != TOK_R_PAREN) { - SPL_FATAL(t, "expected ')' in builtin call"); - return 0; - } - 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 pr; -} - -static spl_ast_node_ref_t parse_array_literal(parser_t *p) { - const spl_tok_t *t = peek(p); - advance(p); /* L_BRACKET */ - isize integer = 0; - - t = peek(p); - if (t && t->type == TOK_INT_LITERAL) { - integer = parse_int_literal(t); - advance(p); - } - - 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); - - 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); - - t = peek(p); - if (t == NULL || t->type != TOK_R_BRACE) { - SPL_FATAL(t, "expected '}' in array literal"); - return 0; - } - 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 pr; -} - -static spl_ast_node_ref_t parse_expr(parser_t *p) { return parse_assign(p); } - -// 类型表达式 - -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; - } -} - -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); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_PATTERN_IDENT, t); + SET_STR_FIELD(p->ast, node_at(p->ast, ref)->pattern_ident.name, t); return ref; - } - if (t->type == TOK_L_BRACKET) { + } else if (t->type == KW_UNDERSCORE) { advance(p); - spl_ast_node_ref_t sz = 0; + return new_node(p, SPL_AST_PATTERN_UNDERSCORE, t); + } else if (t->type == TOK_DOT) { + advance(p); + const spl_tok_t *name = peek(p); + if (!name || name->type != TOK_IDENT) { + SPL_FATAL(name, "expected identifier after '.' in pattern"); + return 0; + } + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_PATTERN_DOT, t); + spl_ast_node_t *pat = node_at(p->ast, ref); + SET_STR_FIELD(p->ast, pat->pattern_dot.name, name); - 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)); + if (peek(p) && peek(p)->type == TOK_L_BRACKET) { + advance(p); + pat->pattern_dot.sub_pattern = parse_var_pattern(p); + t = peek(p); + if (!t || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in pattern"); + return 0; + } advance(p); } - + return ref; + } else if (t->type == TOK_L_PAREN) { + advance(p); + spl_ast_node_ref_t inner = parse_var_pattern(p); t = peek(p); - if (t == NULL || t->type != TOK_R_BRACKET) { - SPL_FATAL(t, "expected ']' in array type"); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in pattern"); 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); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_PATTERN_TUPLE, t); + spl_ast_node_t *tuple = node_at(p->ast, ref); + vec_init(tuple->pattern_tuple.patterns); + if (node_at(p->ast, inner)->kind == SPL_AST_PATTERN_LIST) { + tuple->pattern_tuple.patterns = node_at(p->ast, inner)->pattern_list.patterns; } 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; + vec_push(tuple->pattern_tuple.patterns, inner); } - Assert(ref != 0); + return ref; + } else { + SPL_FATAL(t, "unexpected token in pattern"); + return 0; + } +} + +static spl_ast_node_ref_t parse_var_pattern(parser_t *p) { + spl_ast_node_ref_vec_t patterns; + vec_init(patterns); + + while (!p->failed) { + spl_ast_node_ref_t atom = parse_var_pattern_atom(p); + if (!atom) + break; + vec_push(patterns, atom); + + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_COMMA) { + advance(p); + continue; + } + break; + } + + if (patterns.size == 0) + return 0; + if (patterns.size == 1) { + spl_ast_node_ref_t ref = patterns.data[0]; + vec_free(patterns); return ref; } - return parse_type_base(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_PATTERN_LIST, peek(p)); + node_at(p->ast, ref)->pattern_list.patterns = patterns; + return ref; +} + +static spl_ast_node_ref_t parse_match_pattern(parser_t *p) { + const spl_tok_t *t = peek(p); + if (!t) + return 0; + + /* 如果当前 token 是模式专用起始符,按变量模式解析;否则按表达式解析 */ + if (t->type == KW_UNDERSCORE || t->type == TOK_DOT || t->type == TOK_L_PAREN) { + return parse_var_pattern(p); + } else { + /* 表达式模式:字面量、标识符、块、if 等 */ + return parse_expr(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); + spl_ast_node_ref_vec_t tag_list; + vec_init(tag_list); + parse_tag_list(p, &tag_list, 0); - spl_ast_node_ref_t base = 0; const spl_tok_t *bt = peek(p); if (!bt) { - SPL_FATAL(bt, "expected type base"); + vec_free(tag_list); + SPL_FATAL(bt, "expected type"); return 0; } - const spl_tok_t *t = NULL; + /* 函数类型 */ if (bt->type == KW_FN) { - advance(p); /* KW_FN */ - - t = peek(p); - if (t == NULL || t->type != TOK_L_PAREN) { + vec_free(tag_list); + advance(p); + const spl_tok_t *t = peek(p); + if (!t || 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); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_FN, bt); + spl_ast_node_t *fn_type = node_at(p->ast, ref); + fn_type->type_fn.is_comptime = 0; + vec_init(fn_type->type_fn.params); + while (!p->failed && peek(p) && peek(p)->type != TOK_R_PAREN) { spl_ast_node_ref_t pt = parse_type_expr(p); - vec_push(param_list, pt); + fn_type = node_at(p->ast, ref); // 防悬空 + vec_push(fn_type->type_fn.params, pt); if (peek(p) && peek(p)->type == TOK_COMMA) { advance(p); continue; @@ -1688,86 +770,1377 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) { } t = peek(p); - if (t == NULL || t->type != TOK_R_PAREN) { + if (!t || t->type != TOK_R_PAREN) { SPL_FATAL(t, "expected ')' in function type"); return 0; } advance(p); - 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 (peek(p) && peek(p)->type == TOK_COLON) { + advance(p); + fn_type = node_at(p->ast, ref); + fn_type->type_fn.ret_type = parse_type_expr(p); + } + return ref; } - 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) { + /* 聚合类型:struct / union / enum / shape */ + if (bt->type == KW_STRUCT || bt->type == KW_UNION || bt->type == KW_ENUM || + bt->type == KW_SHAPE) { + vec_free(tag_list); /* 聚合类型不使用 tag_list */ + const char *kind_name = (bt->type == KW_STRUCT) ? "struct" + : (bt->type == KW_UNION) ? "union" + : (bt->type == KW_ENUM) ? "enum" + : "shape"; + advance(p); + const spl_tok_t *t = peek(p); + if (!t || 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_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_AGGREGATE, bt); + spl_ast_node_t *agg = node_at(p->ast, ref); + agg->type_aggregate.kind_name = kind_name; + vec_init(agg->type_aggregate.members); // 存放真正的容器声明节点 + + /* 解析容器成员,直到 '}' */ + while (!p->failed) { t = peek(p); - if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF) + if (!t || t->type == TOK_EOF) { + SPL_FATAL(t, "aggregate type missing '}'"); + return ref; + } + if (t->type == TOK_R_BRACE) { + advance(p); break; - spl_ast_node_ref_t md = parse_container_declaration(p); - if (md) - vec_push(members, md); + } + + spl_ast_node_ref_t member = parse_container_declaration(p); + if (member) { + agg = node_at(p->ast, ref); // 防止节点数组扩容导致悬空 + vec_push(agg->type_aggregate.members, member); + } + + /* 跳过可选分隔符 */ + t = peek(p); + if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) { + advance(p); + } + } + return ref; + } + + /* 内建类型和普通路径 */ + if (bt->type == TOK_IDENT) { + const char *name = bt->lexeme; + usize len = bt->len; + /* 内建类型关键字 */ + if ((len == 2 && strncmp(name, "i8", 2) == 0) || + (len == 2 && strncmp(name, "u8", 2) == 0) || + (len == 3 && strncmp(name, "i16", 3) == 0) || + (len == 3 && strncmp(name, "u16", 3) == 0) || + (len == 3 && strncmp(name, "i32", 3) == 0) || + (len == 3 && strncmp(name, "u32", 3) == 0) || + (len == 3 && strncmp(name, "i64", 3) == 0) || + (len == 3 && strncmp(name, "u64", 3) == 0) || + (len == 5 && strncmp(name, "isize", 5) == 0) || + (len == 5 && strncmp(name, "usize", 5) == 0) || + (len == 3 && strncmp(name, "f32", 3) == 0) || + (len == 3 && strncmp(name, "f64", 3) == 0) || + (len == 4 && strncmp(name, "bool", 4) == 0) || + (len == 4 && strncmp(name, "void", 4) == 0) || + (len == 3 && strncmp(name, "ptr", 3) == 0)) { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PATH, bt); + spl_ast_node_t *tp = node_at(p->ast, ref); + SET_STR_FIELD(p->ast, tp->type_path.name, bt); + vec_init(tp->type_path.generic_args); + vec_free(tag_list); + return ref; + } + + /* 普通类型路径 */ + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PATH, bt); + spl_ast_node_t *tp = node_at(p->ast, ref); + SET_STR_FIELD(p->ast, tp->type_path.name, bt); + vec_init(tp->type_path.generic_args); + + while (peek(p) && peek(p)->type == TOK_DOT) { + advance(p); + const spl_tok_t *seg = peek(p); + if (!seg || seg->type != TOK_IDENT) { + SPL_FATAL(seg, "expected identifier after '.' in type path"); + break; + } + advance(p); + } + vec_free(tag_list); + return ref; + } + + if (bt->type == TOK_AT || bt->type == TOK_SHARP) { + vec_free(tag_list); + return parse_type_comptime_call(p); + } + + vec_free(tag_list); + SPL_FATAL(bt, "unrecognized type"); + return 0; +} + +static spl_ast_node_ref_t parse_type_comptime_call(parser_t *p) { + const spl_tok_t *start = peek(p); + if (!start || (start->type != TOK_AT && start->type != TOK_SHARP)) + return 0; + advance(p); + + const spl_tok_t *name = peek(p); + if (!name || name->type != TOK_IDENT) { + SPL_FATAL(name, "expected comptime call name"); + return 0; + } + advance(p); + + const spl_tok_t *t = peek(p); + if (!t || t->type != TOK_L_PAREN) { + SPL_FATAL(t, "expected '(' in comptime call"); + return 0; + } + advance(p); + + spl_ast_node_ref_vec_t args = parse_expr_list(p); + + t = peek(p); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in comptime call"); + return 0; + } + advance(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_COMPTIME_CALL, start); + spl_ast_node_t *cc = node_at(p->ast, ref); + SET_STR_FIELD(p->ast, cc->type_comptime_call.name, name); + cc->type_comptime_call.args = args; + return ref; +} + +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_pointer.pointee = parse_type_expr(p); + return ref; + } + + if (t->type == TOK_L_BRACKET) { + advance(p); + bool has_len = false; + isize len = 0; + bool is_underscore = false; + + t = peek(p); + if (t && t->type == TOK_INT_LITERAL) { + len = parse_int_literal(t); + has_len = true; + advance(p); + } else if (t && t->type == KW_UNDERSCORE) { + has_len = true; + is_underscore = true; + advance(p); } t = peek(p); - if (t == NULL || t->type != TOK_R_BRACE) { - SPL_FATAL(t, "expected '}' in aggregate type"); + if (!t || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in array 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; + spl_ast_node_ref_t elem_type = parse_type_expr(p); + + spl_ast_node_ref_t ref; + if (has_len) { + ref = new_node(p, SPL_AST_TYPE_ARRAY, t); + spl_ast_node_t *arr = node_at(p->ast, ref); + arr->type_array.has_len = true; + arr->type_array.len = len; + arr->type_array.is_underscore_len = is_underscore; + arr->type_array.elem_type = elem_type; + } else { + ref = new_node(p, SPL_AST_TYPE_SLICE, t); + node_at(p->ast, ref)->type_slice.elem_type = elem_type; + } + return ref; } - 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) { + if (t->type == TOK_L_PAREN) { + advance(p); + spl_ast_node_ref_vec_t types; + vec_init(types); + + if (peek(p) && peek(p)->type == TOK_R_PAREN) { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PAREN, t); + node_at(p->ast, ref)->type_paren.types = types; + return ref; + } + + spl_ast_node_ref_t first = parse_type_expr(p); + vec_push(types, first); + + while (peek(p) && peek(p)->type == TOK_COMMA) { + advance(p); + if (peek(p) && peek(p)->type == TOK_R_PAREN) + break; + spl_ast_node_ref_t next = parse_type_expr(p); + vec_push(types, next); + } + t = peek(p); - if (!t || t->type != TOK_IDENT) { - SPL_FATAL(t, "unrecognized type atom"); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in parenthesized type"); + return 0; + } + advance(p); + + if (types.size == 1) { + vec_free(types); + return first; + } + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PAREN, t); + node_at(p->ast, ref)->type_paren.types = types; + return ref; + } + + return parse_type_base(p); +} + +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; + + 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; + vec_push(vec, parse_expr(p)); + } + return vec; +} + +static spl_ast_node_ref_vec_t parse_aggregate_fields(parser_t *p) { + spl_ast_node_ref_vec_t fields; + vec_init(fields); + + const spl_tok_t *t = peek(p); + if (!t || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected '{' in aggregate literal"); + return fields; // 空 vec,调用者处理 + } + advance(p); // 消费 '{' + + while (!p->failed) { + t = peek(p); + if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF) + break; + + // 字段必须由 '.' 开头 + if (t->type != TOK_DOT) { + SPL_FATAL(t, "expected '.' in aggregate field initializer"); break; } - 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) { + + t = peek(p); + if (!t || t->type != TOK_IDENT) { + SPL_FATAL(t, "expected field name after '.'"); + break; + } + advance(p); + + // 创建 struct_init_item 节点 + spl_ast_node_ref_t item_ref = new_node(p, SPL_AST_STRUCT_INIT_ITEM, t); + spl_ast_node_t *item = node_at(p->ast, item_ref); + SET_STR_FIELD(p->ast, item->struct_init_item.name, t); + item->struct_init_item.expr = 0; + + // 可选:= 表达式 + if (peek(p) && peek(p)->type == TOK_ASSIGN) { + advance(p); + spl_ast_node_ref_t expr_ref = parse_expr(p); + item = node_at(p->ast, item_ref); // 重新获取,防扩容 + item->struct_init_item.expr = expr_ref; + } + + vec_push(fields, item_ref); + + // 分隔符 + t = peek(p); + if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) { advance(p); continue; } break; } - return base; + + t = peek(p); + if (!t || t->type != TOK_R_BRACE) { + SPL_FATAL(t, "expected '}' in aggregate literal"); + } else { + advance(p); // 消费 '}' + } + + return fields; +} + +typedef struct { + int prec; + char assoc; // 'L', 'R', 'N' +} op_info_t; + +static op_info_t binary_op_info[] = { +#define X(name, prec, assoc, str) {prec, assoc}, + SPL_BINARY_OP_TABLE +#undef X +}; + +static spl_binary_op_t token_to_binary_op(spl_tok_type_t tt) { + switch (tt) { + case TOK_ASSIGN: + return SPL_OP_ASSIGN; + case TOK_ASSIGN_ADD: + return SPL_OP_ASSIGN_ADD; + case TOK_ASSIGN_SUB: + return SPL_OP_ASSIGN_SUB; + case TOK_ASSIGN_MUL: + return SPL_OP_ASSIGN_MUL; + case TOK_ASSIGN_DIV: + return SPL_OP_ASSIGN_DIV; + case TOK_ASSIGN_MOD: + return SPL_OP_ASSIGN_MOD; + case TOK_ASSIGN_AND: + return SPL_OP_ASSIGN_AND; + case TOK_ASSIGN_OR: + return SPL_OP_ASSIGN_OR; + case TOK_ASSIGN_XOR: + return SPL_OP_ASSIGN_XOR; + case TOK_ASSIGN_L_SH: + return SPL_OP_ASSIGN_LSHIFT; + case TOK_ASSIGN_R_SH: + return SPL_OP_ASSIGN_RSHIFT; + case TOK_OR_OR: + return SPL_OP_BOOL_OR; + case TOK_AND_AND: + return SPL_OP_BOOL_AND; + case TOK_OR: + return SPL_OP_BIT_OR; + case TOK_XOR: + return SPL_OP_BIT_XOR; + case TOK_AND: + return SPL_OP_BIT_AND; + case TOK_EQ: + return SPL_OP_CMP_EQ; + case TOK_NEQ: + return SPL_OP_CMP_NE; + case TOK_LE: + return SPL_OP_CMP_LE; + case TOK_GE: + return SPL_OP_CMP_GE; + case TOK_LT: + return SPL_OP_CMP_LT; + case TOK_GT: + return SPL_OP_CMP_GT; + case TOK_LEFT_ARROW: + return SPL_OP_ARROW_LEFT; + case TOK_RIGHT_ARROW: + return SPL_OP_ARROW_RIGHT; + case TOK_FAT_ARROW_BOTH: + return SPL_OP_ARROW_FAT_BOTH; + case TOK_ARROW_BOTH: + return SPL_OP_ARROW_THIN_BOTH; + case TOK_RIGHT_FAT_ARROW: + return SPL_OP_ARROW_FAT_RIGHT; + case TOK_RANGE: + return SPL_OP_RANGE; + case TOK_L_SH: + return SPL_OP_LSHIFT; + case TOK_R_SH: + return SPL_OP_RSHIFT; + case TOK_ADD: + return SPL_OP_ADD; + case TOK_SUB: + return SPL_OP_SUB; + case TOK_MUL: + return SPL_OP_MUL; + case TOK_DIV: + return SPL_OP_DIV; + case TOK_MOD: + return SPL_OP_MOD; + default: + return (spl_binary_op_t)-1; // 无效 + } +} + +static spl_ast_node_ref_t parse_expr_prec(parser_t *p, int min_prec) { + spl_ast_node_ref_t left = parse_prefix(p); + if (p->failed) + return left; + + while (!p->failed) { + const spl_tok_t *t = peek(p); + if (!t) + break; + spl_binary_op_t op = token_to_binary_op(t->type); + if (op == (spl_binary_op_t)-1) + break; + + op_info_t info = binary_op_info[op]; + if (info.prec < min_prec) + break; + + advance(p); + + if (op == SPL_OP_RANGE) { + spl_ast_node_ref_t right = 0; + if (peek(p) && can_start_expr(peek(p)->type)) + right = parse_expr_prec(p, info.prec + 1); // 最小优先级 = range 优先级 + 1 + left = mk_bin(p, t, op, left, right); + continue; + } + + int next_min = info.prec; + if (info.assoc == 'R') { + next_min = info.prec; + } else { + next_min = info.prec + 1; + } + + spl_ast_node_ref_t right = parse_expr_prec(p, next_min); + left = mk_bin(p, t, op, left, right); + } + + return left; +} + +static spl_ast_node_ref_t parse_expr(parser_t *p) { + return parse_expr_prec(p, 1); // 最低优先级 +} + +static spl_ast_node_ref_t parse_prefix(parser_t *p) { + const spl_tok_t *t = peek(p); + if (!t) + return 0; + + spl_unary_op_t uop; + switch (t->type) { + case TOK_SUB: + uop = SPL_UNARY_OP_MINUS; + break; + case TOK_NOT: + uop = SPL_UNARY_OP_NOT; + break; + case TOK_BIT_NOT: + uop = SPL_UNARY_OP_BIT_NOT; + break; + case TOK_AND: + uop = SPL_UNARY_OP_ADDRESS; + break; + default: + return parse_postfix(p); + } + advance(p); + spl_ast_node_ref_t operand = parse_prefix(p); + return mk_unary(p, t, uop, operand); +} + +static spl_ast_node_ref_t parse_postfix(parser_t *p) { + spl_ast_node_ref_t expr = parse_primary(p); + while (!p->failed) { + const spl_tok_t *t = peek(p); + if (!t) + break; + + if (t->type == TOK_L_PAREN) { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_CALL, t); + node_at(p->ast, ref)->call.callee = expr; + node_at(p->ast, ref)->call.args = parse_expr_list(p); + t = peek(p); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in call"); + return expr; + } + advance(p); + expr = ref; + } else if (t->type == TOK_DOT) { + advance(p); + const spl_tok_t *next = peek(p); + if (!next) + break; + if (next->type == TOK_IDENT) { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_FIELD, t); + node_at(p->ast, ref)->field.obj = expr; + SET_STR_FIELD(p->ast, node_at(p->ast, ref)->field.field, next); + expr = ref; + } else if (next->type == TOK_MUL) { + advance(p); + spl_ast_node_ref_t ref = mk_unary(p, t, SPL_UNARY_OP_ADDRESS, expr); + expr = ref; + } else { + SPL_FATAL(next, "expected identifier or '*' after '.'"); + break; + } + } else if (t->type == TOK_L_BRACKET) { + advance(p); + spl_ast_node_ref_t begin = parse_expr(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); + t = peek(p); + if (!t || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in slice"); + return expr; + } + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_SLICE, t); + node_at(p->ast, ref)->slice.obj = expr; + node_at(p->ast, ref)->slice.begin = begin; + node_at(p->ast, ref)->slice.end = end; + expr = ref; + } else { + t = peek(p); + if (!t || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in index"); + return expr; + } + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_INDEX, t); + node_at(p->ast, ref)->index.obj = expr; + node_at(p->ast, ref)->index.index = begin; + expr = ref; + } + } else if (t->type == KW_AS && !p->stop_as) { + advance(p); + spl_ast_node_ref_t type = parse_type_expr(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_CAST, t); + node_at(p->ast, ref)->cast.expr = expr; + node_at(p->ast, ref)->cast.type = type; + expr = ref; + } else { + break; + } + } + return expr; +} + +static spl_ast_node_ref_t parse_primary(parser_t *p) { + const spl_tok_t *t = peek(p); + if (!t) { + SPL_FATAL(t, "unexpected end of expression"); + return 0; + } + + switch (t->type) { + case TOK_INT_LITERAL: { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_INT_LIT, t); + node_at(p->ast, ref)->int_lit.val = parse_int_literal(t); + return ref; + } + case TOK_FLOAT_LITERAL: { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_FLOAT_LIT, t); + node_at(p->ast, ref)->float_lit.val = parse_float_literal(t); + return ref; + } + case TOK_CHAR_LITERAL: { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_CHAR_LIT, t); + node_at(p->ast, ref)->char_lit.val = parse_char_literal(t); + return ref; + } + case TOK_STRING_LITERAL: { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_STRING_LIT, t); + node_at(p->ast, ref)->string_lit.data = parse_string_literal(p, t); + return ref; + } + case KW_TRUE: + case KW_FALSE: { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_BOOL_LIT, t); + node_at(p->ast, ref)->bool_lit.val = (t->type == KW_TRUE); + return ref; + } + case KW_NULL: { + advance(p); + return new_node(p, SPL_AST_EXPR_NULL_LIT, t); + } + case KW_UNDEFINED: { + advance(p); + return new_node(p, SPL_AST_EXPR_UNDEFINED_LIT, t); + } + case TOK_IDENT: { + advance(p); + if (peek(p) && peek(p)->type == TOK_L_BRACE && !p->stop_agg) { + // 具名聚合字面量:Identifier { fields } + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_AGGREGATE_LIT, t); + spl_ast_node_t *agg = node_at(p->ast, ref); + agg->aggregate_literal.name = intern_string(p->ast, t->lexeme, t->len); + agg->aggregate_literal.fields = parse_aggregate_fields(p); + return ref; + } + // 普通标识符引用 + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_IDENT, t); + node_at(p->ast, ref)->ident.name = intern_string(p->ast, t->lexeme, t->len); + return ref; + } + case TOK_DOT: { + advance(p); + const spl_tok_t *nx = peek(p); + if (!nx) { + SPL_FATAL(t, "unexpected '.'"); + return 0; + } + if (nx->type == TOK_L_BRACE && !p->stop_agg) { + // 匿名聚合字面量:. { fields } + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_AGGREGATE_LIT, t); + spl_ast_node_t *agg = node_at(p->ast, ref); + agg->aggregate_literal.name = NULL; + agg->aggregate_literal.fields = parse_aggregate_fields(p); + return ref; + } else if (nx->type == TOK_L_BRACKET) { + // 匿名数组字面量:. [ elems ] + advance(p); // 消费 '[' + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_ANON_ARRAY_LIT, t); + spl_ast_node_t *arr = node_at(p->ast, ref); + arr->anon_array_literal.elems = parse_expr_list(p); + const spl_tok_t *close = peek(p); + if (!close || close->type != TOK_R_BRACKET) { + SPL_FATAL(close, "expected ']'"); + return ref; + } + advance(p); + return ref; + } else { + SPL_FATAL(nx, "expected '{' or '[' after '.'"); + return 0; + } + } + case TOK_L_BRACKET: + return parse_array_literal(p); + case TOK_L_BRACE: + return parse_block(p); + case TOK_AT: + case TOK_SHARP: + return parse_comptime_call(p); + case TOK_L_PAREN: { + advance(p); + spl_ast_node_ref_vec_t elems; + vec_init(elems); + + if (peek(p) && peek(p)->type == TOK_R_PAREN) { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_TUPLE, t); + node_at(p->ast, ref)->tuple.elems = elems; + return ref; + } + + spl_ast_node_ref_t first = parse_expr(p); + if (peek(p) && peek(p)->type == TOK_COMMA) { + vec_push(elems, first); + while (peek(p) && peek(p)->type == TOK_COMMA) { + advance(p); + if (peek(p) && peek(p)->type == TOK_R_PAREN) + break; + vec_push(elems, parse_expr(p)); + } + t = peek(p); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')'"); + return 0; + } + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_TUPLE, t); + node_at(p->ast, ref)->tuple.elems = elems; + return ref; + } else { + t = peek(p); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')'"); + return 0; + } + advance(p); + vec_free(elems); + return first; + } + } + case KW_IF: + return parse_if_expr(p); + case KW_WHILE: + return parse_while_expr(p); + case KW_LOOP: + return parse_loop_expr(p); + case KW_FOR: + return parse_for_expr(p); + case KW_MATCH: + return parse_match_expr(p); + default: + SPL_FATAL(t, "unrecognized expression"); + return 0; + } +} + +static spl_ast_node_ref_t parse_array_literal(parser_t *p) { + const spl_tok_t *start = peek(p); + if (!start || start->type != TOK_L_BRACKET) + return 0; + advance(p); + + bool has_len = false; + isize len = 0; + bool is_underscore = false; + + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_INT_LITERAL) { + len = parse_int_literal(t); + has_len = true; + advance(p); + } else if (t && t->type == KW_UNDERSCORE) { + has_len = true; + is_underscore = true; + advance(p); + } + + t = peek(p); + if (!t || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in array literal"); + return 0; + } + advance(p); + + spl_ast_node_ref_t elem_type = parse_type_expr(p); + + t = peek(p); + if (!t || t->type != TOK_L_BRACKET) { + SPL_FATAL(t, "expected '[' in array literal"); + return 0; + } + advance(p); + + spl_ast_node_ref_vec_t elems = parse_expr_list(p); + + t = peek(p); + if (!t || t->type != TOK_R_BRACKET) { + SPL_FATAL(t, "expected ']' in array literal"); + return 0; + } + advance(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_ARRAY_LIT, start); + spl_ast_node_t *arr = node_at(p->ast, ref); + arr->array_literal.has_len = has_len; + arr->array_literal.len = len; + arr->array_literal.is_underscore_len = is_underscore; + arr->array_literal.elem_type = elem_type; + arr->array_literal.elems = elems; // elems 是局部 vec,直接转移 + return ref; +} + +static spl_ast_node_ref_t parse_comptime_call(parser_t *p) { + const spl_tok_t *start = peek(p); + if (!start || (start->type != TOK_AT && start->type != TOK_SHARP)) + return 0; + advance(p); + + const spl_tok_t *name = peek(p); + if (!name || name->type != TOK_IDENT) { + SPL_FATAL(name, "expected comptime call name"); + return 0; + } + advance(p); + + const spl_tok_t *t = peek(p); + if (!t || t->type != TOK_L_PAREN) { + SPL_FATAL(t, "expected '(' in comptime call"); + return 0; + } + advance(p); + + spl_ast_node_ref_vec_t args = parse_expr_list(p); + + t = peek(p); + if (!t || t->type != TOK_R_PAREN) { + SPL_FATAL(t, "expected ')' in comptime call"); + return 0; + } + advance(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_COMPTIME_CALL, start); + spl_ast_node_t *cc = node_at(p->ast, ref); + SET_STR_FIELD(p->ast, cc->comptime_call.name, name); + cc->comptime_call.args = args; + return ref; +} + +static spl_ast_node_ref_t parse_label(parser_t *p) { + const spl_tok_t *t = peek(p); + if (!t || t->type != TOK_DOLLAR) + return 0; + advance(p); + const spl_tok_t *name = peek(p); + if (!name || name->type != TOK_IDENT) { + SPL_FATAL(name, "expected identifier after '$'"); + return 0; + } + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_LABEL, t); + SET_STR_FIELD(p->ast, node_at(p->ast, ref)->label.name, name); + return ref; +} + +static spl_ast_node_ref_t parse_if_expr(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_IF) + return 0; + advance(p); + + int is_ifvar = 0; + spl_ast_node_ref_t var_decl = 0; + + const spl_tok_t *t = peek(p); + if (t && t->type == KW_VAR) { + advance(p); + is_ifvar = 1; + + spl_ast_node_ref_t pattern = parse_var_pattern(p); + if (!pattern) + return 0; + + spl_ast_node_ref_t type_expr = 0; + spl_ast_node_ref_t init_expr = 0; + 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); + init_expr = parse_expr(p); + } else { + SPL_FATAL(t, "expected '=' in if var"); + return 0; + } + } else if (t && t->type == TOK_ASSIGN) { + advance(p); + init_expr = parse_expr(p); + } else { + SPL_FATAL(t, "expected type annotation or '=' in if var"); + return 0; + } + + var_decl = new_node(p, SPL_AST_VAR_DECL, kw); + spl_ast_node_t *vd = node_at(p->ast, var_decl); + vd->var_const_decl.pattern = pattern; + vd->var_const_decl.type = type_expr; + vd->var_const_decl.init_expr = init_expr; + } else { + p->stop_agg++; + spl_ast_node_ref_t cond = parse_expr(p); + p->stop_agg--; + if (!cond) + return 0; + var_decl = cond; + } + + spl_ast_node_ref_t then_block = parse_block(p); + if (!then_block) + return 0; + + spl_ast_node_ref_t else_branch = 0; + t = peek(p); + if (t && t->type == KW_ELSE) { + advance(p); + t = peek(p); + if (t && t->type == KW_IF) { + else_branch = parse_if_expr(p); + } else { + else_branch = parse_block(p); + } + } + + spl_ast_node_ref_t ref; + if (is_ifvar) { + ref = new_node(p, SPL_AST_EXPR_IFVAR, kw); + node_at(p->ast, ref)->ifvar_expr.var_decl = var_decl; + node_at(p->ast, ref)->ifvar_expr.then_block = then_block; + node_at(p->ast, ref)->ifvar_expr.else_branch = else_branch; + } else { + ref = new_node(p, SPL_AST_EXPR_IF, kw); + node_at(p->ast, ref)->if_expr.cond = var_decl; + node_at(p->ast, ref)->if_expr.then_block = then_block; + node_at(p->ast, ref)->if_expr.else_branch = else_branch; + } + return ref; +} + +static spl_ast_node_ref_t parse_while_expr(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_WHILE) + return 0; + advance(p); + + spl_ast_node_ref_t label = parse_label(p); + + p->stop_agg++; + spl_ast_node_ref_t cond = parse_expr(p); + p->stop_agg--; + if (!cond) + return 0; + + spl_ast_node_ref_t body = parse_block(p); + if (!body) + return 0; + + spl_ast_node_ref_t else_branch = 0; + if (peek(p) && peek(p)->type == KW_ELSE) { + advance(p); + if (peek(p) && peek(p)->type == TOK_L_BRACE) + else_branch = parse_block(p); + else + else_branch = parse_expr(p); + } + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_WHILE, kw); + node_at(p->ast, ref)->while_expr.label = label; + node_at(p->ast, ref)->while_expr.cond = cond; + node_at(p->ast, ref)->while_expr.body = body; + node_at(p->ast, ref)->while_expr.else_branch = else_branch; + return ref; +} + +static spl_ast_node_ref_t parse_loop_expr(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_LOOP) + return 0; + advance(p); + + spl_ast_node_ref_t label = parse_label(p); + spl_ast_node_ref_t body = parse_block(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_LOOP, kw); + node_at(p->ast, ref)->loop_expr.label = label; + node_at(p->ast, ref)->loop_expr.body = body; + return ref; +} + +static spl_ast_node_ref_t parse_for_expr(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_FOR) + return 0; + advance(p); + + spl_ast_node_ref_t label = parse_label(p); + + // 解析迭代表达式列表(用 stop_as 阻止 'as' 被误解析为类型转换) + p->stop_as = 1; + spl_ast_node_ref_vec_t iter_exprs; + vec_init(iter_exprs); + vec_push(iter_exprs, parse_expr(p)); + while (peek(p) && peek(p)->type == TOK_COMMA) { + advance(p); + vec_push(iter_exprs, parse_expr(p)); + } + p->stop_as = 0; + + // 必须有关键字 as + const spl_tok_t *t = peek(p); + if (!t || t->type != KW_AS) { + SPL_FATAL(t, "expected 'as' in for loop"); + return 0; + } + advance(p); + + // 解析绑定变量列表(允许 '_') + spl_ast_node_ref_vec_t idents; + vec_init(idents); + t = peek(p); + if (!t || (t->type != TOK_IDENT && t->type != KW_UNDERSCORE)) { + SPL_FATAL(t, "expected binding variable or '_' in for"); + return 0; + } + advance(p); + spl_ast_node_ref_t id_node = new_node(p, SPL_AST_EXPR_IDENT, t); + SET_STR_FIELD(p->ast, node_at(p->ast, id_node)->ident.name, t); + vec_push(idents, id_node); + + while (peek(p) && peek(p)->type == TOK_COMMA) { + advance(p); + t = peek(p); + if (!t || (t->type != TOK_IDENT && t->type != KW_UNDERSCORE)) { + SPL_FATAL(t, "expected binding variable or '_' in for"); + return 0; + } + advance(p); + id_node = new_node(p, SPL_AST_EXPR_IDENT, t); + SET_STR_FIELD(p->ast, node_at(p->ast, id_node)->ident.name, t); + vec_push(idents, id_node); + } + + // 循环体必须为块 + spl_ast_node_ref_t body = parse_block(p); + if (!body) + return 0; + + // 可选的 else 分支 + spl_ast_node_ref_t else_branch = 0; + if (peek(p) && peek(p)->type == KW_ELSE) { + advance(p); + if (peek(p) && peek(p)->type == TOK_L_BRACE) + else_branch = parse_block(p); + else + else_branch = parse_expr(p); + } + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_FOR, kw); + spl_ast_node_t *fe = node_at(p->ast, ref); + fe->for_expr.label = label; + fe->for_expr.iter_exprs = iter_exprs; + fe->for_expr.idents = idents; + fe->for_expr.body = body; + fe->for_expr.else_branch = else_branch; + return ref; +} + +static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *patterns_out, + spl_ast_node_ref_vec_t *bodies_out) { + spl_ast_node_ref_vec_t pats; + vec_init(pats); + + while (!p->failed) { + spl_ast_node_ref_t pat = parse_match_pattern(p); + if (!pat) + break; + vec_push(pats, pat); + if (peek(p) && peek(p)->type == TOK_COMMA) { + advance(p); + continue; + } + break; + } + + const spl_tok_t *t = peek(p); + if (!t || t->type != TOK_RIGHT_FAT_ARROW) { + SPL_FATAL(t, "expected '=>' in match arm"); + return 0; + } + advance(p); + + spl_ast_node_ref_t body; + t = peek(p); + if (!t || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected block after '=>' in match arm"); + return 0; + } + body = parse_block(p); + + for (usize i = 0; i < pats.size; i++) { + vec_push(*patterns_out, pats.data[i]); + vec_push(*bodies_out, body); + } + vec_free(pats); + return 1; +} + +static spl_ast_node_ref_t parse_match_expr(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_MATCH) + return 0; + advance(p); + + p->stop_agg++; + spl_ast_node_ref_t matched_expr = parse_expr(p); + p->stop_agg--; + + const spl_tok_t *t = peek(p); + if (!t || t->type != TOK_L_BRACE) { + SPL_FATAL(t, "expected '{' in match"); + return 0; + } + advance(p); + + spl_ast_node_ref_vec_t patterns, bodies; + vec_init(patterns); + vec_init(bodies); + + while (!p->failed) { + t = peek(p); + if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF) + break; + if (!parse_match_arm(p, &patterns, &bodies)) + break; + if (peek(p) && peek(p)->type == TOK_COMMA) + advance(p); + } + + t = peek(p); + if (!t || t->type != TOK_R_BRACE) { + SPL_FATAL(t, "expected '}' in match"); + return 0; + } + advance(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_MATCH, kw); + spl_ast_node_t *me = node_at(p->ast, ref); + me->match_expr.matched_expr = matched_expr; + vec_init(me->match_expr.arms); + for (usize i = 0; i < patterns.size; i++) { + spl_ast_node_ref_t arm = new_node(p, SPL_AST_MATCH_ARM, NULL); + spl_ast_node_t *arm_node = node_at(p->ast, arm); + arm_node->match_arm.pattern = patterns.data[i]; + arm_node->match_arm.body = bodies.data[i]; + vec_push(me->match_expr.arms, arm); + } + vec_free(patterns); + vec_free(bodies); + return ref; +} + +static spl_ast_node_ref_t parse_ret_stmt(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_RET) + return 0; + advance(p); + + spl_ast_node_ref_t expr = 0; + const spl_tok_t *t = peek(p); + if (t && can_start_expr(t->type)) + expr = parse_expr(p); + + t = peek(p); + if (t && t->type == TOK_SEMICOLON) + advance(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_STATEMENT_RET, kw); + node_at(p->ast, ref)->statement_ret.expr = expr; + return ref; +} + +static spl_ast_node_ref_t parse_break_stmt(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_BREAK) + return 0; + advance(p); + + spl_ast_node_ref_t label = parse_label(p); + spl_ast_node_ref_t expr = 0; + const spl_tok_t *t = peek(p); + if (t && can_start_expr(t->type)) + expr = parse_expr(p); + + t = peek(p); + if (t && t->type == TOK_SEMICOLON) + advance(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_STATEMENT_BREAK, kw); + node_at(p->ast, ref)->statement_break.label = label; + node_at(p->ast, ref)->statement_break.expr = expr; + return ref; +} + +static spl_ast_node_ref_t parse_continue_stmt(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_CONTINUE) + return 0; + advance(p); + + spl_ast_node_ref_t label = parse_label(p); + + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_SEMICOLON) + advance(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_STATEMENT_CONTINUE, kw); + node_at(p->ast, ref)->statement_continue.label = label; + return ref; +} + +static spl_ast_node_ref_t parse_defer_stmt(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_DEFER) + return 0; + advance(p); + + spl_ast_node_ref_t body = 0; + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_L_BRACE) { + body = parse_block(p); + } else if (t && can_start_statement(t->type)) { + body = parse_statement(p); + } else { + body = parse_expr(p); + t = peek(p); + if (t && t->type == TOK_SEMICOLON) + advance(p); + } + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_STATEMENT_DEFER, kw); + node_at(p->ast, ref)->statement_defer.body = body; + return ref; +} + +static spl_ast_node_ref_t parse_comptime_stmt(parser_t *p) { + const spl_tok_t *kw = peek(p); + if (!kw || kw->type != KW_COMPTIME) + return 0; + advance(p); + + spl_ast_node_ref_t body = 0; + const spl_tok_t *t = peek(p); + if (t && t->type == TOK_L_BRACE) { + body = parse_block(p); + } else { + body = parse_expr(p); + } + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_STATEMENT_COMPTIME, kw); + node_at(p->ast, ref)->statement_comptime.body = body; + return ref; +} + +static spl_ast_node_ref_t parse_statement(parser_t *p) { + const spl_tok_t *t = peek(p); + if (!t) + return 0; + + switch (t->type) { + case KW_RET: + return parse_ret_stmt(p); + case KW_BREAK: + return parse_break_stmt(p); + case KW_CONTINUE: + return parse_continue_stmt(p); + case KW_DEFER: + return parse_defer_stmt(p); + case KW_COMPTIME: + return parse_comptime_stmt(p); + case KW_VAR: + case KW_CONST: + case KW_TYPE: { + spl_ast_node_ref_vec_t tag_list; + vec_init(tag_list); + parse_tag_list(p, &tag_list, 0); // 解析声明前的普通 tag + + spl_ast_node_ref_t decl; + if (t->type == KW_VAR) + decl = parse_var_const_decl(p, tag_list, 0); + else if (t->type == KW_CONST) + decl = parse_var_const_decl(p, tag_list, 1); + else + decl = parse_type_decl(p, tag_list); + /* 不再 vec_free(tag_list),所有权已转移 */ + if (!decl) + return 0; + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_STATEMENT_DECL, t); + node_at(p->ast, ref)->statement_decl.decl = decl; + return ref; + } + default: { + if (can_start_expr(t->type)) { + spl_ast_node_ref_t expr = parse_expr(p); + if (!expr) + return 0; + spl_ast_node_ref_t ref = new_node(p, SPL_AST_STATEMENT_EXPR, t); + node_at(p->ast, ref)->statement_expr.expr = expr; + return ref; + } else { + SPL_FATAL(t, "unrecognized statement"); + return 0; + } + } + } +} + +static spl_ast_node_ref_t parse_block(parser_t *p) { + const spl_tok_t *start = peek(p); + if (!start || start->type != TOK_L_BRACE) { + SPL_FATAL(start, "expected '{'"); + return 0; + } + advance(p); + + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_BLOCK, start); + spl_ast_node_t *block = node_at(p->ast, ref); + vec_init(block->block.stmts); + block->block.tail_expr = 0; + + while (!p->failed) { + const spl_tok_t *t = peek(p); + if (!t || t->type == TOK_EOF) { + SPL_FATAL(t, "block missing '}'"); + return ref; + } + if (t->type == TOK_R_BRACE) { + advance(p); + break; + } + + if (can_start_statement(t->type)) { + spl_ast_node_ref_t stmt = parse_statement(p); + block = node_at(p->ast, ref); + if (stmt) + vec_push(block->block.stmts, stmt); + } else if (can_start_expr(t->type)) { + spl_ast_node_ref_t expr = parse_expr(p); + block = node_at(p->ast, ref); + t = peek(p); + if (t && t->type == TOK_SEMICOLON) { + advance(p); + vec_push(block->block.stmts, expr); + } else if (t && t->type == TOK_R_BRACE) { + if (block->block.tail_expr != 0) { + SPL_FATAL(t, "only one tail expression allowed"); + } + block->block.tail_expr = expr; + } else if (expr && node_at(p->ast, expr)->kind == SPL_AST_EXPR_BLOCK) { + vec_push(block->block.stmts, expr); + // 继续循环,处理下一个语句 + } else { + SPL_FATAL(t, "expected ';' or '}' after expression"); + break; + } + } else { + SPL_FATAL(t, "unrecognized token in block"); + break; + } + } + + return ref; } void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec) { - ast->input = *tok_vec; // move + ast->input = *tok_vec; vec_init(ast->node_buckets); vec_init(ast->str_buckets); ast->root = 0; @@ -1777,28 +2150,55 @@ void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec) { vec_push(ast->node_buckets, n); } -void spl_ast_prase(spl_ast_t *ast) { +void spl_ast_parse(spl_ast_t *ast) { if (!ast || !ast->input.data || ast->node_buckets.size == 0) return; + parser_t p; p.ast = ast; p.pos = 0; p.failed = 0; + p.stop_as = 0; + p.stop_agg = 0; ast->parsed = 0; - spl_tok_t *begin = &vec_at(ast->input, 0); - spl_ast_node_ref_vec_t members; - vec_init(members); + spl_ast_node_ref_vec_t external_tags; + vec_init(external_tags); + spl_ast_node_ref_vec_t declarations; + vec_init(declarations); + while (!p.failed) { 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); + + if (t->type == TOK_AT || t->type == TOK_SHARP) { + usize save_pos = p.pos; + const spl_tok_t *t2 = NULL; + if (t) { + p.pos++; + t2 = peek(&p); + p.pos = save_pos; + } + if (t2 && t2->type == TOK_NOT) { + parse_tag_list(&p, &external_tags, 1); + continue; + } + } + + spl_ast_node_ref_t decl = parse_container_declaration(&p); + if (decl) + vec_push(declarations, decl); } - spl_ast_node_ref_t root = new_node(&p, SPL_AST_CONTAINER_MEMBERS, begin); - node_at(ast, root)->container_members = members; + + spl_ast_node_ref_t container_members = new_node(&p, SPL_AST_CONTAINER_MEMBERS, NULL); + spl_ast_node_t *cm = node_at(ast, container_members); + cm->container_members.external_tags = external_tags; + cm->container_members.declarations = declarations; + + spl_ast_node_ref_t root = new_node(&p, SPL_AST_ROOT, NULL); + node_at(ast, root)->root.members = container_members; + ast->root = root; ast->parsed = p.failed ? -1 : 1; } @@ -1815,9 +2215,9 @@ void spl_ast_drop(spl_ast_t *ast) { } spl_ast_node_t *spl_ast_node(spl_ast_t *ast, spl_ast_node_ref_t node) { - if (!ast || node == 0) + if (!ast || node == 0 || node >= ast->node_buckets.size) return NULL; - return &vec_at(ast->node_buckets, node); + return &ast->node_buckets.data[node]; } void spl_ast_valid(spl_ast_t *ast) { @@ -1827,10 +2227,11 @@ void spl_ast_valid(spl_ast_t *ast) { printf("valid: AST not parsed successfully (parsed=%d)\n", ast->parsed); return; } - // TODO + /* 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, bool last); void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) { @@ -1839,7 +2240,8 @@ void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) { dump_stack_t stack; vec_init(stack); printf("AST:\n"); - dump_node(ast, node, &stack, 1); + dump_node(ast, node, &stack, true); + vec_free(stack); } #define dump_vec(_ast, _vec, _stack) \ @@ -1848,35 +2250,51 @@ void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) { } while (0) static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, bool last) { - spl_ast_node_t *node = &vec_at(ast->node_buckets, node_ref); + spl_ast_node_t *node = &ast->node_buckets.data[node_ref]; for (usize i = 0; i < vec_size(*stack); i++) printf("%s", vec_at(*stack, i) ? " " : "| "); - printf("%s%s #%zu ID`%zu`", last ? "`-" : "|-", spl_ast_kind_name(node->kind), node_ref, - node->resolved_type_id); + printf("%s%s #%zu", last ? "`-" : "|-", spl_ast_kind_name(node->kind), node_ref); if (node->dbg.fname) printf(" [%d:%d]", node->dbg.line, node->dbg.col); printf("\n"); vec_push(*stack, last); + switch (node->kind) { - case SPL_AST_NONE: - UNREACHABLE(); + case SPL_AST_ROOT: + if (node->root.members) + dump_node(ast, node->root.members, stack, true); break; case SPL_AST_CONTAINER_MEMBERS: - dump_vec(ast, node->container_members, stack); + dump_vec(ast, node->container_members.external_tags, stack); + dump_vec(ast, node->container_members.declarations, stack); + break; + + case SPL_AST_TAG_ITEM: + case SPL_AST_EXTERNAL_TAG_ITEM: + dump_vec(ast, node->tag_item.args, stack); 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) { - last = node->kind == SPL_AST_FN_DECL ? true : false; - dump_node(ast, node->fn_decl.type_expr, stack, last); - } - dump_node(ast, node->fn_decl.block, stack, true); + dump_vec(ast, node->fn_decl.tag_list, stack); + dump_vec(ast, node->fn_decl.params, stack); + if (node->fn_decl.ret_type) + dump_node(ast, node->fn_decl.ret_type, stack, false); + if (node->fn_decl.body) + dump_node(ast, node->fn_decl.body, stack, true); + break; + + 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.pattern) + dump_node(ast, node->var_const_decl.pattern, stack, false); + if (node->var_const_decl.type) + dump_node(ast, node->var_const_decl.type, stack, false); + if (node->var_const_decl.init_expr) + dump_node(ast, node->var_const_decl.init_expr, stack, true); break; case SPL_AST_TYPE_DECL: @@ -1884,19 +2302,12 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t dump_node(ast, node->type_decl.type_expr, stack, true); break; - 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, false); - if (node->var_const_decl.expr) - dump_node(ast, node->var_const_decl.expr, stack, true); - break; - 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, true); + dump_node(ast, node->member_decl.type_expr, stack, false); + if (node->member_decl.init_expr) + dump_node(ast, node->member_decl.init_expr, stack, true); break; case SPL_AST_PARAM_DECL: @@ -1905,256 +2316,273 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t dump_node(ast, node->param_decl.type_expr, stack, true); break; - case SPL_AST_ATTR_ITEM: - dump_vec(ast, node->attr_item.expr_list, stack); + case SPL_AST_COMPTIME_DECL: + if (node->comptime_decl.body) + dump_node(ast, node->comptime_decl.body, stack, true); break; - case SPL_AST_ARGG_INIT_ITEM: - if (node->aggregate_init_item.expr) - dump_node(ast, node->aggregate_init_item.expr, stack, true); + case SPL_AST_TOP_LEVEL_BLOCK: + dump_vec(ast, node->top_level_block.tag_list, stack); + if (node->top_level_block.block) + dump_node(ast, node->top_level_block.block, stack, true); break; - case SPL_AST_IF_STATEMENT: - if (node->if_statement.expr) - dump_node(ast, node->if_statement.expr, stack, false); - dump_node(ast, node->if_statement.if_block, stack, false); - dump_node(ast, node->if_statement.else_block, stack, true); + case SPL_AST_STATEMENT_RET: + if (node->statement_ret.expr) + dump_node(ast, node->statement_ret.expr, stack, true); break; - case SPL_AST_IFVAR_STATEMENT: - if (node->ifvar_statement.packed_expr) - dump_node(ast, node->ifvar_statement.packed_expr, stack, false); - dump_node(ast, node->ifvar_statement.if_block, stack, false); - dump_node(ast, node->ifvar_statement.else_block, stack, true); + case SPL_AST_STATEMENT_BREAK: + if (node->statement_break.label) + dump_node(ast, node->statement_break.label, stack, false); + if (node->statement_break.expr) + dump_node(ast, node->statement_break.expr, stack, true); break; - case SPL_AST_WHILE_STATEMENT: - if (node->while_statement.expr) - dump_node(ast, node->while_statement.expr, stack, false); - dump_node(ast, node->while_statement.while_block, stack, true); + case SPL_AST_STATEMENT_CONTINUE: + if (node->statement_continue.label) + dump_node(ast, node->statement_continue.label, stack, true); break; - case SPL_AST_LOOP_STATEMENT: - dump_node(ast, node->loop_statement.loop_block, stack, true); + case SPL_AST_STATEMENT_DEFER: + case SPL_AST_STATEMENT_COMPTIME: + if (node->statement_defer.body) + dump_node(ast, node->statement_defer.body, stack, true); 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]); - } - dump_node(ast, node->for_statement.block, stack, true); + case SPL_AST_STATEMENT_DECL: + if (node->statement_decl.decl) + dump_node(ast, node->statement_decl.decl, stack, true); break; - case SPL_AST_MATCH_STATEMENT: - if (node->match_statement.expr) - dump_node(ast, node->match_statement.expr, stack, false); - dump_vec(ast, node->match_statement.paced_exprs, stack); - dump_node(ast, node->match_statement.match_block, stack, true); + case SPL_AST_STATEMENT_EXPR: + if (node->statement_expr.expr) + dump_node(ast, node->statement_expr.expr, stack, true); break; - case SPL_AST_RET_STATEMENT: - if (node->ret_statement.expr) - dump_node(ast, node->ret_statement.expr, stack, true); + case SPL_AST_AGGREGATE_MEMBER: + dump_vec(ast, node->aggregate_member.attr_list, stack); + if (node->aggregate_member.type_expr) + dump_node(ast, node->aggregate_member.type_expr, stack, false); + if (node->aggregate_member.init_expr) + dump_node(ast, node->aggregate_member.init_expr, stack, true); break; - case SPL_AST_DEFER_STATEMENT: - dump_vec(ast, node->defer_statement.block_or_statement, stack); + case SPL_AST_STRUCT_INIT_ITEM: + if (node->struct_init_item.expr) + dump_node(ast, node->struct_init_item.expr, stack, true); break; - case SPL_AST_PACKED_EXPR: - if (node->packed_expr.expr) - dump_node(ast, node->packed_expr.expr, stack, true); + case SPL_AST_MATCH_ARM: + if (node->match_arm.pattern) + dump_node(ast, node->match_arm.pattern, stack, false); + if (node->match_arm.body) + dump_node(ast, node->match_arm.body, stack, true); 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_RSHIFT_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, false); - if (node->op_expr.right) - dump_node(ast, node->op_expr.right, stack, true); + case SPL_AST_LABEL: 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, true); - break; - - case SPL_AST_CALL_EXPR: - if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, false); - 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, true); - break; - - case SPL_AST_INDEX_EXPR: - if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, false); - if (node->postfix_expr.index_expr) - dump_node(ast, node->postfix_expr.index_expr, stack, true); - break; - - case SPL_AST_SLICE_EXPR: - if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, false); - if (node->postfix_expr.slice_expr.begin) - dump_node(ast, node->postfix_expr.slice_expr.begin, stack, false); - if (node->postfix_expr.slice_expr.end) - dump_node(ast, node->postfix_expr.slice_expr.end, stack, true); - break; - - case SPL_AST_AS_EXPR: - if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, false); - if (node->postfix_expr.type_expr) - dump_node(ast, node->postfix_expr.type_expr, stack, true); - break; - - case SPL_AST_EXPR_INTEGER_LIT: + case SPL_AST_EXPR_INT_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_BOOL_LIT: + case SPL_AST_EXPR_NULL_LIT: + case SPL_AST_EXPR_UNDEFINED_LIT: case SPL_AST_EXPR_IDENT: break; - case SPL_AST_ARGGREGATE_INIT: - dump_vec(ast, node->primary_expr.aggregate_init.expr, stack); + case SPL_AST_EXPR_UNARY: + if (node->unary.operand) + dump_node(ast, node->unary.operand, stack, true); break; - case SPL_AST_EXPR_EXPR: - if (node->primary_expr.expr) - dump_node(ast, node->primary_expr.expr, stack, true); + case SPL_AST_EXPR_BINARY: + if (node->binary.left) + dump_node(ast, node->binary.left, stack, false); + if (node->binary.right) + dump_node(ast, node->binary.right, stack, true); 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, false); - dump_vec(ast, node->primary_expr.array_lit_expr.expr_list, stack); + case SPL_AST_EXPR_CALL: + if (node->call.callee) + dump_node(ast, node->call.callee, stack, false); + dump_vec(ast, node->call.args, stack); break; - case SPL_AST_BUILTIN_EXPR: - dump_vec(ast, node->primary_expr.builtin_expr.expr_list, stack); + case SPL_AST_EXPR_FIELD: + if (node->field.obj) + dump_node(ast, node->field.obj, stack, true); break; - case SPL_AST_BLOCK_EXPR: - dump_vec(ast, node->primary_expr.block_expr, stack); + case SPL_AST_EXPR_INDEX: + if (node->index.obj) + dump_node(ast, node->index.obj, stack, false); + if (node->index.index) + dump_node(ast, node->index.index, stack, true); break; - case SPL_AST_BASE_TYPE_FN: - 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, true); + case SPL_AST_EXPR_SLICE: + if (node->slice.obj) + dump_node(ast, node->slice.obj, stack, false); + if (node->slice.begin) + dump_node(ast, node->slice.begin, stack, false); + if (node->slice.end) + dump_node(ast, node->slice.end, stack, true); break; - case SPL_AST_BASE_TYPE_PATH: - dump_vec(ast, node->type_expr.attr_list, stack); + case SPL_AST_EXPR_CAST: + if (node->cast.expr) + dump_node(ast, node->cast.expr, stack, false); + if (node->cast.type) + dump_node(ast, node->cast.type, stack, true); + break; + + case SPL_AST_EXPR_TUPLE: + dump_vec(ast, node->tuple.elems, stack); + break; + + case SPL_AST_EXPR_ARRAY_LIT: + if (node->array_literal.elem_type) + dump_node(ast, node->array_literal.elem_type, stack, false); + dump_vec(ast, node->array_literal.elems, stack); + break; + + case SPL_AST_EXPR_ANON_ARRAY_LIT: + dump_vec(ast, node->anon_array_literal.elems, stack); + break; + + case SPL_AST_EXPR_AGGREGATE_LIT: + + dump_vec(ast, node->aggregate_literal.fields, stack); + break; + + case SPL_AST_EXPR_COMPTIME_CALL: + dump_vec(ast, node->comptime_call.args, stack); + break; + + case SPL_AST_EXPR_BLOCK: + dump_vec(ast, node->block.stmts, stack); + if (node->block.tail_expr) + dump_node(ast, node->block.tail_expr, stack, true); + break; + + case SPL_AST_EXPR_IF: + if (node->if_expr.cond) + dump_node(ast, node->if_expr.cond, stack, false); + if (node->if_expr.then_block) + dump_node(ast, node->if_expr.then_block, stack, false); + if (node->if_expr.else_branch) + dump_node(ast, node->if_expr.else_branch, stack, true); + break; + + case SPL_AST_EXPR_IFVAR: + if (node->ifvar_expr.var_decl) + dump_node(ast, node->ifvar_expr.var_decl, stack, false); + if (node->ifvar_expr.then_block) + dump_node(ast, node->ifvar_expr.then_block, stack, false); + if (node->ifvar_expr.else_branch) + dump_node(ast, node->ifvar_expr.else_branch, stack, true); + break; + + case SPL_AST_EXPR_WHILE: + if (node->while_expr.label) + dump_node(ast, node->while_expr.label, stack, false); + if (node->while_expr.cond) + dump_node(ast, node->while_expr.cond, stack, false); + if (node->while_expr.body) + dump_node(ast, node->while_expr.body, stack, false); + if (node->while_expr.else_branch) + dump_node(ast, node->while_expr.else_branch, stack, true); + break; + + case SPL_AST_EXPR_LOOP: + if (node->loop_expr.label) + dump_node(ast, node->loop_expr.label, stack, false); + if (node->loop_expr.body) + dump_node(ast, node->loop_expr.body, stack, true); + break; + + case SPL_AST_EXPR_FOR: + if (node->for_expr.label) + dump_node(ast, node->for_expr.label, stack, false); + dump_vec(ast, node->for_expr.iter_exprs, stack); + dump_vec(ast, node->for_expr.idents, stack); + if (node->for_expr.body) + dump_node(ast, node->for_expr.body, stack, false); + if (node->for_expr.else_branch) + dump_node(ast, node->for_expr.else_branch, stack, true); + break; + + case SPL_AST_EXPR_MATCH: + if (node->match_expr.matched_expr) + dump_node(ast, node->match_expr.matched_expr, stack, false); + dump_vec(ast, node->match_expr.arms, stack); + break; + + case SPL_AST_EXPR_FN_TYPE: + dump_vec(ast, node->fn_type.params, stack); + if (node->fn_type.ret_type) + dump_node(ast, node->fn_type.ret_type, stack, true); + break; + + case SPL_AST_TYPE_PATH: 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, true); - 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, true); + if (node->type_pointer.pointee) + dump_node(ast, node->type_pointer.pointee, stack, true); 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, false); - if (node->type_expr.array_type.size) - dump_node(ast, node->type_expr.array_type.size, stack, true); + if (node->type_array.elem_type) + dump_node(ast, node->type_array.elem_type, stack, true); break; - case SPL_AST_TYPE_STRUCT: - case SPL_AST_TYPE_UNION: - case SPL_AST_TYPE_ENUM: - case SPL_AST_TYPE_SHAPE: - dump_vec(ast, node->type_expr.attr_list, stack); - dump_vec(ast, node->type_expr.aggregate_list, stack); + case SPL_AST_TYPE_SLICE: + if (node->type_slice.elem_type) + dump_node(ast, node->type_slice.elem_type, stack, true); 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: + case SPL_AST_TYPE_FN: + dump_vec(ast, node->type_fn.params, stack); + if (node->type_fn.ret_type) + dump_node(ast, node->type_fn.ret_type, stack, true); 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: + case SPL_AST_TYPE_PAREN: + dump_vec(ast, node->type_paren.types, stack); break; - case SPL_AST_COUNT: - UNREACHABLE(); + case SPL_AST_TYPE_AGGREGATE: + dump_vec(ast, node->type_aggregate.members, stack); + break; + + case SPL_AST_TYPE_COMPTIME_CALL: + dump_vec(ast, node->type_comptime_call.args, stack); + break; + + case SPL_AST_PATTERN_IDENT: + case SPL_AST_PATTERN_UNDERSCORE: + break; + + case SPL_AST_PATTERN_DOT: + if (node->pattern_dot.sub_pattern) + dump_node(ast, node->pattern_dot.sub_pattern, stack, true); + break; + + case SPL_AST_PATTERN_TUPLE: + dump_vec(ast, node->pattern_tuple.patterns, stack); + break; + + case SPL_AST_PATTERN_LIST: + dump_vec(ast, node->pattern_list.patterns, stack); + break; + + default: break; } + (void)vec_pop(*stack); } diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index d48f4d8..ce928b2 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -7,134 +7,147 @@ #include "spl_tok.h" /* clang-format off */ -#define SPL_AST_KIND_TABLE \ - X(SPL_AST_NONE, V0, none) \ - X(SPL_AST_CONTAINER_MEMBERS, V0, container_members) \ - 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_RSHIFT_EXPR, V0, assign_rshift_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_SHAPE, V0, type_shape) \ - 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) \ - -/* clang-format on*/ +#define SPL_AST_KIND_TABLE \ + X(SPL_AST_NONE, V0, none) \ + X(SPL_AST_ROOT, V0, root) \ + X(SPL_AST_CONTAINER_MEMBERS, V0, container_members) \ + X(SPL_AST_EXTERNAL_TAG_ITEM, V0, external_tag_item) \ + X(SPL_AST_TAG_ITEM, V0, tag_item) \ + X(SPL_AST_COMPTIME_DECL, V0, comptime_decl) \ + X(SPL_AST_TOP_LEVEL_BLOCK, V0, top_level_block) \ + X(SPL_AST_FN_DECL, V0, fn_decl) \ + X(SPL_AST_VAR_DECL, V0, var_decl) \ + X(SPL_AST_CONST_DECL, V0, const_decl) \ + X(SPL_AST_TYPE_DECL, V0, type_decl) \ + X(SPL_AST_MEMBER_DECL, V0, member_decl) \ + X(SPL_AST_PARAM_DECL, V0, param_decl) \ + X(SPL_AST_STATEMENT_RET, V0, statement_ret) \ + X(SPL_AST_STATEMENT_BREAK, V0, statement_break) \ + X(SPL_AST_STATEMENT_CONTINUE, V0, statement_continue) \ + X(SPL_AST_STATEMENT_DEFER, V0, statement_defer) \ + X(SPL_AST_STATEMENT_COMPTIME, V0, statement_comptime) \ + X(SPL_AST_STATEMENT_DECL, V0, statement_decl) \ + X(SPL_AST_STATEMENT_EXPR, V0, statement_expr) \ + X(SPL_AST_AGGREGATE_MEMBER, V0, aggregate_member) \ + X(SPL_AST_STRUCT_INIT_ITEM, V0, struct_init_item) \ + X(SPL_AST_MATCH_ARM, V0, match_arm) \ + X(SPL_AST_LABEL, V0, label) \ + X(SPL_AST_EXPR_INT_LIT, V0, int_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_BOOL_LIT, V0, bool_lit) \ + X(SPL_AST_EXPR_NULL_LIT, V0, null_lit) \ + X(SPL_AST_EXPR_UNDEFINED_LIT, V0, undefined_lit) \ + X(SPL_AST_EXPR_IDENT, V0, ident) \ + X(SPL_AST_EXPR_UNARY, V0, unary) \ + X(SPL_AST_EXPR_BINARY, V0, binary) \ + X(SPL_AST_EXPR_CALL, V0, call) \ + X(SPL_AST_EXPR_FIELD, V0, field) \ + X(SPL_AST_EXPR_INDEX, V0, index) \ + X(SPL_AST_EXPR_SLICE, V0, slice) \ + X(SPL_AST_EXPR_CAST, V0, cast) \ + X(SPL_AST_EXPR_TUPLE, V0, tuple) \ + X(SPL_AST_EXPR_ARRAY_LIT, V0, array_literal) \ + X(SPL_AST_EXPR_ANON_ARRAY_LIT, V0, anon_array_literal) \ + X(SPL_AST_EXPR_AGGREGATE_LIT, V0, aggregate_literal) \ + X(SPL_AST_EXPR_COMPTIME_CALL, V0, comptime_call) \ + X(SPL_AST_EXPR_BLOCK, V0, block) \ + X(SPL_AST_EXPR_IF, V0, if_expr) \ + X(SPL_AST_EXPR_IFVAR, V0, ifvar_expr) \ + X(SPL_AST_EXPR_WHILE, V0, while_expr) \ + X(SPL_AST_EXPR_LOOP, V0, loop_expr) \ + X(SPL_AST_EXPR_FOR, V0, for_expr) \ + X(SPL_AST_EXPR_MATCH, V0, match_expr) \ + X(SPL_AST_EXPR_FN_TYPE, V0, fn_type) \ + X(SPL_AST_TYPE_PATH, V0, 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_FN, V0, type_fn) \ + X(SPL_AST_TYPE_PAREN, V0, type_paren) \ + X(SPL_AST_TYPE_AGGREGATE, V0, type_aggregate) \ + X(SPL_AST_TYPE_COMPTIME_CALL, V0, type_comptime_call) \ + X(SPL_AST_PATTERN_IDENT, V0, pattern_ident) \ + X(SPL_AST_PATTERN_UNDERSCORE, V0, pattern_underscore) \ + X(SPL_AST_PATTERN_DOT, V0, pattern_dot) \ + X(SPL_AST_PATTERN_TUPLE, V0, pattern_tuple) \ + X(SPL_AST_PATTERN_LIST, V0, pattern_list) +/* clang-format on */ typedef enum { #ifdef X #undef X #endif - #define X(name, ...) name, +#define X(name, ...) name, SPL_AST_KIND_TABLE #undef X - SPL_AST_COUNT, + SPL_AST_COUNT, } spl_ast_node_kind_t; -const char *spl_ast_kind_name(spl_ast_node_kind_t kind); +/* clang-format off */ +#define SPL_BINARY_OP_TABLE \ + X(SPL_OP_ASSIGN, 1, 'R', =) \ + X(SPL_OP_ASSIGN_ADD, 1, 'R', +=) \ + X(SPL_OP_ASSIGN_SUB, 1, 'R', -=) \ + X(SPL_OP_ASSIGN_MUL, 1, 'R', *=) \ + X(SPL_OP_ASSIGN_DIV, 1, 'R', /=) \ + X(SPL_OP_ASSIGN_MOD, 1, 'R', %=) \ + X(SPL_OP_ASSIGN_AND, 1, 'R', &=) \ + X(SPL_OP_ASSIGN_OR, 1, 'R', |=) \ + X(SPL_OP_ASSIGN_XOR, 1, 'R', ^=) \ + X(SPL_OP_ASSIGN_LSHIFT, 1, 'R', <<=) \ + X(SPL_OP_ASSIGN_RSHIFT, 1, 'R', >>=) \ + X(SPL_OP_BOOL_OR, 2, 'L', ||) \ + X(SPL_OP_BOOL_AND, 3, 'L', &&) \ + X(SPL_OP_BIT_OR, 4, 'L', |) \ + X(SPL_OP_BIT_XOR, 5, 'L', ^) \ + X(SPL_OP_BIT_AND, 6, 'L', &) \ + X(SPL_OP_CMP_EQ, 7, 'L', ==) \ + X(SPL_OP_CMP_NE, 7, 'L', !=) \ + X(SPL_OP_CMP_LE, 8, 'L', <=) \ + X(SPL_OP_CMP_GE, 8, 'L', >=) \ + X(SPL_OP_CMP_LT, 8, 'L', <) \ + X(SPL_OP_CMP_GT, 8, 'L', >) \ + X(SPL_OP_ARROW_LEFT, 9, 'L', <-) \ + X(SPL_OP_ARROW_RIGHT, 9, 'L', ->) \ + X(SPL_OP_ARROW_FAT_BOTH, 9, 'L', <=>) \ + X(SPL_OP_ARROW_THIN_BOTH, 9, 'L', <->) \ + X(SPL_OP_ARROW_FAT_RIGHT, 9, 'L', =>) \ + X(SPL_OP_RANGE, 10, 'L', ..) \ + X(SPL_OP_LSHIFT, 11, 'L', <<) \ + X(SPL_OP_RSHIFT, 11, 'L', >>) \ + X(SPL_OP_ADD, 12, 'L', +) \ + X(SPL_OP_SUB, 12, 'L', -) \ + X(SPL_OP_MUL, 13, 'L', *) \ + X(SPL_OP_DIV, 13, 'L', /) \ + X(SPL_OP_MOD, 13, 'L', %) +/* clang-format on */ + +typedef enum { +#ifdef X +#undef X +#endif +#define X(name, ...) name, + SPL_BINARY_OP_TABLE +#undef X +} spl_binary_op_t; + +typedef enum { + SPL_UNARY_OP_MINUS, + SPL_UNARY_OP_NOT, + SPL_UNARY_OP_BIT_NOT, + SPL_UNARY_OP_ADDRESS, +} spl_unary_op_t; + +const char *spl_binary_op_name(spl_binary_op_t op); +const char *spl_unary_op_name(spl_unary_op_t op); struct spl_ast_node; typedef struct spl_ast_node spl_ast_node_t; 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_dbg_node_t dbg; @@ -143,168 +156,337 @@ struct spl_ast_node { usize resolved_def_id; usize resolved_type_id; }; + union { - spl_ast_node_ref_vec_t container_members; /* container_decl */ - + /* SPL_AST_ROOT */ struct { - const char *ident; - spl_ast_node_ref_vec_t expr_list; - } attr_item; + spl_ast_node_ref_t members; /* container_members 节点 */ + } root; + /* SPL_AST_CONTAINER_MEMBERS */ struct { - spl_ast_node_ref_vec_t attr_list; /* attr_item */ + spl_ast_node_ref_vec_t external_tags; /* external_tag_item 节点列表 */ + spl_ast_node_ref_vec_t declarations; + } container_members; + + /* SPL_AST_FN_DECL */ + struct { + spl_ast_node_ref_vec_t tag_list; /* tag_item 节点 */ + bool is_comptime; const char *name; - spl_ast_node_ref_vec_t param_list; /* param_decl */ - spl_ast_node_ref_t type_expr; /* ret type expr */ - spl_ast_node_ref_t block; /* block_expr */ + spl_ast_node_ref_vec_t params; /* param_decl 节点 */ + spl_ast_node_ref_t ret_type; /* 类型节点,可空 */ + spl_ast_node_ref_t body; /* 表达式节点,可空表示仅声明 */ } fn_decl; + + /* SPL_AST_VAR_DECL / SPL_AST_CONST_DECL */ struct { - spl_ast_node_ref_vec_t attr_list; /* attr_item */ + spl_ast_node_ref_vec_t attr_list; + spl_ast_node_ref_t pattern; /* 模式节点 */ + spl_ast_node_ref_t type; /* 类型节点,可空 */ + spl_ast_node_ref_t init_expr; /* 表达式节点,可空 */ + } var_const_decl; + + /* SPL_AST_TYPE_DECL */ + struct { + spl_ast_node_ref_vec_t attr_list; + const char *name; + spl_ast_node_ref_t type_expr; /* 类型节点 */ + } type_decl; + + /* SPL_AST_MEMBER_DECL */ + struct { + spl_ast_node_ref_vec_t attr_list; + const char *name; + spl_ast_node_ref_t type_expr; /* 可空 */ + spl_ast_node_ref_t init_expr; /* 可空 */ + } member_decl; + + /* SPL_AST_PARAM_DECL */ + struct { + spl_ast_node_ref_vec_t attr_list; const char *name; spl_ast_node_ref_t type_expr; } param_decl; + /* SPL_AST_TAG_ITEM / SPL_AST_EXTERNAL_TAG_ITEM */ + struct { + bool is_at; /* true: @, false: # */ + bool is_external; /* true: @!或#! */ + const char *name; + spl_ast_node_ref_vec_t args; + } tag_item; + + /* SPL_AST_COMPTIME_DECL */ + struct { + spl_ast_node_ref_t body; /* block 或 expr 节点 */ + } comptime_decl; + + /* SPL_AST_TOP_LEVEL_BLOCK */ + struct { + spl_ast_node_ref_vec_t tag_list; /* tag_item 节点列表 */ + spl_ast_node_ref_t block; /* 表达式节点block */ + } top_level_block; + + /* SPL_AST_STATEMENT_RET */ + struct { + spl_ast_node_ref_t expr; /* 可空 */ + } statement_ret; + + /* SPL_AST_STATEMENT_BREAK */ + struct { + spl_ast_node_ref_t label; /* 可空 */ + spl_ast_node_ref_t expr; /* 可空 */ + } statement_break; + + /* SPL_AST_STATEMENT_CONTINUE */ + struct { + spl_ast_node_ref_t label; /* 可空 */ + } statement_continue; + + /* SPL_AST_STATEMENT_DEFER */ + struct { + spl_ast_node_ref_t body; /* block 或 statement 节点 */ + } statement_defer; + + /* SPL_AST_STATEMENT_COMPTIME */ + struct { + spl_ast_node_ref_t body; /* block 或 expr 节点 */ + } statement_comptime; + + /* SPL_AST_STATEMENT_DECL */ + struct { + spl_ast_node_ref_t decl; /* var/const/type 声明节点 */ + } statement_decl; + + /* SPL_AST_STATEMENT_EXPR */ + struct { + spl_ast_node_ref_t expr; + } statement_expr; + + /* SPL_AST_AGGREGATE_MEMBER */ + struct { + spl_ast_node_ref_vec_t attr_list; + const char *name; + spl_ast_node_ref_t type_expr; /* 可空 */ + spl_ast_node_ref_t init_expr; /* 可空 */ + } aggregate_member; + + /* SPL_AST_STRUCT_INIT_ITEM */ struct { const char *name; - spl_ast_node_ref_t type_expr; - } type_decl; + spl_ast_node_ref_t expr; /* 可空 */ + } struct_init_item; + + /* SPL_AST_MATCH_ARM */ + struct { + spl_ast_node_ref_t pattern; /* 模式节点 */ + spl_ast_node_ref_t body; /* block 或 expr 节点 */ + } match_arm; + + /* SPL_AST_LABEL */ struct { - spl_ast_node_ref_vec_t attr_list; /* attr_item */ const char *name; - spl_ast_node_ref_t type_expr; - } member_decl; + } label; + + /* ---- 表达式子类型 ---- */ + struct { + isize val; + } int_lit; + struct { + double val; + } float_lit; + struct { + char val; + } char_lit; + struct { + const char *data; + } string_lit; + struct { + bool val; + } bool_lit; + /* null_lit, undefined_lit 无数据 */ struct { - spl_ast_node_ref_vec_t attr_list; /* attr_item */ const char *name; - spl_ast_node_ref_t type_expr; - spl_ast_node_ref_t expr; - } var_const_decl; - - /* statement */ + } ident; struct { - spl_ast_node_ref_t expr; - spl_ast_node_ref_t if_block; /* block_expr */ - spl_ast_node_ref_t else_block; /* block_expr */ - } if_statement; - struct { - spl_ast_node_ref_t packed_expr; - spl_ast_node_ref_t if_block; /* block_expr */ - spl_ast_node_ref_t else_block; /* block_expr */ - } ifvar_statement; - struct { - spl_ast_node_ref_t expr; - spl_ast_node_ref_t while_block; /* block_expr */ - } while_statement; - struct { - spl_ast_node_ref_t loop_block; /* block_expr */ - } loop_statement; - struct { - spl_ast_node_ref_vec_t expr_vec; - VEC(char *) ident_vec; - spl_ast_node_ref_t block; /* block_expr */ - } for_statement; - struct { - spl_ast_node_ref_t expr; - spl_ast_node_ref_vec_t paced_exprs; /* packed_expr */ - spl_ast_node_ref_t match_block; /* block_expr */ - } 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; + spl_unary_op_t op; + spl_ast_node_ref_t operand; + } unary; struct { - const char *ident; - const char *bind_ident; - spl_ast_node_ref_t expr; - } packed_expr; - struct { + spl_binary_op_t op; spl_ast_node_ref_t left; spl_ast_node_ref_t right; - } op_expr; - struct { - spl_ast_node_ref_t postfix_expr; - } prefix_expr; - struct { - spl_ast_node_ref_t primary_expr; - union { - spl_ast_node_ref_vec_t call_expr; - const char *field_expr; /* field/method */ - spl_ast_node_ref_t index_expr; - struct { - spl_ast_node_ref_t begin; - spl_ast_node_ref_t end; - } slice_expr; - spl_ast_node_ref_t type_expr; - }; - } postfix_expr; + } binary; struct { - isize integer_expr; - double float_expr; - char char_lit_expr; - const char *string_lit_expr; /* parsed c string */ - const char *ident; + spl_ast_node_ref_t callee; + spl_ast_node_ref_vec_t args; + } call; - struct { - const char *name; - spl_ast_node_ref_vec_t expr; /* aggregate_init_item */ - } aggregate_init; + struct { + spl_ast_node_ref_t obj; + const char *field; + } field; + struct { + spl_ast_node_ref_t obj; + spl_ast_node_ref_t index; + } index; + + struct { + spl_ast_node_ref_t obj; + spl_ast_node_ref_t begin; + spl_ast_node_ref_t end; + } slice; + + struct { 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; /* 语句 */ - } primary_expr; + spl_ast_node_ref_t type; + } cast; struct { - const char *ident; - spl_ast_node_ref_t expr; - } aggregate_init_item; + spl_ast_node_ref_vec_t elems; + } tuple; struct { - spl_ast_node_ref_vec_t attr_list; /* attr_item */ - union { - 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; - } fn_type; - spl_ast_node_ref_vec_t aggregate_list; /* container_decl */ - }; - } type_expr; + bool has_len; + isize len; + bool is_underscore_len; + spl_ast_node_ref_t elem_type; + spl_ast_node_ref_vec_t elems; + } array_literal; + + struct { + spl_ast_node_ref_vec_t elems; + } anon_array_literal; + + struct { + const char *name; /* 可空,匿名时为 NULL */ + spl_ast_node_ref_vec_t fields; /* struct_init_item 节点列表 */ + } aggregate_literal; + + struct { + const char *name; + spl_ast_node_ref_vec_t args; + } comptime_call; + + struct { + spl_ast_node_ref_vec_t stmts; + spl_ast_node_ref_t tail_expr; + } block; + + struct { + spl_ast_node_ref_t cond; + spl_ast_node_ref_t then_block; + spl_ast_node_ref_t else_branch; + } if_expr; + + struct { + spl_ast_node_ref_t var_decl; + spl_ast_node_ref_t then_block; + spl_ast_node_ref_t else_branch; + } ifvar_expr; + + struct { + spl_ast_node_ref_t label; + spl_ast_node_ref_t cond; + spl_ast_node_ref_t body; + spl_ast_node_ref_t else_branch; + } while_expr; + + struct { + spl_ast_node_ref_t label; + spl_ast_node_ref_t body; + } loop_expr; + + struct { + spl_ast_node_ref_t label; + spl_ast_node_ref_vec_t iter_exprs; + spl_ast_node_ref_vec_t idents; + spl_ast_node_ref_t body; + spl_ast_node_ref_t else_branch; + } for_expr; + + struct { + spl_ast_node_ref_t matched_expr; + spl_ast_node_ref_vec_t arms; /* match_arm 节点 */ + } match_expr; + + struct { + bool is_comptime; + spl_ast_node_ref_vec_t params; + spl_ast_node_ref_t ret_type; + } fn_type; + + /* ---- 类型子类型 ---- */ + struct { + const char *name; + spl_ast_node_ref_vec_t generic_args; + } type_path; + + struct { + spl_ast_node_ref_t pointee; + } type_pointer; + + struct { + bool has_len; + isize len; + bool is_underscore_len; + spl_ast_node_ref_t elem_type; + } type_array; + + struct { + spl_ast_node_ref_t elem_type; + } type_slice; + + struct { + bool is_comptime; + spl_ast_node_ref_vec_t params; + spl_ast_node_ref_t ret_type; + } type_fn; + + struct { + spl_ast_node_ref_vec_t types; + } type_paren; + + struct { + const char *kind_name; + spl_ast_node_ref_vec_t members; /* aggregate_member 节点 */ + } type_aggregate; + + struct { + const char *name; + spl_ast_node_ref_vec_t args; + } type_comptime_call; + + /* ---- 模式子类型 ---- */ + struct { + const char *name; + } pattern_ident; + + /* pattern_underscore 无数据 */ + + struct { + const char *name; + spl_ast_node_ref_t sub_pattern; + } pattern_dot; + + struct { + spl_ast_node_ref_vec_t patterns; + } pattern_tuple; + + struct { + spl_ast_node_ref_vec_t patterns; + } pattern_list; }; }; typedef VEC(spl_ast_node_t) spl_ast_node_vec_t; -typedef VEC(char*)spl_ast_cstr_ref_vec_t; +typedef VEC(char *) spl_ast_cstr_ref_vec_t; typedef struct { int parsed; spl_tok_vec_t input; @@ -316,9 +498,10 @@ typedef struct { void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec /*move*/); void spl_ast_drop(spl_ast_t *ast); -spl_ast_node_t* spl_ast_node(spl_ast_t *ast, spl_ast_node_ref_t node); +spl_ast_node_t *spl_ast_node(spl_ast_t *ast, spl_ast_node_ref_t node); +const char *spl_ast_node_name(spl_ast_node_t *node); -void spl_ast_prase(spl_ast_t *ast); +void spl_ast_parse(spl_ast_t *ast); void spl_ast_valid(spl_ast_t *ast); void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node); diff --git a/stage1/spl_dbg.h b/stage1/spl_dbg.h index 679f06f..37ee77b 100644 --- a/stage1/spl_dbg.h +++ b/stage1/spl_dbg.h @@ -11,15 +11,15 @@ typedef struct { } spl_dbg_node_t; #define SPL_FATAL(dbg, fmt, ...) \ - LOG_FATAL("fatal at %s:%zd:%zd " fmt, ((dbg) && (dbg)->fname ? (dbg)->fname : ""), \ + LOG_FATAL("fatal at %s:%d:%d " fmt, ((dbg) && (dbg)->fname ? (dbg)->fname : ""), \ ((dbg) ? (dbg)->line : 0), ((dbg) ? (dbg)->col : 0), ##__VA_ARGS__) #define SPL_ERROR(dbg, fmt, ...) \ - LOG_ERROR("error at %s:%zd:%zd " fmt, ((dbg) && (dbg)->fname ? (dbg)->fname : ""), \ + LOG_ERROR("error at %s:%d:%d " fmt, ((dbg) && (dbg)->fname ? (dbg)->fname : ""), \ ((dbg) ? (dbg)->line : 0), ((dbg) ? (dbg)->col : 0), ##__VA_ARGS__) #define SPL_WARN(dbg, fmt, ...) \ - LOG_ERROR("warn at %s:%zd:%zd " fmt, ((dbg) && (dbg)->fname ? (dbg)->fname : ""), \ + LOG_ERROR("warn at %s:%d:%d " fmt, ((dbg) && (dbg)->fname ? (dbg)->fname : ""), \ ((dbg) ? (dbg)->line : 0), ((dbg) ? (dbg)->col : 0), ##__VA_ARGS__) #endif /* __SPL_DBG_H__ */ diff --git a/stage1/spl_lexer.c b/stage1/spl_lexer.c index 67f52a8..73b3033 100644 --- a/stage1/spl_lexer.c +++ b/stage1/spl_lexer.c @@ -349,6 +349,22 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) { } /* Multi-character operators (longest match) */ +#define TRY_OP1(c1, tok1) \ + if (c == (c1)) { \ + spl_tok_t tok; \ + memset(&tok, 0, sizeof(tok)); \ + tok.type = (tok1); \ + tok.lexeme = start; \ + tok.len = 1; \ + tok.fname = fname; \ + tok.offset = offset; \ + tok.line = line; \ + tok.col = col; \ + vec_push(toks, tok); \ + offset++; \ + col++; \ + continue; \ + } /* Helper: try to match a two-char operator */ #define TRY_OP2(c1, c2, tok2, tok1) \ @@ -394,13 +410,15 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) { } /* Three-char operators first */ + TRY_OP3('<', '-', '>', TOK_ARROW_BOTH, TOK_RIGHT_ARROW, TOK_LT) + TRY_OP3('<', '=', '>', TOK_FAT_ARROW_BOTH, TOK_RIGHT_FAT_ARROW, TOK_LT) TRY_OP3('<', '<', '=', TOK_ASSIGN_L_SH, TOK_L_SH, TOK_LT) TRY_OP3('>', '>', '=', TOK_ASSIGN_R_SH, TOK_R_SH, TOK_GT) TRY_OP3('.', '.', '.', TOK_ELLIPSIS, TOK_RANGE, TOK_DOT) /* Two-char operators */ TRY_OP2('=', '=', TOK_EQ, TOK_ASSIGN) - TRY_OP2('=', '>', TOK_FAT_ARROW, TOK_ASSIGN) + TRY_OP2('=', '>', TOK_RIGHT_FAT_ARROW, TOK_ASSIGN) TRY_OP2('!', '=', TOK_NEQ, TOK_NOT) TRY_OP2('<', '=', TOK_LE, TOK_LT) TRY_OP2('>', '=', TOK_GE, TOK_GT) @@ -414,110 +432,53 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) { TRY_OP2('&', '=', TOK_ASSIGN_AND, TOK_AND) TRY_OP2('|', '=', TOK_ASSIGN_OR, TOK_OR) TRY_OP2('^', '=', TOK_ASSIGN_XOR, TOK_XOR) - TRY_OP2('<', '-', TOK_LEFT_ARRAY, TOK_LT) - TRY_OP2('-', '>', TOK_RIGHT_ARRAY, TOK_SUB) + TRY_OP2('<', '-', TOK_LEFT_ARROW, TOK_LT) + TRY_OP2('-', '>', TOK_RIGHT_ARROW, TOK_SUB) TRY_OP2(':', '=', TOK_COLON_ASSIGN, TOK_COLON) /* Single-character operators */ - { - spl_tok_type_t tt = TOK_UNKNOWN; - switch (c) { - case '+': - tt = TOK_ADD; - break; - case '-': - tt = TOK_SUB; - break; - case '*': - tt = TOK_MUL; - break; - case '/': - tt = TOK_DIV; - break; - case '%': - tt = TOK_MOD; - break; - case '&': - tt = TOK_AND; - break; - case '|': - tt = TOK_OR; - break; - case '^': - tt = TOK_XOR; - break; - case '~': - tt = TOK_BIT_NOT; - break; - case '!': - tt = TOK_NOT; - break; - case '<': - tt = TOK_LT; - break; - case '>': - tt = TOK_GT; - break; - case '=': - tt = TOK_ASSIGN; - break; - case '.': - tt = TOK_DOT; - break; - case ',': - tt = TOK_COMMA; - break; - case ';': - tt = TOK_SEMICOLON; - break; - case ':': - tt = TOK_COLON; - break; - case '(': - tt = TOK_L_PAREN; - break; - case ')': - tt = TOK_R_PAREN; - break; - case '[': - tt = TOK_L_BRACKET; - break; - case ']': - tt = TOK_R_BRACKET; - break; - case '{': - tt = TOK_L_BRACE; - break; - case '}': - tt = TOK_R_BRACE; - break; - case '#': - tt = TOK_SHARP; - break; - case '@': - tt = TOK_AT; - break; - case '?': - tt = TOK_COND; - break; - default: - tt = TOK_UNKNOWN; - break; - } + TRY_OP1('+', TOK_ADD); + TRY_OP1('-', TOK_SUB); + TRY_OP1('*', TOK_MUL); + TRY_OP1('/', TOK_DIV); + TRY_OP1('%', TOK_MOD); + TRY_OP1('&', TOK_AND); + TRY_OP1('|', TOK_OR); + TRY_OP1('^', TOK_XOR); + TRY_OP1('~', TOK_BIT_NOT); + TRY_OP1('!', TOK_NOT); + TRY_OP1('<', TOK_LT); + TRY_OP1('>', TOK_GT); + TRY_OP1('=', TOK_ASSIGN); + TRY_OP1('.', TOK_DOT); + TRY_OP1(',', TOK_COMMA); + TRY_OP1(';', TOK_SEMICOLON); + TRY_OP1(':', TOK_COLON); + TRY_OP1('(', TOK_L_PAREN); + TRY_OP1(')', TOK_R_PAREN); + TRY_OP1('[', TOK_L_BRACKET); + TRY_OP1(']', TOK_R_BRACKET); + TRY_OP1('{', TOK_L_BRACE); + TRY_OP1('}', TOK_R_BRACE); + TRY_OP1('#', TOK_SHARP); + TRY_OP1('@', TOK_AT); + TRY_OP1('$', TOK_DOLLAR); + TRY_OP1('?', TOK_COND); - spl_tok_t tok; - memset(&tok, 0, sizeof(tok)); - tok.type = tt; - tok.lexeme = start; - tok.len = 1; - tok.fname = fname; - tok.offset = offset; - tok.line = line; - tok.col = col; - vec_push(toks, tok); - offset++; - col++; - } + // TODO + spl_tok_t tok; + memset(&tok, 0, sizeof(tok)); + tok.type = TOK_UNKNOWN; + tok.lexeme = start; + tok.len = 1; + tok.fname = fname; + tok.offset = offset; + tok.line = line; + tok.col = col; + vec_push(toks, tok); + offset++; + col++; + continue; } /* EOF token */ diff --git a/stage1/spl_tok.h b/stage1/spl_tok.h index cdea086..104d7cb 100644 --- a/stage1/spl_tok.h +++ b/stage1/spl_tok.h @@ -25,17 +25,17 @@ 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(shape , KW_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(undefined , KW_UNDEFINED , 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(_ , KW_UNDERSCORE , SPL_V0) \ // KEYWORD_TABLE #define TOKEN_TABLE \ @@ -45,13 +45,17 @@ X(endline , TOK_ENDLINE , SPL_V0 ) \ X("#" , TOK_SHARP , SPL_V0 ) \ X("@" , TOK_AT , SPL_V0 ) \ + X("$" , TOK_DOLLAR , SPL_V0 ) \ X("==" , TOK_EQ , SPL_V0 ) \ X("=" , TOK_ASSIGN , SPL_V0 ) \ X("+=" , TOK_ASSIGN_ADD , SPL_V0 ) \ X("+" , TOK_ADD , SPL_V0 ) \ X("-=" , TOK_ASSIGN_SUB , SPL_V0 ) \ - X("->" , TOK_RIGHT_ARRAY , SPL_V0 ) \ - X("<-" , TOK_LEFT_ARRAY , SPL_V0 ) \ + X("->" , TOK_RIGHT_ARROW , SPL_V0 ) \ + X("<-" , TOK_LEFT_ARROW , SPL_V0 ) \ + X("<->" , TOK_ARROW_BOTH , SPL_V0 ) \ + X("<=>" , TOK_FAT_ARROW_BOTH , SPL_V0 ) \ + X("=>" , TOK_RIGHT_FAT_ARROW , SPL_V0 ) \ X("-" , TOK_SUB , SPL_V0 ) \ X("*=" , TOK_ASSIGN_MUL , SPL_V0 ) \ X("*" , TOK_MUL , SPL_V0 ) \ @@ -93,7 +97,6 @@ X("." , TOK_DOT , SPL_V0 ) \ X(".." , TOK_RANGE , SPL_V0 ) \ X("..." , TOK_ELLIPSIS , SPL_V0 ) \ - X("=>" , TOK_FAT_ARROW , SPL_V0 ) \ X("?" , TOK_COND , SPL_V0 ) \ X(ident , TOK_IDENT , SPL_V0 ) \ X(int , TOK_INT_LITERAL , SPL_V0 ) \ diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 6a11ddc..951f206 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -6,9 +6,6 @@ static usize spl_type_hash(spl_type_node_t n) { case SPL_TYPE_ERROR: case SPL_TYPE_VOID: case SPL_TYPE_BOOL: - case SPL_TYPE_UNDEFINED: - case SPL_TYPE_NULL: - break; case SPL_TYPE_INT: hash += n.int_type.bits + n.int_type.is_signed; break; @@ -16,41 +13,28 @@ static usize spl_type_hash(spl_type_node_t n) { hash += n.float_type.bits; break; case SPL_TYPE_PTR: - hash += n.ptr_pointee; - break; - case SPL_TYPE_SLICE: - hash += n.slice_element; - break; - case SPL_TYPE_RANGE: - hash += n.range_element; + hash += n.ptr_type.pointee; break; case SPL_TYPE_ARRAY: hash += n.array_type.element + n.array_type.len; break; case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: - hash += n.layout.mode * 31 + n.layout.fixed_align_bits; - vec_for(n.agg_members, i) { - hash += (n.agg_members.data[i].name ? map_hash_str(n.agg_members.data[i].name) : 0) + - n.agg_members.data[i].type_id; - } - break; case SPL_TYPE_ENUM: + case SPL_TYPE_SHAPE: hash += n.layout.mode * 31 + n.layout.fixed_align_bits; - hash += n.adt_type.tag_type; - vec_for(n.adt_type.variants, i) { + hash += n.agg_type.tag_type; + vec_for(n.agg_type.variants, i) { hash += - (n.adt_type.variants.data[i].name ? map_hash_str(n.adt_type.variants.data[i].name) + (n.agg_type.variants.data[i].name ? map_hash_str(n.agg_type.variants.data[i].name) : 0) + - n.adt_type.variants.data[i].type_id; + n.agg_type.variants.data[i].type_id; } break; case SPL_TYPE_FN: hash += n.fn_type.ret; vec_for(n.fn_type.params, i) { hash += vec_at(n.fn_type.params, i); } break; - default: // TODO - break; } return hash; } @@ -62,9 +46,6 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { case SPL_TYPE_ERROR: case SPL_TYPE_VOID: case SPL_TYPE_BOOL: - case SPL_TYPE_UNDEFINED: - case SPL_TYPE_NULL: - break; case SPL_TYPE_INT: if (n1.int_type.bits != n2.int_type.bits) return 1; @@ -76,15 +57,7 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { return 1; break; case SPL_TYPE_PTR: - if (n1.ptr_pointee != n2.ptr_pointee) - return 1; - break; - case SPL_TYPE_SLICE: - if (n1.slice_element != n2.slice_element) - return 1; - break; - case SPL_TYPE_RANGE: - if (n1.range_element != n2.range_element) + if (n1.ptr_type.pointee != n2.ptr_type.pointee) return 1; break; case SPL_TYPE_ARRAY: @@ -95,34 +68,21 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { break; case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: - if (n1.layout.mode != n2.layout.mode || - n1.layout.fixed_align_bits != n2.layout.fixed_align_bits) - return 1; - if (vec_size(n1.agg_members) != vec_size(n2.agg_members)) - return 1; - vec_for(n1.agg_members, i) { - const char *na = n1.agg_members.data[i].name; - const char *nb = n2.agg_members.data[i].name; - if (strcmp(na ? na : "", nb ? nb : "") != 0) - return 1; - if (n1.agg_members.data[i].type_id != n2.agg_members.data[i].type_id) - return 1; - } - break; case SPL_TYPE_ENUM: + case SPL_TYPE_SHAPE: if (n1.layout.mode != n2.layout.mode || n1.layout.fixed_align_bits != n2.layout.fixed_align_bits) return 1; - if (n1.adt_type.tag_type != n2.adt_type.tag_type) + if (n1.agg_type.tag_type != n2.agg_type.tag_type) return 1; - if (vec_size(n1.adt_type.variants) != vec_size(n2.adt_type.variants)) + if (vec_size(n1.agg_type.variants) != vec_size(n2.agg_type.variants)) return 1; - vec_for(n1.adt_type.variants, i) { - const char *na = n1.adt_type.variants.data[i].name; - const char *nb = n2.adt_type.variants.data[i].name; + vec_for(n1.agg_type.variants, i) { + const char *na = n1.agg_type.variants.data[i].name; + const char *nb = n2.agg_type.variants.data[i].name; if (strcmp(na ? na : "", nb ? nb : "") != 0) return 1; - if (n1.adt_type.variants.data[i].type_id != n2.adt_type.variants.data[i].type_id) + if (n1.agg_type.variants.data[i].type_id != n2.agg_type.variants.data[i].type_id) return 1; } break; @@ -136,8 +96,6 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { return 1; } break; - default: // TODO - return 1; } return 0; } @@ -150,10 +108,9 @@ static void spl_type_node_free_vecs(spl_type_node_t *tn) { switch (tn->kind) { case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: - vec_free(tn->agg_members); - break; case SPL_TYPE_ENUM: - vec_free(tn->adt_type.variants); + case SPL_TYPE_SHAPE: + vec_free(tn->agg_type.variants); break; case SPL_TYPE_FN: vec_free(tn->fn_type.params); @@ -187,24 +144,15 @@ static const spl_type_member_t *spl_type_agg_member_find(spl_type_t *type, spl_t if (!n || !name) { return NULL; } - if (n->kind == SPL_TYPE_STRUCT || n->kind == SPL_TYPE_UNION) { - vec_for(n->agg_members, i) { - const char *mn = n->agg_members.data[i].name; + if (n->kind == SPL_TYPE_STRUCT || n->kind == SPL_TYPE_UNION || n->kind == SPL_TYPE_ENUM || + n->kind == SPL_TYPE_SHAPE) { + vec_for(n->agg_type.variants, i) { + const char *mn = vec_at(n->agg_type.variants, i).name; if (strcmp(mn ? mn : "", name) == 0) { if (out_idx) { *out_idx = i; } - return &n->agg_members.data[i]; - } - } - } else if (n->kind == SPL_TYPE_ENUM) { - vec_for(n->adt_type.variants, i) { - const char *mn = n->adt_type.variants.data[i].name; - if (strcmp(mn ? mn : "", name) == 0) { - if (out_idx) { - *out_idx = i; - } - return &n->adt_type.variants.data[i]; + return &n->agg_type.variants.data[i]; } } } @@ -245,21 +193,7 @@ spl_type_id_t spl_type_builder_float(spl_type_t *type, usize bits) { spl_type_id_t spl_type_builder_ptr(spl_type_t *type, spl_type_id_t pointee) { spl_type_node_t tn = {0}; tn.kind = SPL_TYPE_PTR; - tn.ptr_pointee = pointee; - return spl_type_node_push(type, &tn); -} - -spl_type_id_t spl_type_builder_slice(spl_type_t *type, spl_type_id_t element) { - spl_type_node_t tn = {0}; - tn.kind = SPL_TYPE_SLICE; - tn.slice_element = element; - return spl_type_node_push(type, &tn); -} - -spl_type_id_t spl_type_builder_range(spl_type_t *type, spl_type_id_t element) { - spl_type_node_t tn = {0}; - tn.kind = SPL_TYPE_RANGE; - tn.range_element = element; + tn.ptr_type.pointee = pointee; return spl_type_node_push(type, &tn); } @@ -284,24 +218,96 @@ spl_type_id_t spl_type_builder_fn(spl_type_t *type, spl_type_id_t ret, const spl } spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk, - const spl_type_member_t *members, usize nmembers, - spl_type_id_t tag_type, spl_type_layout_t layout) { + spl_type_member_vec_t *variants, spl_type_id_t tag_type, + spl_type_layout_t layout) { spl_type_node_t tn = {0}; tn.kind = tk; tn.layout = layout; + tn.agg_type.variants = *variants; if (tk == SPL_TYPE_ENUM) { - vec_init(tn.adt_type.variants); - for (usize i = 0; i < nmembers; i++) { - vec_push(tn.adt_type.variants, members[i]); - } - tn.adt_type.tag_type = tag_type; + tn.agg_type.tag_type = tag_type; } else { - vec_init(tn.agg_members); - for (usize i = 0; i < nmembers; i++) { - vec_push(tn.agg_members, members[i]); + tn.agg_type.tag_type = 0; + } + vec_init(*variants); + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name) { + if (!name || !*name) + return 0; + + // 固定名称类型 + if (strcmp(name, "bool") == 0) + return spl_type_builder_simple(type, SPL_TYPE_BOOL); + if (strcmp(name, "void") == 0) + return spl_type_builder_simple(type, SPL_TYPE_VOID); + if (strcmp(name, "isize") == 0) + return spl_type_builder_int(type, sizeof(void *) * 8, true); + if (strcmp(name, "usize") == 0) + return spl_type_builder_int(type, sizeof(void *) * 8, false); + + // 动态模式:iN / uN / fN,N 为正整数 + char prefix = name[0]; + if (prefix == 'i' || prefix == 'u' || prefix == 'f') { + const char *rest = name + 1; + if (*rest == '\0') + return 0; + char *end; + long bits = strtol(rest, &end, 10); + if (end != rest && *end == '\0' && bits > 0) { + if (prefix == 'i') + return spl_type_builder_int(type, (int)bits, true); + if (prefix == 'u') + return spl_type_builder_int(type, (int)bits, false); + if (prefix == 'f') + return spl_type_builder_float(type, (int)bits); } } - return spl_type_node_push(type, &tn); + return 0; +} + +spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id) { + spl_def_node_t *def_node = spl_def_node(type, def_id); + Assert(def_node != NULL); + return def_node->type_id; +} + +spl_def_id_t spl_def_builder_void(spl_type_t *type) { + TODO(); + return 0; +} +spl_def_id_t spl_def_builder_bool(spl_type_t *type) { + TODO(); + return 0; +} +spl_def_id_t spl_def_builder_int(spl_type_t *type, usize bits, int is_signed) { + TODO(); + return 0; +} +spl_def_id_t spl_def_builder_float(spl_type_t *type, usize bits) { + TODO(); + return 0; +} +spl_def_id_t spl_def_builder_ptr(spl_type_t *type, spl_def_id_t pointee) { + TODO(); + return 0; +} +spl_def_id_t spl_def_builder_array(spl_type_t *type, spl_def_id_t element, usize len) { + TODO(); + return 0; +} +spl_def_id_t spl_def_builder_slice(spl_type_t *type, spl_type_id_t element) { + TODO(); + return 0; +} +spl_def_id_t spl_def_builder_range(spl_type_t *type) { + TODO(); + return 0; +} +spl_def_id_t spl_def_builder_fn(spl_type_t *type) { + TODO(); + return 0; } spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, @@ -337,20 +343,18 @@ void spl_type_init(spl_type_t *type) { vec_init(type->def_table); vec_push(type->def_table, (spl_def_node_t){0}); - spl_type_builder_simple(type, SPL_TYPE_VOID); - spl_type_builder_simple(type, SPL_TYPE_BOOL); - spl_type_builder_simple(type, SPL_TYPE_UNDEFINED); - spl_type_builder_simple(type, SPL_TYPE_NULL); - spl_type_builder_int(type, 8, false); - spl_type_builder_int(type, 16, false); - spl_type_builder_int(type, 32, false); - spl_type_builder_int(type, 64, false); - spl_type_builder_int(type, 8, true); - spl_type_builder_int(type, 16, true); - spl_type_builder_int(type, 32, true); - spl_type_builder_int(type, 64, true); - spl_type_builder_float(type, 32); - spl_type_builder_float(type, 64); + // spl_type_builder_simple(type, SPL_TYPE_VOID); + // spl_type_builder_simple(type, SPL_TYPE_BOOL); + // spl_type_builder_int(type, 8, false); + // spl_type_builder_int(type, 16, false); + // spl_type_builder_int(type, 32, false); + // spl_type_builder_int(type, 64, false); + // spl_type_builder_int(type, 8, true); + // spl_type_builder_int(type, 16, true); + // spl_type_builder_int(type, 32, true); + // spl_type_builder_int(type, 64, true); + // spl_type_builder_float(type, 32); + // spl_type_builder_float(type, 64); } void spl_type_drop(spl_type_t *type) { @@ -359,10 +363,9 @@ void spl_type_drop(spl_type_t *type) { switch (n->kind) { case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: - vec_free(n->agg_members); - break; case SPL_TYPE_ENUM: - vec_free(n->adt_type.variants); + case SPL_TYPE_SHAPE: + vec_free(n->agg_type.variants); break; case SPL_TYPE_FN: vec_free(n->fn_type.params); @@ -405,12 +408,6 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { case SPL_TYPE_BOOL: printf("bool"); break; - case SPL_TYPE_UNDEFINED: - printf("undefined"); - break; - case SPL_TYPE_NULL: - printf("null"); - break; case SPL_TYPE_INT: if (n->int_type.bits == 0) { printf("comptime_int"); @@ -427,52 +424,35 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { break; case SPL_TYPE_PTR: printf("*"); - spl_type_pure_dump(type, n->ptr_pointee); - break; - case SPL_TYPE_SLICE: - printf("[]"); - spl_type_pure_dump(type, n->slice_element); - break; - case SPL_TYPE_RANGE: - printf("range["); - spl_type_pure_dump(type, n->range_element); - printf("]"); + spl_type_pure_dump(type, n->ptr_type.pointee); break; case SPL_TYPE_ARRAY: printf("[%zu]", n->array_type.len); spl_type_pure_dump(type, n->array_type.element); break; case SPL_TYPE_STRUCT: - printf("struct{"); - vec_for(n->agg_members, i) { - if (i) { - printf(", "); - } - spl_type_member_t *member = &vec_at(n->agg_members, i); - printf("%s:", member->name ? member->name : "?"); - spl_type_pure_dump(type, member->type_id); - } - printf("}"); - break; case SPL_TYPE_UNION: - printf("union{"); - vec_for(n->agg_members, i) { - if (i) { - printf(", "); - } - spl_type_member_t *member = &vec_at(n->agg_members, i); - printf("%s:", member->name ? member->name : "?"); - spl_type_pure_dump(type, member->type_id); - } - printf("}"); - break; case SPL_TYPE_ENUM: - printf("enum{"); // TODO tag_type - vec_for(n->adt_type.variants, i) { + case SPL_TYPE_SHAPE: + switch (n->kind) { + case SPL_TYPE_STRUCT: + printf("struct{\n"); + case SPL_TYPE_UNION: + printf("union{\n"); + case SPL_TYPE_ENUM: + printf("enum{\n"); + case SPL_TYPE_SHAPE: + printf("shape{\n"); + break; + default: + UNREACHABLE(); + break; + } + vec_for(n->agg_type.variants, i) { if (i) { printf(", "); } - spl_type_member_t *member = &vec_at(n->adt_type.variants, i); + spl_type_member_t *member = &vec_at(n->agg_type.variants, i); printf("%s:", member->name ? member->name : "?"); spl_type_pure_dump(type, member->type_id); } @@ -486,13 +466,10 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { } spl_type_pure_dump(type, vec_at(n->fn_type.params, i)); } - printf(") -> "); + printf(")"); spl_type_pure_dump(type, n->fn_type.ret); break; } - case SPL_TYPE_ID: - printf("id#%zu", n->type_id); - break; } } @@ -523,6 +500,19 @@ void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) { case SPL_DEF_AGG: def_kind_name = "agg"; break; + case SPL_DEF_BUILTIN: + switch (node->builtin_kind) { + case SPL_BUILTIN_RANGE: + def_kind_name = "builtin.range"; + break; + case SPL_BUILTIN_SLICE: + def_kind_name = "builtin.slice"; + break; + default: + def_kind_name = "builtin"; + break; + } + break; case SPL_DEF_DISTINCT: def_kind_name = "newtype"; break; diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 345a476..69b2bb2 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -15,17 +15,13 @@ typedef enum { SPL_TYPE_BOOL, SPL_TYPE_INT, SPL_TYPE_FLOAT, - SPL_TYPE_UNDEFINED, // 自动配对任意类型的字面量,值为 undefined - SPL_TYPE_NULL, // 自动配对指针/切片的字面量,值为 0 SPL_TYPE_PTR, - SPL_TYPE_SLICE, // 未来拥有泛型后删除 - SPL_TYPE_RANGE, // 未来拥有泛型后删除 SPL_TYPE_ARRAY, SPL_TYPE_STRUCT, SPL_TYPE_UNION, SPL_TYPE_ENUM, + SPL_TYPE_SHAPE, SPL_TYPE_FN, - SPL_TYPE_ID, } spl_type_node_kind_t; typedef enum { @@ -48,7 +44,7 @@ typedef VEC(spl_type_member_t) spl_type_member_vec_t; typedef struct { spl_type_node_kind_t kind; - spl_type_layout_t layout; + spl_type_layout_t layout; // attribute union { struct { usize bits; @@ -57,23 +53,21 @@ typedef struct { struct { usize bits; } float_type; - spl_type_id_t ptr_pointee; - spl_type_id_t slice_element; - spl_type_id_t range_element; + struct { + spl_type_id_t pointee; + } ptr_type; struct { spl_type_id_t element; usize len; } array_type; - spl_type_member_vec_t agg_members; struct { spl_type_member_vec_t variants; spl_type_id_t tag_type; - } adt_type; // ADT + } agg_type; // adt record aggregate struct { spl_type_id_vec_t params; spl_type_id_t ret; } fn_type; - spl_type_id_t type_id; }; } spl_type_node_t; typedef VEC(spl_type_node_t) spl_type_node_vec_t; @@ -84,13 +78,19 @@ typedef enum { SPL_DEF_MEMBER, SPL_DEF_VAR, SPL_DEF_FN, - SPL_DEF_AGG, // include enum variants - SPL_DEF_DISTINCT, // newtype - SPL_DEF_ALIAS, // sametypes + SPL_DEF_AGG, + SPL_DEF_DISTINCT, + SPL_DEF_ALIAS, + SPL_DEF_BUILTIN, } spl_def_node_kind_t; typedef struct { spl_def_node_kind_t kind; + enum { + SPL_BUILTIN_NONE, + SPL_BUILTIN_SLICE, + SPL_BUILTIN_RANGE, + } builtin_kind; const char *name; spl_dbg_node_t dbg_node; spl_type_id_t type_id; @@ -127,12 +127,24 @@ spl_type_id_t spl_type_builder_simple(spl_type_t *type, spl_type_node_kind_t kin spl_type_id_t spl_type_builder_int(spl_type_t *type, usize bits, int is_signed); spl_type_id_t spl_type_builder_float(spl_type_t *type, usize bits); spl_type_id_t spl_type_builder_ptr(spl_type_t *type, spl_type_id_t pointee); -spl_type_id_t spl_type_builder_slice(spl_type_t *type, spl_type_id_t element); -spl_type_id_t spl_type_builder_range(spl_type_t *type, spl_type_id_t element); spl_type_id_t spl_type_builder_array(spl_type_t *type, spl_type_id_t element, usize len); spl_type_id_t spl_type_builder_fn(spl_type_t *type, spl_type_id_t ret, const spl_type_id_t *params, usize nparams); spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk, - const spl_type_member_t *members, usize nmembers, - spl_type_id_t tag_type, spl_type_layout_t layout); + spl_type_member_vec_t *variants, spl_type_id_t tag_type, + spl_type_layout_t layout); + +spl_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name); + +spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id); +spl_def_id_t spl_def_builder_void(spl_type_t *type); +spl_def_id_t spl_def_builder_bool(spl_type_t *type); +spl_def_id_t spl_def_builder_int(spl_type_t *type, usize bits, int is_signed); +spl_def_id_t spl_def_builder_float(spl_type_t *type, usize bits); +spl_def_id_t spl_def_builder_ptr(spl_type_t *type, spl_def_id_t pointee); +spl_def_id_t spl_def_builder_array(spl_type_t *type, spl_def_id_t element, usize len); +spl_def_id_t spl_def_builder_slice(spl_type_t *type, spl_type_id_t element); +spl_def_id_t spl_def_builder_range(spl_type_t *type); +spl_def_id_t spl_def_builder_fn(spl_type_t *type); + #endif /* __SPL_TYPE_H__ */ diff --git a/stage1/splc0.c b/stage1/splc0.c index 7912ab2..390499c 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -79,7 +79,7 @@ static int compile_spl(const char *src, const char *fname, const char *outpath, } spl_ast_t ast; spl_ast_init(&ast, &toks); - spl_ast_prase(&ast); + spl_ast_parse(&ast); if (ast.parsed < 0) { printf("parse failed, no output\n"); // memory leak @@ -91,63 +91,63 @@ static int compile_spl(const char *src, const char *fname, const char *outpath, // memory leak return 0; } - spl_sema_t sema; - spl_type_t type; - spl_scope_t scope; - spl_type_init(&type); - spl_scope_init(&scope); - spl_sema_init(&sema, &ast, &type, &scope); - sema.ast = * - spl_sema_run(&sema); - if (sema.error_count) { - printf("sema errors=%d, no output\n", sema.error_count); - // memory leak - return 1; - } - if (dump == DUMP_SEMA) { - spl_sema_dump(&sema); - spl_ast_dump(&ast, ast.root); - // memory leak - return 0; - } + // spl_sema_t sema; + // spl_type_t type; + // spl_scope_t scope; + // spl_type_init(&type); + // spl_scope_init(&scope); + // spl_sema_init(&sema, &ast, &type, &scope); + // sema.ast = * + // spl_sema_run(&sema); + // if (sema.error_count) { + // printf("sema errors=%d, no output\n", sema.error_count); + // // memory leak + // return 1; + // } + // if (dump == DUMP_SEMA) { + // spl_sema_dump(&sema); + // spl_ast_dump(&ast, ast.root); + // // memory leak + // return 0; + // } - spl_ast2ir_t a2ir; - spl_ir_builder_t ir_builder; - spl_ir_builder_init(&ir_builder); - spl_ast2ir_init(&a2ir, &ir_builder, &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; - } - if (dump == DUMP_IR) { - spl_ir_dump(&ir_builder.ir, &type); - // memory leak - return 0; - } + // spl_ast2ir_t a2ir; + // spl_ir_builder_t ir_builder; + // spl_ir_builder_init(&ir_builder); + // spl_ast2ir_init(&a2ir, &ir_builder, &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; + // } + // if (dump == DUMP_IR) { + // spl_ir_dump(&ir_builder.ir, &type); + // // memory leak + // return 0; + // } - spl_ir2vm_t ir2vm; - spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, sema.type); - int rc = spl_ir2vm_run(&ir2vm); - if (rc != 0) { - printf("ir2vm error %d", rc); - return rc; - } - if (dump == DUMP_VM) { - spl_prog_dump(&ir2vm.prog); - // memory leak - return 0; - } + // spl_ir2vm_t ir2vm; + // spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, sema.type); + // int rc = spl_ir2vm_run(&ir2vm); + // if (rc != 0) { + // printf("ir2vm error %d", rc); + // return rc; + // } + // if (dump == DUMP_VM) { + // spl_prog_dump(&ir2vm.prog); + // // memory leak + // return 0; + // } - spl_prog_store_to_file(outpath, &ir2vm.prog); + // spl_prog_store_to_file(outpath, &ir2vm.prog); - spl_ir2vm_drop(&ir2vm); - spl_ast2ir_drop(&a2ir); - spl_sema_drop(&sema); - spl_ast_drop(&ast); + // spl_ir2vm_drop(&ir2vm); + // spl_ast2ir_drop(&a2ir); + // spl_sema_drop(&sema); + // spl_ast_drop(&ast); return 0; }