stage1 重写进行代码设计并重构 提供diag替换老旧错误处理
This commit is contained in:
1 parent
7cbe2d2b9a
commit
e4347cc3ea
14 files changed
+960
-503
No files matched your search
@@ -23,6 +23,7 @@ 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 *test_srcs[] = {"stage0/test_spl_vm.c", VM_SRCS};
|
||||||
static const char *splc0_srcs[] = {
|
static const char *splc0_srcs[] = {
|
||||||
"stage1/splc0.c",
|
"stage1/splc0.c",
|
||||||
|
"stage1/spl_diag.c",
|
||||||
"stage1/spl_lexer.c",
|
"stage1/spl_lexer.c",
|
||||||
"stage1/spl_ast.c",
|
"stage1/spl_ast.c",
|
||||||
"stage1/spl_dumptree.c",
|
"stage1/spl_dumptree.c",
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#define SYSCALL_0(name, ret_expr) \
|
#define SYSCALL_0(name, ret_expr) \
|
||||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||||
|
(void)_vm; \
|
||||||
CHECK_NARGS(#name, 0); \
|
CHECK_NARGS(#name, 0); \
|
||||||
(void)args; \
|
(void)args; \
|
||||||
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
|
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
|
|
||||||
#define SYSCALL_1(name, t1, ret_expr) \
|
#define SYSCALL_1(name, t1, ret_expr) \
|
||||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||||
|
(void)_vm; \
|
||||||
CHECK_NARGS(#name, 1); \
|
CHECK_NARGS(#name, 1); \
|
||||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||||
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
|
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
|
||||||
@@ -51,6 +53,7 @@
|
|||||||
|
|
||||||
#define SYSCALL_2(name, t1, t2, ret_expr) \
|
#define SYSCALL_2(name, t1, t2, ret_expr) \
|
||||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||||
|
(void)_vm; \
|
||||||
CHECK_NARGS(#name, 2); \
|
CHECK_NARGS(#name, 2); \
|
||||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||||
t2 a2 = (t2)(uintptr_t)args[1]; \
|
t2 a2 = (t2)(uintptr_t)args[1]; \
|
||||||
@@ -59,6 +62,7 @@
|
|||||||
|
|
||||||
#define SYSCALL_3(name, t1, t2, t3, ret_expr) \
|
#define SYSCALL_3(name, t1, t2, t3, ret_expr) \
|
||||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||||
|
(void)_vm; \
|
||||||
CHECK_NARGS(#name, 3); \
|
CHECK_NARGS(#name, 3); \
|
||||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||||
t2 a2 = (t2)(uintptr_t)args[1]; \
|
t2 a2 = (t2)(uintptr_t)args[1]; \
|
||||||
@@ -68,6 +72,7 @@
|
|||||||
|
|
||||||
#define SYSCALL_4(name, t1, t2, t3, t4, ret_expr) \
|
#define SYSCALL_4(name, t1, t2, t3, t4, ret_expr) \
|
||||||
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
|
||||||
|
(void)_vm; \
|
||||||
CHECK_NARGS(#name, 4); \
|
CHECK_NARGS(#name, 4); \
|
||||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||||
t2 a2 = (t2)(uintptr_t)args[1]; \
|
t2 a2 = (t2)(uintptr_t)args[1]; \
|
||||||
@@ -145,6 +150,7 @@ SYSCALL_4(vm_fwrite, const void *, size_t, size_t, FILE *, fwrite(a1, a2, a3, a4
|
|||||||
|
|
||||||
/* vm_fsize - get file size in bytes */
|
/* vm_fsize - get file size in bytes */
|
||||||
static spl_vm_val_t vm_fsize(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
static spl_vm_val_t vm_fsize(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||||
|
(void)_vm;
|
||||||
CHECK_NARGS("vm_fsize", 1);
|
CHECK_NARGS("vm_fsize", 1);
|
||||||
FILE *f = (FILE *)(uintptr_t)args[0];
|
FILE *f = (FILE *)(uintptr_t)args[0];
|
||||||
long cur = ftell(f);
|
long cur = ftell(f);
|
||||||
@@ -160,6 +166,7 @@ SYSCALL_0(vm_stderr, stderr)
|
|||||||
|
|
||||||
/* vm_read_file - read entire file into a malloc'd, null-terminated buffer */
|
/* vm_read_file - read entire file into a malloc'd, null-terminated buffer */
|
||||||
static spl_vm_val_t vm_read_file(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
static spl_vm_val_t vm_read_file(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||||
|
(void)_vm;
|
||||||
CHECK_NARGS("vm_read_file", 1);
|
CHECK_NARGS("vm_read_file", 1);
|
||||||
const char *path = (const char *)(uintptr_t)args[0];
|
const char *path = (const char *)(uintptr_t)args[0];
|
||||||
if (path == nullptr) {
|
if (path == nullptr) {
|
||||||
@@ -248,6 +255,7 @@ static spl_vm_val_t vm_memcmp(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static spl_vm_val_t vm_printf(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
static spl_vm_val_t vm_printf(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||||
|
(void)_vm;
|
||||||
if (nargs <= 0)
|
if (nargs <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -323,6 +331,7 @@ static spl_vm_val_t vm_printf(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
|||||||
|
|
||||||
/* vm_new - create a new sub-VM instance, returns spl_vm_t* */
|
/* vm_new - create a new sub-VM instance, returns spl_vm_t* */
|
||||||
static spl_vm_val_t vm_new(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
static spl_vm_val_t vm_new(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||||
|
(void)_vm;
|
||||||
CHECK_NARGS("vm_new", 0);
|
CHECK_NARGS("vm_new", 0);
|
||||||
(void)args;
|
(void)args;
|
||||||
spl_vm_t *vm = (spl_vm_t *)malloc(sizeof(spl_vm_t));
|
spl_vm_t *vm = (spl_vm_t *)malloc(sizeof(spl_vm_t));
|
||||||
@@ -334,6 +343,7 @@ static spl_vm_val_t vm_new(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
|||||||
|
|
||||||
/* vm_drop - destroy a sub-VM and its loaded program */
|
/* vm_drop - destroy a sub-VM and its loaded program */
|
||||||
static spl_vm_val_t vm_drop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
static spl_vm_val_t vm_drop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||||
|
(void)_vm;
|
||||||
CHECK_NARGS("vm_drop", 1);
|
CHECK_NARGS("vm_drop", 1);
|
||||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||||
if (!vm)
|
if (!vm)
|
||||||
@@ -350,6 +360,7 @@ static spl_vm_val_t vm_drop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
|||||||
|
|
||||||
/* vm_load - load a .sir file, register syscalls, return spl_prog_t* */
|
/* vm_load - load a .sir file, register syscalls, return spl_prog_t* */
|
||||||
static spl_vm_val_t vm_load(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
static spl_vm_val_t vm_load(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||||
|
(void)_vm;
|
||||||
CHECK_NARGS("vm_load", 2);
|
CHECK_NARGS("vm_load", 2);
|
||||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||||
const char *path = (const char *)(uintptr_t)args[1];
|
const char *path = (const char *)(uintptr_t)args[1];
|
||||||
@@ -374,6 +385,7 @@ static spl_vm_val_t vm_load(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
|||||||
|
|
||||||
/* vm_push - push a value onto the sub-VM's stack (for passing arguments) */
|
/* vm_push - push a value onto the sub-VM's stack (for passing arguments) */
|
||||||
static spl_vm_val_t vm_push(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
static spl_vm_val_t vm_push(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||||
|
(void)_vm;
|
||||||
CHECK_NARGS("vm_push", 2);
|
CHECK_NARGS("vm_push", 2);
|
||||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||||
spl_vm_val_t val = args[1];
|
spl_vm_val_t val = args[1];
|
||||||
@@ -399,6 +411,7 @@ static spl_vm_val_t vm_push(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
|||||||
* - Sets ip to the function address
|
* - Sets ip to the function address
|
||||||
*/
|
*/
|
||||||
static spl_vm_val_t vm_call(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
static spl_vm_val_t vm_call(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
|
||||||
|
(void)_vm;
|
||||||
CHECK_NARGS("vm_call", 3);
|
CHECK_NARGS("vm_call", 3);
|
||||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||||
const char *name = (const char *)(uintptr_t)args[1];
|
const char *name = (const char *)(uintptr_t)args[1];
|
||||||
|
|||||||
+104
-99
@@ -59,12 +59,34 @@ const char *spl_unary_op_name(spl_unary_op_t op) {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_ast_t *ast;
|
spl_ast_t *ast;
|
||||||
|
spl_diag_t *diag;
|
||||||
usize pos;
|
usize pos;
|
||||||
int failed;
|
int failed;
|
||||||
int stop_as;
|
int stop_as;
|
||||||
int stop_agg;
|
int stop_agg;
|
||||||
} parser_t;
|
} parser_t;
|
||||||
|
|
||||||
|
/* token -> dbg 位置;tok 可为 NULL */
|
||||||
|
static spl_dbg_node_t tok_to_dbg(const spl_tok_t *t) {
|
||||||
|
spl_dbg_node_t d = {0};
|
||||||
|
if (t) {
|
||||||
|
d.fname = t->fname;
|
||||||
|
d.line = (int)t->line;
|
||||||
|
d.col = (int)t->col;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parser 层的 fatal 发射。diag 为 NULL 时静默。
|
||||||
|
* 调用者必须紧跟 return / break,因为 diag_fatal 不终止流程。 */
|
||||||
|
#define PARSE_FATAL(p, kind, tok, ...) \
|
||||||
|
do { \
|
||||||
|
if ((p)->diag) { \
|
||||||
|
spl_dbg_node_t _pd = tok_to_dbg(tok); \
|
||||||
|
spl_diag_fatal((p)->diag, (kind), &_pd, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static inline int is_trivia(spl_tok_type_t t) { return t == TOK_ENDLINE || t == TOK_LINE_COMMENT; }
|
static inline int is_trivia(spl_tok_type_t t) { return t == TOK_ENDLINE || t == TOK_LINE_COMMENT; }
|
||||||
|
|
||||||
static inline const spl_tok_t *peek(parser_t *p) {
|
static inline const spl_tok_t *peek(parser_t *p) {
|
||||||
@@ -301,7 +323,7 @@ static void parse_tag_list(parser_t *p, spl_ast_node_ref_vec_t *out, int is_exte
|
|||||||
if (is_external) {
|
if (is_external) {
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_NOT) {
|
if (!t || t->type != TOK_NOT) {
|
||||||
SPL_FATAL(t, "expected '!' in external tag");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '!' in external tag");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -309,7 +331,7 @@ static void parse_tag_list(parser_t *p, spl_ast_node_ref_vec_t *out, int is_exte
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_IDENT) {
|
if (!t || t->type != TOK_IDENT) {
|
||||||
SPL_FATAL(t, "expected tag name");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected tag name");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -328,7 +350,7 @@ static void parse_tag_list(parser_t *p, spl_ast_node_ref_vec_t *out, int is_exte
|
|||||||
node_at(p->ast, ref)->tag_item.args = args;
|
node_at(p->ast, ref)->tag_item.args = args;
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')' in tag args");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')' in tag args");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -363,15 +385,9 @@ static void parse_param_list(parser_t *p, spl_ast_node_ref_vec_t *out) {
|
|||||||
if (peek(p) && peek(p)->type == TOK_COMMA)
|
if (peek(p) && peek(p)->type == TOK_COMMA)
|
||||||
advance(p);
|
advance(p);
|
||||||
break;
|
break;
|
||||||
// } else if (t->type == KW_VOID) {
|
|
||||||
// advance(p);
|
|
||||||
// t = peek(p);
|
|
||||||
// if (!t || t->type != TOK_R_PAREN) {
|
|
||||||
// SPL_FATAL(t, "expected ')' after void");
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "unexpected token in parameter list");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t,
|
||||||
|
"unexpected token in parameter list");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,14 +400,14 @@ static spl_ast_node_ref_t parse_param_decl_impl(parser_t *p) {
|
|||||||
|
|
||||||
const spl_tok_t *name = peek(p);
|
const spl_tok_t *name = peek(p);
|
||||||
if (!name || (name->type != TOK_IDENT && name->type != KW_UNDERSCORE)) {
|
if (!name || (name->type != TOK_IDENT && name->type != KW_UNDERSCORE)) {
|
||||||
SPL_FATAL(name, "expected parameter name or '_'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, name, "expected parameter name or '_'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != TOK_COLON) {
|
if (!t || t->type != TOK_COLON) {
|
||||||
SPL_FATAL(t, "expected ':' in parameter declaration");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ':' in parameter declaration");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -415,14 +431,14 @@ static spl_ast_node_ref_t parse_fn_decl(parser_t *p, spl_ast_node_ref_vec_t tag_
|
|||||||
|
|
||||||
const spl_tok_t *name = peek(p);
|
const spl_tok_t *name = peek(p);
|
||||||
if (!name || name->type != TOK_IDENT) {
|
if (!name || name->type != TOK_IDENT) {
|
||||||
SPL_FATAL(name ? name : kw, "expected function name");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, name ? name : kw, "expected function name");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != TOK_L_PAREN) {
|
if (!t || t->type != TOK_L_PAREN) {
|
||||||
SPL_FATAL(t, "expected '(' in function declaration");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '(' in function declaration");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -432,7 +448,7 @@ static spl_ast_node_ref_t parse_fn_decl(parser_t *p, spl_ast_node_ref_vec_t tag_
|
|||||||
parse_param_list(p, ¶ms);
|
parse_param_list(p, ¶ms);
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')' in function declaration");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')' in function declaration");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -451,7 +467,8 @@ static spl_ast_node_ref_t parse_fn_decl(parser_t *p, spl_ast_node_ref_vec_t tag_
|
|||||||
} else if (t && t->type == TOK_SEMICOLON) {
|
} else if (t && t->type == TOK_SEMICOLON) {
|
||||||
advance(p);
|
advance(p);
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "function declaration must end with ';' or block");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t,
|
||||||
|
"function declaration must end with ';' or block");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,14 +491,14 @@ static spl_ast_node_ref_t parse_type_decl(parser_t *p, spl_ast_node_ref_vec_t ta
|
|||||||
|
|
||||||
const spl_tok_t *name = peek(p);
|
const spl_tok_t *name = peek(p);
|
||||||
if (!name || name->type != TOK_IDENT) {
|
if (!name || name->type != TOK_IDENT) {
|
||||||
SPL_FATAL(name ? name : kw, "expected type name");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, name ? name : kw, "expected type name");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != TOK_ASSIGN) {
|
if (!t || t->type != TOK_ASSIGN) {
|
||||||
SPL_FATAL(t, "expected '=' in type declaration");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '=' in type declaration");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -636,7 +653,7 @@ static spl_ast_node_ref_t parse_container_declaration(parser_t *p) {
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
SPL_FATAL(t, "unrecognized declaration");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unrecognized declaration");
|
||||||
vec_free(tag_list);
|
vec_free(tag_list);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -659,7 +676,8 @@ static spl_ast_node_ref_t parse_var_pattern_atom(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
const spl_tok_t *name = peek(p);
|
const spl_tok_t *name = peek(p);
|
||||||
if (!name || name->type != TOK_IDENT) {
|
if (!name || name->type != TOK_IDENT) {
|
||||||
SPL_FATAL(name, "expected identifier after '.' in pattern");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, name,
|
||||||
|
"expected identifier after '.' in pattern");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -674,7 +692,7 @@ static spl_ast_node_ref_t parse_var_pattern_atom(parser_t *p) {
|
|||||||
node_at(p->ast, ref)->pattern_dot.sub_pattern = sub;
|
node_at(p->ast, ref)->pattern_dot.sub_pattern = sub;
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_BRACKET) {
|
if (!t || t->type != TOK_R_BRACKET) {
|
||||||
SPL_FATAL(t, "expected ']' in pattern");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ']' in pattern");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -685,7 +703,7 @@ static spl_ast_node_ref_t parse_var_pattern_atom(parser_t *p) {
|
|||||||
spl_ast_node_ref_t inner = parse_var_pattern(p);
|
spl_ast_node_ref_t inner = parse_var_pattern(p);
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')' in pattern");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')' in pattern");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -700,7 +718,7 @@ static spl_ast_node_ref_t parse_var_pattern_atom(parser_t *p) {
|
|||||||
}
|
}
|
||||||
return ref;
|
return ref;
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "unexpected token in pattern");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unexpected token in pattern");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -753,7 +771,7 @@ static spl_ast_node_ref_t parse_match_pattern(parser_t *p) {
|
|||||||
static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
||||||
const spl_tok_t *bt = peek(p);
|
const spl_tok_t *bt = peek(p);
|
||||||
if (!bt) {
|
if (!bt) {
|
||||||
SPL_FATAL(bt, "expected type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, bt, "expected type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,7 +780,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != TOK_L_PAREN) {
|
if (!t || t->type != TOK_L_PAREN) {
|
||||||
SPL_FATAL(t, "expected '(' in function type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '(' in function type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -785,7 +803,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')' in function type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')' in function type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -808,7 +826,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != TOK_L_BRACE) {
|
if (!t || t->type != TOK_L_BRACE) {
|
||||||
SPL_FATAL(t, "expected '{' in aggregate type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '{' in aggregate type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -822,7 +840,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
|||||||
while (!p->failed) {
|
while (!p->failed) {
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type == TOK_EOF) {
|
if (!t || t->type == TOK_EOF) {
|
||||||
SPL_FATAL(t, "aggregate type missing '}'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "aggregate type missing '}'");
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
if (t->type == TOK_R_BRACE) {
|
if (t->type == TOK_R_BRACE) {
|
||||||
@@ -862,10 +880,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
|||||||
(len == 5 && strncmp(name, "usize", 5) == 0) ||
|
(len == 5 && strncmp(name, "usize", 5) == 0) ||
|
||||||
(len == 3 && strncmp(name, "f32", 3) == 0) ||
|
(len == 3 && strncmp(name, "f32", 3) == 0) ||
|
||||||
(len == 3 && strncmp(name, "f64", 3) == 0) ||
|
(len == 3 && strncmp(name, "f64", 3) == 0) ||
|
||||||
(len == 4 && strncmp(name, "bool", 4) == 0)
|
(len == 4 && strncmp(name, "bool", 4) == 0)) {
|
||||||
// (len == 4 && strncmp(name, "void", 4) == 0) ||
|
|
||||||
// (len == 3 && strncmp(name, "any", 3) == 0)
|
|
||||||
) {
|
|
||||||
advance(p);
|
advance(p);
|
||||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PATH, bt);
|
spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PATH, bt);
|
||||||
spl_ast_node_t *tp = node_at(p->ast, ref);
|
spl_ast_node_t *tp = node_at(p->ast, ref);
|
||||||
@@ -885,7 +900,8 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
const spl_tok_t *seg = peek(p);
|
const spl_tok_t *seg = peek(p);
|
||||||
if (!seg || seg->type != TOK_IDENT) {
|
if (!seg || seg->type != TOK_IDENT) {
|
||||||
SPL_FATAL(seg, "expected identifier after '.' in type path");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, seg,
|
||||||
|
"expected identifier after '.' in type path");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -906,7 +922,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPL_FATAL(bt, "unrecognized type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, bt, "unrecognized type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -918,7 +934,7 @@ static spl_ast_node_ref_t parse_type_comptime_call(parser_t *p) {
|
|||||||
|
|
||||||
const spl_tok_t *name = peek(p);
|
const spl_tok_t *name = peek(p);
|
||||||
if (!name || name->type != TOK_IDENT) {
|
if (!name || name->type != TOK_IDENT) {
|
||||||
SPL_FATAL(name, "expected comptime name");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, name, "expected comptime name");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -932,7 +948,7 @@ static spl_ast_node_ref_t parse_type_comptime_call(parser_t *p) {
|
|||||||
args = parse_expr_list(p);
|
args = parse_expr_list(p);
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')' in comptime type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')' in comptime type");
|
||||||
vec_free(args);
|
vec_free(args);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -949,7 +965,7 @@ static spl_ast_node_ref_t parse_type_comptime_call(parser_t *p) {
|
|||||||
static spl_ast_node_ref_t parse_type_expr(parser_t *p) {
|
static spl_ast_node_ref_t parse_type_expr(parser_t *p) {
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t) {
|
if (!t) {
|
||||||
SPL_FATAL(t, "expected type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -980,7 +996,7 @@ static spl_ast_node_ref_t parse_type_expr(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_BRACKET) {
|
if (!t || t->type != TOK_R_BRACKET) {
|
||||||
SPL_FATAL(t, "expected ']' in array type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ']' in array type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1027,7 +1043,7 @@ static spl_ast_node_ref_t parse_type_expr(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')' in parenthesized type");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')' in parenthesized type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1071,37 +1087,35 @@ static spl_ast_node_ref_vec_t parse_aggregate_fields(parser_t *p) {
|
|||||||
|
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != TOK_L_BRACE) {
|
if (!t || t->type != TOK_L_BRACE) {
|
||||||
SPL_FATAL(t, "expected '{' in aggregate literal");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '{' in aggregate literal");
|
||||||
return fields; // 空 vec,调用者处理
|
return fields;
|
||||||
}
|
}
|
||||||
advance(p); // 消费 '{'
|
advance(p);
|
||||||
|
|
||||||
while (!p->failed) {
|
while (!p->failed) {
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF)
|
if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 字段必须由 '.' 开头
|
|
||||||
if (t->type != TOK_DOT) {
|
if (t->type != TOK_DOT) {
|
||||||
SPL_FATAL(t, "expected '.' in aggregate field initializer");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t,
|
||||||
|
"expected '.' in aggregate field initializer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_IDENT) {
|
if (!t || t->type != TOK_IDENT) {
|
||||||
SPL_FATAL(t, "expected field name after '.'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected field name after '.'");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
// 创建 struct_init_item 节点
|
|
||||||
spl_ast_node_ref_t item_ref = new_node(p, SPL_AST_STRUCT_INIT_ITEM, t);
|
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);
|
spl_ast_node_t *item = node_at(p->ast, item_ref);
|
||||||
SET_STR_FIELD(p->ast, item->struct_init_item.name, t);
|
SET_STR_FIELD(p->ast, item->struct_init_item.name, t);
|
||||||
item->struct_init_item.expr = 0;
|
item->struct_init_item.expr = 0;
|
||||||
|
|
||||||
// 可选:= 表达式
|
|
||||||
if (peek(p) && peek(p)->type == TOK_ASSIGN) {
|
if (peek(p) && peek(p)->type == TOK_ASSIGN) {
|
||||||
advance(p);
|
advance(p);
|
||||||
spl_ast_node_ref_t expr_ref = parse_expr(p);
|
spl_ast_node_ref_t expr_ref = parse_expr(p);
|
||||||
@@ -1111,7 +1125,6 @@ static spl_ast_node_ref_vec_t parse_aggregate_fields(parser_t *p) {
|
|||||||
|
|
||||||
vec_push(fields, item_ref);
|
vec_push(fields, item_ref);
|
||||||
|
|
||||||
// 分隔符
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) {
|
if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) {
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1122,9 +1135,9 @@ static spl_ast_node_ref_vec_t parse_aggregate_fields(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_BRACE) {
|
if (!t || t->type != TOK_R_BRACE) {
|
||||||
SPL_FATAL(t, "expected '}' in aggregate literal");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '}' in aggregate literal");
|
||||||
} else {
|
} else {
|
||||||
advance(p); // 消费 '}'
|
advance(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
@@ -1295,7 +1308,7 @@ static spl_ast_node_ref_t parse_prefix(parser_t *p) {
|
|||||||
else if (kw && kw->type == KW_FOR)
|
else if (kw && kw->type == KW_FOR)
|
||||||
ref = parse_for_expr(p);
|
ref = parse_for_expr(p);
|
||||||
else {
|
else {
|
||||||
SPL_FATAL(kw, "expected while/loop/for after label");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, kw, "expected while/loop/for after label");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!ref)
|
if (!ref)
|
||||||
@@ -1357,7 +1370,7 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')' in call");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')' in call");
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1378,7 +1391,8 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
|
|||||||
spl_ast_node_ref_t ref = mk_unary(p, t, SPL_UNARY_OP_DEREF, expr);
|
spl_ast_node_ref_t ref = mk_unary(p, t, SPL_UNARY_OP_DEREF, expr);
|
||||||
expr = ref;
|
expr = ref;
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(next, "expected identifier or '*' after '.'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, next,
|
||||||
|
"expected identifier or '*' after '.'");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (t->type == TOK_L_BRACKET) {
|
} else if (t->type == TOK_L_BRACKET) {
|
||||||
@@ -1392,7 +1406,7 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
|
|||||||
end = parse_expr(p);
|
end = parse_expr(p);
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_BRACKET) {
|
if (!t || t->type != TOK_R_BRACKET) {
|
||||||
SPL_FATAL(t, "expected ']' in slice");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ']' in slice");
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1404,7 +1418,7 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
|
|||||||
} else {
|
} else {
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_BRACKET) {
|
if (!t || t->type != TOK_R_BRACKET) {
|
||||||
SPL_FATAL(t, "expected ']' in index");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ']' in index");
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1423,7 +1437,7 @@ 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_t parse_primary(parser_t *p) {
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t) {
|
if (!t) {
|
||||||
SPL_FATAL(t, "unexpected end of expression");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unexpected end of expression");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1491,7 +1505,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
const spl_tok_t *nx = peek(p);
|
const spl_tok_t *nx = peek(p);
|
||||||
if (!nx) {
|
if (!nx) {
|
||||||
SPL_FATAL(t, "unexpected '.'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unexpected '.'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (nx->type == TOK_L_BRACE && !p->stop_agg) {
|
if (nx->type == TOK_L_BRACE && !p->stop_agg) {
|
||||||
@@ -1508,7 +1522,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
|||||||
spl_ast_node_ref_vec_t elems = parse_expr_list(p);
|
spl_ast_node_ref_vec_t elems = parse_expr_list(p);
|
||||||
const spl_tok_t *close = peek(p);
|
const spl_tok_t *close = peek(p);
|
||||||
if (!close || close->type != TOK_R_BRACKET) {
|
if (!close || close->type != TOK_R_BRACKET) {
|
||||||
SPL_FATAL(close, "expected ']'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, close, "expected ']'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p); // 消费 ']'
|
advance(p); // 消费 ']'
|
||||||
@@ -1518,7 +1532,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
|||||||
arr->array_literal.elem_type = 0;
|
arr->array_literal.elem_type = 0;
|
||||||
return ref;
|
return ref;
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(nx, "expected '{' or '[' after '.'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, nx, "expected '{' or '[' after '.'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1552,7 +1566,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
|||||||
}
|
}
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1562,7 +1576,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
|||||||
} else {
|
} else {
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1581,7 +1595,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
|||||||
case KW_MATCH:
|
case KW_MATCH:
|
||||||
return parse_match_expr(p);
|
return parse_match_expr(p);
|
||||||
default:
|
default:
|
||||||
SPL_FATAL(t, "unrecognized expression");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unrecognized expression");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1609,7 +1623,7 @@ static spl_ast_node_ref_t parse_array_literal(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_BRACKET) {
|
if (!t || t->type != TOK_R_BRACKET) {
|
||||||
SPL_FATAL(t, "expected ']' in array literal");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ']' in array literal");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1618,7 +1632,7 @@ static spl_ast_node_ref_t parse_array_literal(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_L_BRACKET) {
|
if (!t || t->type != TOK_L_BRACKET) {
|
||||||
SPL_FATAL(t, "expected '[' in array literal");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '[' in array literal");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1627,7 +1641,7 @@ static spl_ast_node_ref_t parse_array_literal(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_BRACKET) {
|
if (!t || t->type != TOK_R_BRACKET) {
|
||||||
SPL_FATAL(t, "expected ']' in array literal");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ']' in array literal");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1650,7 +1664,7 @@ static spl_ast_node_ref_t parse_comptime_call(parser_t *p) {
|
|||||||
|
|
||||||
const spl_tok_t *name = peek(p);
|
const spl_tok_t *name = peek(p);
|
||||||
if (!name || name->type != TOK_IDENT) {
|
if (!name || name->type != TOK_IDENT) {
|
||||||
SPL_FATAL(name, "expected comptime name");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, name, "expected comptime name");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1666,7 +1680,7 @@ static spl_ast_node_ref_t parse_comptime_call(parser_t *p) {
|
|||||||
args = parse_expr_list(p);
|
args = parse_expr_list(p);
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_PAREN) {
|
if (!t || t->type != TOK_R_PAREN) {
|
||||||
SPL_FATAL(t, "expected ')' in comptime call");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')' in comptime call");
|
||||||
vec_free(args);
|
vec_free(args);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1688,7 +1702,7 @@ static spl_ast_node_ref_t parse_label(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
const spl_tok_t *name = peek(p);
|
const spl_tok_t *name = peek(p);
|
||||||
if (!name || name->type != TOK_IDENT) {
|
if (!name || name->type != TOK_IDENT) {
|
||||||
SPL_FATAL(name, "expected identifier after '$'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, name, "expected identifier after '$'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1726,14 +1740,15 @@ static spl_ast_node_ref_t parse_if_expr(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
init_expr = parse_expr(p);
|
init_expr = parse_expr(p);
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "expected '=' in if var");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '=' in if var");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (t && t->type == TOK_ASSIGN) {
|
} else if (t && t->type == TOK_ASSIGN) {
|
||||||
advance(p);
|
advance(p);
|
||||||
init_expr = parse_expr(p);
|
init_expr = parse_expr(p);
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "expected type annotation or '=' in if var");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t,
|
||||||
|
"expected type annotation or '=' in if var");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1847,7 +1862,7 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
|
|||||||
|
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != KW_AS) {
|
if (!t || t->type != KW_AS) {
|
||||||
SPL_FATAL(t, "expected 'as' in for loop");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected 'as' in for loop");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1856,7 +1871,7 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
|
|||||||
vec_init(idents);
|
vec_init(idents);
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || (t->type != TOK_IDENT && t->type != KW_UNDERSCORE)) {
|
if (!t || (t->type != TOK_IDENT && t->type != KW_UNDERSCORE)) {
|
||||||
SPL_FATAL(t, "expected binding variable or '_' in for");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected binding variable or '_' in for");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1868,7 +1883,8 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
|
|||||||
advance(p);
|
advance(p);
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || (t->type != TOK_IDENT && t->type != KW_UNDERSCORE)) {
|
if (!t || (t->type != TOK_IDENT && t->type != KW_UNDERSCORE)) {
|
||||||
SPL_FATAL(t, "expected binding variable or '_' in for");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t,
|
||||||
|
"expected binding variable or '_' in for");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1919,7 +1935,7 @@ static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *patterns_out,
|
|||||||
|
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != TOK_RIGHT_FAT_ARROW) {
|
if (!t || t->type != TOK_RIGHT_FAT_ARROW) {
|
||||||
SPL_FATAL(t, "expected '=>' in match arm");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '=>' in match arm");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1927,7 +1943,7 @@ static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *patterns_out,
|
|||||||
spl_ast_node_ref_t body;
|
spl_ast_node_ref_t body;
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_L_BRACE) {
|
if (!t || t->type != TOK_L_BRACE) {
|
||||||
SPL_FATAL(t, "expected block after '=>' in match arm");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected block after '=>' in match arm");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
body = parse_block(p);
|
body = parse_block(p);
|
||||||
@@ -1952,7 +1968,7 @@ static spl_ast_node_ref_t parse_match_expr(parser_t *p) {
|
|||||||
|
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != TOK_L_BRACE) {
|
if (!t || t->type != TOK_L_BRACE) {
|
||||||
SPL_FATAL(t, "expected '{' in match");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '{' in match");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1973,7 +1989,7 @@ static spl_ast_node_ref_t parse_match_expr(parser_t *p) {
|
|||||||
|
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
if (!t || t->type != TOK_R_BRACE) {
|
if (!t || t->type != TOK_R_BRACE) {
|
||||||
SPL_FATAL(t, "expected '}' in match");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '}' in match");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -2145,7 +2161,7 @@ static spl_ast_node_ref_t parse_statement(parser_t *p) {
|
|||||||
node_at(p->ast, ref)->statement_expr.expr = expr;
|
node_at(p->ast, ref)->statement_expr.expr = expr;
|
||||||
return ref;
|
return ref;
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "unrecognized statement");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unrecognized statement");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2155,7 +2171,7 @@ static spl_ast_node_ref_t parse_statement(parser_t *p) {
|
|||||||
static spl_ast_node_ref_t parse_block(parser_t *p) {
|
static spl_ast_node_ref_t parse_block(parser_t *p) {
|
||||||
const spl_tok_t *start = peek(p);
|
const spl_tok_t *start = peek(p);
|
||||||
if (!start || start->type != TOK_L_BRACE) {
|
if (!start || start->type != TOK_L_BRACE) {
|
||||||
SPL_FATAL(start, "expected '{'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, start, "expected '{'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -2168,7 +2184,7 @@ static spl_ast_node_ref_t parse_block(parser_t *p) {
|
|||||||
while (!p->failed) {
|
while (!p->failed) {
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type == TOK_EOF) {
|
if (!t || t->type == TOK_EOF) {
|
||||||
SPL_FATAL(t, "block missing '}'");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "block missing '}'");
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
if (t->type == TOK_R_BRACE) {
|
if (t->type == TOK_R_BRACE) {
|
||||||
@@ -2190,7 +2206,8 @@ static spl_ast_node_ref_t parse_block(parser_t *p) {
|
|||||||
vec_push(block->block.stmts, expr);
|
vec_push(block->block.stmts, expr);
|
||||||
} else if (t && t->type == TOK_R_BRACE) {
|
} else if (t && t->type == TOK_R_BRACE) {
|
||||||
if (block->block.tail_expr != 0) {
|
if (block->block.tail_expr != 0) {
|
||||||
SPL_FATAL(t, "only one tail expression allowed");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t,
|
||||||
|
"only one tail expression allowed");
|
||||||
}
|
}
|
||||||
block->block.tail_expr = expr;
|
block->block.tail_expr = expr;
|
||||||
} else {
|
} else {
|
||||||
@@ -2202,12 +2219,13 @@ static spl_ast_node_ref_t parse_block(parser_t *p) {
|
|||||||
if (block_like) {
|
if (block_like) {
|
||||||
vec_push(block->block.stmts, expr);
|
vec_push(block->block.stmts, expr);
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "expected ';' or '}' after expression");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t,
|
||||||
|
"expected ';' or '}' after expression");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "unrecognized token in block");
|
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unrecognized token in block");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2220,7 +2238,7 @@ void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec) {
|
|||||||
vec_init(ast->node_buckets);
|
vec_init(ast->node_buckets);
|
||||||
vec_init(ast->str_buckets);
|
vec_init(ast->str_buckets);
|
||||||
ast->root = 0;
|
ast->root = 0;
|
||||||
ast->parsed = 0;
|
ast->diag = NULL;
|
||||||
|
|
||||||
spl_ast_node_t n = {0};
|
spl_ast_node_t n = {0};
|
||||||
vec_push(ast->node_buckets, n);
|
vec_push(ast->node_buckets, n);
|
||||||
@@ -2232,11 +2250,11 @@ void spl_ast_parse(spl_ast_t *ast) {
|
|||||||
|
|
||||||
parser_t p;
|
parser_t p;
|
||||||
p.ast = ast;
|
p.ast = ast;
|
||||||
|
p.diag = ast->diag;
|
||||||
p.pos = 0;
|
p.pos = 0;
|
||||||
p.failed = 0;
|
p.failed = 0;
|
||||||
p.stop_as = 0;
|
p.stop_as = 0;
|
||||||
p.stop_agg = 0;
|
p.stop_agg = 0;
|
||||||
ast->parsed = 0;
|
|
||||||
|
|
||||||
spl_ast_node_ref_vec_t external_tags;
|
spl_ast_node_ref_vec_t external_tags;
|
||||||
vec_init(external_tags);
|
vec_init(external_tags);
|
||||||
@@ -2276,7 +2294,6 @@ void spl_ast_parse(spl_ast_t *ast) {
|
|||||||
node_at(ast, root)->root.members = container_members;
|
node_at(ast, root)->root.members = container_members;
|
||||||
|
|
||||||
ast->root = root;
|
ast->root = root;
|
||||||
ast->parsed = p.failed ? -1 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_ast_drop(spl_ast_t *ast) {
|
void spl_ast_drop(spl_ast_t *ast) {
|
||||||
@@ -2287,7 +2304,6 @@ void spl_ast_drop(spl_ast_t *ast) {
|
|||||||
vec_for(ast->node_buckets, idx) { vec_free(vec_at(ast->node_buckets, idx).attrs); }
|
vec_for(ast->node_buckets, idx) { vec_free(vec_at(ast->node_buckets, idx).attrs); }
|
||||||
vec_free(ast->node_buckets);
|
vec_free(ast->node_buckets);
|
||||||
vec_free(ast->input);
|
vec_free(ast->input);
|
||||||
ast->parsed = 0;
|
|
||||||
ast->root = 0;
|
ast->root = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2297,16 +2313,6 @@ spl_ast_node_t *spl_ast_node(spl_ast_t *ast, spl_ast_node_ref_t node) {
|
|||||||
return &ast->node_buckets.data[node];
|
return &ast->node_buckets.data[node];
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_ast_valid(spl_ast_t *ast) {
|
|
||||||
if (!ast)
|
|
||||||
return;
|
|
||||||
if (ast->parsed != 1) {
|
|
||||||
printf("valid: AST not parsed successfully (parsed=%d)\n", ast->parsed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* TODO */
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef VEC(char) dump_stack_t;
|
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);
|
static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, bool last);
|
||||||
@@ -2527,7 +2533,6 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SPL_AST_EXPR_AGGREGATE_LIT:
|
case SPL_AST_EXPR_AGGREGATE_LIT:
|
||||||
|
|
||||||
dump_vec(ast, node->aggregate_literal.fields, stack);
|
dump_vec(ast, node->aggregate_literal.fields, stack);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -4,6 +4,7 @@
|
|||||||
#include "../stage0/include/utils.h"
|
#include "../stage0/include/utils.h"
|
||||||
#include "spl_attr.h"
|
#include "spl_attr.h"
|
||||||
#include "spl_dbg.h"
|
#include "spl_dbg.h"
|
||||||
|
#include "spl_diag.h"
|
||||||
#include "spl_lexer.h"
|
#include "spl_lexer.h"
|
||||||
#include "spl_mpa.h"
|
#include "spl_mpa.h"
|
||||||
#include "spl_tok.h"
|
#include "spl_tok.h"
|
||||||
@@ -483,11 +484,12 @@ struct spl_ast_node {
|
|||||||
typedef VEC(spl_ast_node_t) spl_ast_node_vec_t;
|
typedef VEC(spl_ast_node_t) spl_ast_node_vec_t;
|
||||||
typedef VEC(char *) spl_ast_cstr_ref_vec_t;
|
typedef VEC(char *) spl_ast_cstr_ref_vec_t;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int parsed;
|
|
||||||
spl_tok_vec_t input;
|
spl_tok_vec_t input;
|
||||||
spl_ast_node_vec_t node_buckets;
|
spl_ast_node_vec_t node_buckets;
|
||||||
spl_ast_cstr_ref_vec_t str_buckets;
|
spl_ast_cstr_ref_vec_t str_buckets;
|
||||||
spl_ast_node_ref_t root;
|
spl_ast_node_ref_t root;
|
||||||
|
|
||||||
|
spl_diag_t *diag;
|
||||||
} spl_ast_t;
|
} spl_ast_t;
|
||||||
|
|
||||||
void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec /*move*/);
|
void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec /*move*/);
|
||||||
@@ -497,7 +499,6 @@ 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);
|
const char *spl_ast_node_name(spl_ast_node_t *node);
|
||||||
|
|
||||||
void spl_ast_parse(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);
|
void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node);
|
||||||
|
|
||||||
#endif /* __SPL_AST_H__ */
|
#endif /* __SPL_AST_H__ */
|
||||||
+24
-87
@@ -39,9 +39,8 @@ static spl_ir_node_ref_t ast2ir_emit_cast_builtin(spl_ast2ir_t *a, spl_ast_node_
|
|||||||
spl_type_id_t tt, spl_ir_node_ref_t v);
|
spl_type_id_t tt, spl_ir_node_ref_t v);
|
||||||
static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n);
|
static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n);
|
||||||
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
||||||
static spl_ir_node_ref_t emit_if_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n, spl_type_id_t ft,
|
||||||
static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_type_id_t ft, spl_type_id_t tt,
|
spl_type_id_t tt, spl_ir_node_ref_t v);
|
||||||
spl_ir_node_ref_t v);
|
|
||||||
|
|
||||||
static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in,
|
static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in,
|
||||||
spl_ast_node_ref_vec_t *args);
|
spl_ast_node_ref_vec_t *args);
|
||||||
@@ -111,6 +110,7 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy_attrs_to_ir_node(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t ir_ref) {
|
static void copy_attrs_to_ir_node(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t ir_ref) {
|
||||||
if (!ir_ref || !n || vec_size(n->attrs) == 0)
|
if (!ir_ref || !n || vec_size(n->attrs) == 0)
|
||||||
return;
|
return;
|
||||||
@@ -135,7 +135,8 @@ static spl_ir_node_ref_t ast2ir_intrin_cast(spl_ast2ir_t *a, spl_ast_node_t *n,
|
|||||||
spl_ast_node_ref_vec_t *args) {
|
spl_ast_node_ref_vec_t *args) {
|
||||||
usize nargs = vec_size(*args);
|
usize nargs = vec_size(*args);
|
||||||
if (nargs < 1) {
|
if (nargs < 1) {
|
||||||
SPL_ERROR(&n->dbg, "cast builtin requires at least 1 argument");
|
spl_diag_error(a->diag, SPL_DIAG_KIND_INTRIN_ARG_COUNT, &n->dbg,
|
||||||
|
"cast builtin requires at least 1 argument");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_ir_node_ref_t v = emit_expr(a, vec_at(*args, 0));
|
spl_ir_node_ref_t v = emit_expr(a, vec_at(*args, 0));
|
||||||
@@ -149,7 +150,6 @@ static spl_ir_node_ref_t ast2ir_intrin_cast(spl_ast2ir_t *a, spl_ast_node_t *n,
|
|||||||
spl_ast_node_t *targ = spl_ast_node(a->sema->ast, vec_at(*args, 1));
|
spl_ast_node_t *targ = spl_ast_node(a->sema->ast, vec_at(*args, 1));
|
||||||
tt = node_ir(a, targ);
|
tt = node_ir(a, targ);
|
||||||
} else {
|
} else {
|
||||||
/* 单参数形式:目标类型由 sema 在节点上标好的 resolved 类型给出 */
|
|
||||||
tt = node_ir(a, n);
|
tt = node_ir(a, n);
|
||||||
}
|
}
|
||||||
if (!ft || !tt)
|
if (!ft || !tt)
|
||||||
@@ -287,7 +287,6 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
case SPL_AST_EXPR_UNARY: {
|
case SPL_AST_EXPR_UNARY: {
|
||||||
if (n->unary.op != SPL_UNARY_OP_DEREF)
|
if (n->unary.op != SPL_UNARY_OP_DEREF)
|
||||||
return 0;
|
return 0;
|
||||||
/* *p 作为左值,地址就是指针 p 的值 */
|
|
||||||
return emit_expr(a, n->unary.operand);
|
return emit_expr(a, n->unary.operand);
|
||||||
}
|
}
|
||||||
case SPL_AST_EXPR_FIELD: {
|
case SPL_AST_EXPR_FIELD: {
|
||||||
@@ -302,7 +301,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
spl_lang_type_id_t obj_elem = (obj_kind == SPL_LANG_TYPE_PTR) ? obj_ln->extra.elem : 0;
|
spl_lang_type_id_t obj_elem = (obj_kind == SPL_LANG_TYPE_PTR) ? obj_ln->extra.elem : 0;
|
||||||
|
|
||||||
if (spl_intrin_lookup_field(obj_kind, n->field.field) != SPL_INTRIN_NONE)
|
if (spl_intrin_lookup_field(obj_kind, n->field.field) != SPL_INTRIN_NONE)
|
||||||
return 0; /* 内建字段不是左值 */
|
return 0;
|
||||||
|
|
||||||
spl_ir_node_ref_t base = 0;
|
spl_ir_node_ref_t base = 0;
|
||||||
spl_lang_type_id_t agg_lang = 0;
|
spl_lang_type_id_t agg_lang = 0;
|
||||||
@@ -430,7 +429,7 @@ static spl_ir_node_ref_t ast2ir_emit_cast_builtin(spl_ast2ir_t *a, spl_ast_node_
|
|||||||
case SPL_INTRIN_PTR_CAST:
|
case SPL_INTRIN_PTR_CAST:
|
||||||
return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v);
|
return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v);
|
||||||
default:
|
default:
|
||||||
SPL_ERROR(&n->dbg, "as: unknown cast builtin");
|
spl_diag_error(a->diag, SPL_DIAG_KIND_INTERNAL, &n->dbg, "ast2ir: unknown cast builtin");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,7 +447,8 @@ static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
|||||||
|
|
||||||
spl_intrin_t in = spl_intrin_lookup_cast(a->sema->type, ft, tt);
|
spl_intrin_t in = spl_intrin_lookup_cast(a->sema->type, ft, tt);
|
||||||
if (in == SPL_INTRIN_NONE) {
|
if (in == SPL_INTRIN_NONE) {
|
||||||
SPL_ERROR(&n->dbg, "as: no conversion between the given types");
|
spl_diag_error(a->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
|
||||||
|
"as: no conversion between the given types");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return ast2ir_emit_cast_builtin(a, n, in, ft, tt, v);
|
return ast2ir_emit_cast_builtin(a, n, in, ft, tt, v);
|
||||||
@@ -475,7 +475,7 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
if (!from_ir || !to_ir || from_ir == to_ir)
|
if (!from_ir || !to_ir || from_ir == to_ir)
|
||||||
return val;
|
return val;
|
||||||
|
|
||||||
return emit_implicit_cast(a, from_ir, to_ir, val);
|
return emit_implicit_cast(a, n, from_ir, to_ir, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||||
@@ -485,8 +485,6 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
|
|
||||||
switch (n->kind) {
|
switch (n->kind) {
|
||||||
case SPL_AST_EXPR_INT_LIT: {
|
case SPL_AST_EXPR_INT_LIT: {
|
||||||
/* 节点经 coerce 后 resolved 可能是具体 int 或 float。
|
|
||||||
* 值始终存在 int_lit.bits(补码);按 resolved 决定如何构造 IR 常量。 */
|
|
||||||
spl_type_id_t it = node_ir(a, n);
|
spl_type_id_t it = node_ir(a, n);
|
||||||
spl_type_node_t *itn = spl_type_node(a->sema->type, it);
|
spl_type_node_t *itn = spl_type_node(a->sema->type, it);
|
||||||
if (itn && itn->kind == SPL_TYPE_FLOAT) {
|
if (itn && itn->kind == SPL_TYPE_FLOAT) {
|
||||||
@@ -673,7 +671,6 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
case SPL_OP_CMP_LE:
|
case SPL_OP_CMP_LE:
|
||||||
case SPL_OP_CMP_GT:
|
case SPL_OP_CMP_GT:
|
||||||
case SPL_OP_CMP_GE: {
|
case SPL_OP_CMP_GE: {
|
||||||
/* 比较的操作数类型从左侧子节点读(sema 已 coerce 到共同类型) */
|
|
||||||
spl_ast_node_t *cmln = spl_ast_node(a->sema->ast, n->binary.left);
|
spl_ast_node_t *cmln = spl_ast_node(a->sema->ast, n->binary.left);
|
||||||
spl_type_id_t op_tid = cmln ? node_ir(a, cmln) : 0;
|
spl_type_id_t op_tid = cmln ? node_ir(a, cmln) : 0;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@@ -719,14 +716,12 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
if (!fn)
|
if (!fn)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* 先求所有参数 */
|
|
||||||
usize nargs = vec_size(n->call.args);
|
usize nargs = vec_size(n->call.args);
|
||||||
spl_ir_node_ref_vec_t arg_refs;
|
spl_ir_node_ref_vec_t arg_refs;
|
||||||
vec_init(arg_refs);
|
vec_init(arg_refs);
|
||||||
for (usize i = 0; i < nargs; ++i)
|
for (usize i = 0; i < nargs; ++i)
|
||||||
vec_push(arg_refs, emit_expr(a, vec_at(n->call.args, i)));
|
vec_push(arg_refs, emit_expr(a, vec_at(n->call.args, i)));
|
||||||
|
|
||||||
/* 再创建 call 节点 */
|
|
||||||
spl_type_id_t ret_t = node_ir(a, n);
|
spl_type_id_t ret_t = node_ir(a, n);
|
||||||
spl_ir_node_ref_t call = spl_ir_builder_control_call(a->ir, ret_t, fn);
|
spl_ir_node_ref_t call = spl_ir_builder_control_call(a->ir, ret_t, fn);
|
||||||
if (!call) {
|
if (!call) {
|
||||||
@@ -960,13 +955,10 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
|
spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
|
||||||
spl_type_id_t usize_ir = to_ir_type(a, usize_lang);
|
spl_type_id_t usize_ir = to_ir_type(a, usize_lang);
|
||||||
|
|
||||||
/* base = 元素数据首地址 */
|
|
||||||
spl_ir_node_ref_t base = 0;
|
spl_ir_node_ref_t base = 0;
|
||||||
if (obj_kind == SPL_LANG_TYPE_PTR) {
|
if (obj_kind == SPL_LANG_TYPE_PTR) {
|
||||||
/* ptr 值本身就是首元素地址 */
|
|
||||||
base = emit_expr(a, n->slice.obj);
|
base = emit_expr(a, n->slice.obj);
|
||||||
} else if (obj_kind == SPL_LANG_TYPE_SLICE) {
|
} else if (obj_kind == SPL_LANG_TYPE_SLICE) {
|
||||||
/* 取 slice 的 ptr 字段 */
|
|
||||||
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
|
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
|
||||||
if (!slice_val)
|
if (!slice_val)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -974,7 +966,6 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
base = spl_ir_builder_agg_extract(a->ir, obj_ir, ptr_ir, SPL_SLICE_PTR_FIELD_IDX,
|
base = spl_ir_builder_agg_extract(a->ir, obj_ir, ptr_ir, SPL_SLICE_PTR_FIELD_IDX,
|
||||||
slice_val);
|
slice_val);
|
||||||
} else {
|
} else {
|
||||||
/* ARRAY:&arr 即首元素地址 */
|
|
||||||
base = emit_lvalue(a, n->slice.obj);
|
base = emit_lvalue(a, n->slice.obj);
|
||||||
}
|
}
|
||||||
if (!base)
|
if (!base)
|
||||||
@@ -1032,60 +1023,6 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static spl_ir_node_ref_t emit_if_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|
||||||
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
|
|
||||||
if (!n || n->kind != SPL_AST_EXPR_IF)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
spl_type_id_t if_t = node_ir(a, n);
|
|
||||||
spl_type_node_t *if_tn = if_t ? spl_type_node(a->sema->type, if_t) : NULL;
|
|
||||||
/* 只有 when 有非 unit 值时(作为表达式使用),才分配 result_slot */
|
|
||||||
bool need_result = if_tn && if_tn->kind != SPL_TYPE_UNIT;
|
|
||||||
|
|
||||||
spl_ir_node_ref_t result_slot = 0;
|
|
||||||
if (need_result)
|
|
||||||
result_slot = spl_ir_builder_mem_alloca(a->ir, if_t, const_usize(a, 1));
|
|
||||||
|
|
||||||
spl_ir_node_ref_t cond = emit_expr(a, n->if_expr.cond);
|
|
||||||
if (!cond)
|
|
||||||
Panic("if cond emit failed");
|
|
||||||
spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, cond);
|
|
||||||
spl_ir_builder_block_end(a->ir);
|
|
||||||
|
|
||||||
usize then_blk = spl_ir_builder_block_begin(a->ir);
|
|
||||||
spl_ir_node_ref_t then_v = 0;
|
|
||||||
if (n->if_expr.then_block)
|
|
||||||
then_v = emit_expr(a, n->if_expr.then_block);
|
|
||||||
if (result_slot && then_v)
|
|
||||||
spl_ir_builder_mem_store(a->ir, if_t, result_slot, then_v);
|
|
||||||
spl_ir_node_ref_t then_end = 0;
|
|
||||||
if (!a->ir->terminated)
|
|
||||||
then_end = spl_ir_builder_control_jmp(a->ir);
|
|
||||||
spl_ir_builder_block_end(a->ir);
|
|
||||||
|
|
||||||
usize else_blk = spl_ir_builder_block_begin(a->ir);
|
|
||||||
spl_ir_node_ref_t else_v = 0;
|
|
||||||
if (n->if_expr.else_branch)
|
|
||||||
else_v = emit_expr(a, n->if_expr.else_branch);
|
|
||||||
if (result_slot && else_v)
|
|
||||||
spl_ir_builder_mem_store(a->ir, if_t, result_slot, else_v);
|
|
||||||
spl_ir_node_ref_t else_end = 0;
|
|
||||||
if (!a->ir->terminated)
|
|
||||||
else_end = spl_ir_builder_control_jmp(a->ir);
|
|
||||||
spl_ir_builder_block_end(a->ir);
|
|
||||||
|
|
||||||
usize merge_blk = spl_ir_builder_block_begin(a->ir);
|
|
||||||
spl_ir_builder_control_br_fixup(a->ir, br, then_blk, else_blk);
|
|
||||||
if (then_end)
|
|
||||||
spl_ir_builder_control_jmp_fixup(a->ir, then_end, merge_blk);
|
|
||||||
if (else_end)
|
|
||||||
spl_ir_builder_control_jmp_fixup(a->ir, else_end, merge_blk);
|
|
||||||
|
|
||||||
if (!result_slot)
|
|
||||||
return 0;
|
|
||||||
return spl_ir_builder_mem_load(a->ir, if_t, result_slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
static spl_ir_node_ref_t emit_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
static spl_ir_node_ref_t emit_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||||
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
|
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
|
||||||
if (!n)
|
if (!n)
|
||||||
@@ -1179,8 +1116,6 @@ static spl_ir_node_ref_t emit_loop_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
pre_jmp = spl_ir_builder_control_jmp(a->ir);
|
pre_jmp = spl_ir_builder_control_jmp(a->ir);
|
||||||
spl_ir_builder_block_end(a->ir);
|
spl_ir_builder_block_end(a->ir);
|
||||||
|
|
||||||
/* while 需要独立 head 块(含 cond + br);
|
|
||||||
loop 没有头块,body_blk 同时是入口和回跳目标 */
|
|
||||||
usize head_blk = 0;
|
usize head_blk = 0;
|
||||||
spl_ir_node_ref_t br = 0;
|
spl_ir_node_ref_t br = 0;
|
||||||
|
|
||||||
@@ -1198,7 +1133,6 @@ static spl_ir_node_ref_t emit_loop_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
|
|
||||||
spl_loop_ctx_t ctx = {0};
|
spl_loop_ctx_t ctx = {0};
|
||||||
ctx.cont_blk = cont_blk;
|
ctx.cont_blk = cont_blk;
|
||||||
ctx.brk_blk = 0;
|
|
||||||
ctx.label = NULL;
|
ctx.label = NULL;
|
||||||
ctx.result_slot = result_slot;
|
ctx.result_slot = result_slot;
|
||||||
ctx.result_tid = result_t;
|
ctx.result_tid = result_t;
|
||||||
@@ -1272,7 +1206,6 @@ static void emit_break_stmt(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
|||||||
if (!target)
|
if (!target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* 有值 loop:先把 break 值写入 result_slot 再跳转 */
|
|
||||||
if (n->statement_break.expr && target->result_slot) {
|
if (n->statement_break.expr && target->result_slot) {
|
||||||
spl_ir_node_ref_t bv = emit_expr(a, n->statement_break.expr);
|
spl_ir_node_ref_t bv = emit_expr(a, n->statement_break.expr);
|
||||||
if (bv)
|
if (bv)
|
||||||
@@ -1292,12 +1225,10 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
case SPL_AST_STATEMENT_RET: {
|
case SPL_AST_STATEMENT_RET: {
|
||||||
spl_type_id_t ret_ir = to_ir_type(a, a->cur_ret_lang);
|
spl_type_id_t ret_ir = to_ir_type(a, a->cur_ret_lang);
|
||||||
|
|
||||||
/* 先求值 ret 表达式,结果保存在 v 中 */
|
|
||||||
spl_ir_node_ref_t v = 0;
|
spl_ir_node_ref_t v = 0;
|
||||||
if (n->statement_ret.expr)
|
if (n->statement_ret.expr)
|
||||||
v = emit_expr(a, n->statement_ret.expr);
|
v = emit_expr(a, n->statement_ret.expr);
|
||||||
|
|
||||||
/* 再执行 defer(LIFO),只清空当前函数注册的 defer */
|
|
||||||
while (vec_size(a->defer_stack) > a->cur_defer_base) {
|
while (vec_size(a->defer_stack) > a->cur_defer_base) {
|
||||||
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
|
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
|
||||||
emit_stmt(a, d);
|
emit_stmt(a, d);
|
||||||
@@ -1620,8 +1551,8 @@ static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_type_id_t ft, spl_type_id_t tt,
|
static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n, spl_type_id_t ft,
|
||||||
spl_ir_node_ref_t v) {
|
spl_type_id_t tt, spl_ir_node_ref_t v) {
|
||||||
if (!ft || !tt || ft == tt)
|
if (!ft || !tt || ft == tt)
|
||||||
return v;
|
return v;
|
||||||
spl_type_node_t *fs = spl_type_node(a->sema->type, ft);
|
spl_type_node_t *fs = spl_type_node(a->sema->type, ft);
|
||||||
@@ -1638,10 +1569,6 @@ static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_type_id_t ft, s
|
|||||||
return spl_ir_builder_cast_sext(a->ir, ft, tt, v);
|
return spl_ir_builder_cast_sext(a->ir, ft, tt, v);
|
||||||
return spl_ir_builder_cast_zext(a->ir, ft, tt, v);
|
return spl_ir_builder_cast_zext(a->ir, ft, tt, v);
|
||||||
}
|
}
|
||||||
if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_FLOAT)
|
|
||||||
return spl_ir_builder_case_int2float(a->ir, ft, tt, v);
|
|
||||||
if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_INT)
|
|
||||||
return spl_ir_builder_case_float2int(a->ir, ft, tt, v);
|
|
||||||
if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_FLOAT) {
|
if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_FLOAT) {
|
||||||
if (fs->float_type.bits > ts->float_type.bits)
|
if (fs->float_type.bits > ts->float_type.bits)
|
||||||
return spl_ir_builder_cast_ftrunc(a->ir, ft, tt, v);
|
return spl_ir_builder_cast_ftrunc(a->ir, ft, tt, v);
|
||||||
@@ -1649,11 +1576,20 @@ static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_type_id_t ft, s
|
|||||||
}
|
}
|
||||||
if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT)
|
if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT)
|
||||||
return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v);
|
return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v);
|
||||||
|
|
||||||
|
/* 指针之间:IR 层不区分 pointee,值语义相同,直接透传。
|
||||||
|
覆盖 *never -> *T(null 字面量)和 *T -> *any。 */
|
||||||
|
if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_PTR)
|
||||||
|
return v;
|
||||||
|
|
||||||
if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_INT)
|
if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_INT)
|
||||||
return spl_ir_builder_cast_ptr2int(a->ir, ft, tt, v);
|
return spl_ir_builder_cast_ptr2int(a->ir, ft, tt, v);
|
||||||
if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_PTR)
|
if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_PTR)
|
||||||
return spl_ir_builder_cast_int2ptr(a->ir, ft, tt, v);
|
return spl_ir_builder_cast_int2ptr(a->ir, ft, tt, v);
|
||||||
return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v);
|
|
||||||
|
spl_diag_fatal(a->diag, SPL_DIAG_KIND_IMPLICIT_CAST_FAIL, &n->dbg,
|
||||||
|
"implicit cast: cannot convert type#%zu -> type#%zu", ft, tt);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static usize spl_int_map_hash(usize k) { return MAP_HASH_INT(k); }
|
static usize spl_int_map_hash(usize k) { return MAP_HASH_INT(k); }
|
||||||
@@ -1665,9 +1601,10 @@ void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_
|
|||||||
map_init(ast2ir->def2ir_map, spl_int_map_hash, spl_int_map_cmp);
|
map_init(ast2ir->def2ir_map, spl_int_map_hash, spl_int_map_cmp);
|
||||||
vec_init(ast2ir->loop_stack);
|
vec_init(ast2ir->loop_stack);
|
||||||
vec_init(ast2ir->defer_stack);
|
vec_init(ast2ir->defer_stack);
|
||||||
ast2ir->err_count = 0;
|
|
||||||
ast2ir->cur_ret_lang = 0;
|
ast2ir->cur_ret_lang = 0;
|
||||||
ast2ir->cur_defer_base = 0;
|
ast2ir->cur_defer_base = 0;
|
||||||
|
|
||||||
|
ast2ir->diag = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {
|
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
#ifndef __SPL_AST2IR_H__
|
#ifndef __SPL_AST2IR_H__
|
||||||
#define __SPL_AST2IR_H__
|
#define __SPL_AST2IR_H__
|
||||||
|
|
||||||
|
#include "spl_diag.h"
|
||||||
#include "spl_ir.h"
|
#include "spl_ir.h"
|
||||||
#include "spl_sema.h"
|
#include "spl_sema.h"
|
||||||
|
|
||||||
@@ -8,7 +9,6 @@ typedef MAP(spl_def_id_t, spl_ir_node_ref_t) spl_def2ir_map_t;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
usize cont_blk;
|
usize cont_blk;
|
||||||
usize brk_blk;
|
|
||||||
const char *label;
|
const char *label;
|
||||||
spl_ir_node_ref_vec_t breaks;
|
spl_ir_node_ref_vec_t breaks;
|
||||||
spl_ir_node_ref_t result_slot;
|
spl_ir_node_ref_t result_slot;
|
||||||
@@ -26,7 +26,8 @@ typedef struct {
|
|||||||
spl_defer_stack_t defer_stack;
|
spl_defer_stack_t defer_stack;
|
||||||
spl_lang_type_id_t cur_ret_lang;
|
spl_lang_type_id_t cur_ret_lang;
|
||||||
usize cur_defer_base;
|
usize cur_defer_base;
|
||||||
int err_count;
|
|
||||||
|
spl_diag_t *diag;
|
||||||
} spl_ast2ir_t;
|
} spl_ast2ir_t;
|
||||||
|
|
||||||
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema);
|
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema);
|
||||||
|
|||||||
@@ -0,0 +1,368 @@
|
|||||||
|
#include "spl_diag.h"
|
||||||
|
#include "../stage0/include/color.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
static const char *const g_kind_names[] = {
|
||||||
|
[SPL_DIAG_KIND_NONE] = "none",
|
||||||
|
[SPL_DIAG_KIND_LEX_UNEXPECTED] = "lex_unexpected",
|
||||||
|
[SPL_DIAG_KIND_PARSE_EXPECTED] = "parse_expected",
|
||||||
|
[SPL_DIAG_KIND_PARSE_UNRECOGNIZED] = "parse_unrecognized",
|
||||||
|
[SPL_DIAG_KIND_UNDEFINED_SYMBOL] = "undefined_symbol",
|
||||||
|
[SPL_DIAG_KIND_DUPLICATE_SYMBOL] = "duplicate_symbol",
|
||||||
|
[SPL_DIAG_KIND_TYPE_MISMATCH] = "type_mismatch",
|
||||||
|
[SPL_DIAG_KIND_ARG_COUNT_MISMATCH] = "arg_count_mismatch",
|
||||||
|
[SPL_DIAG_KIND_NOT_A_FUNCTION] = "not_a_function",
|
||||||
|
[SPL_DIAG_KIND_NO_FIELD] = "no_field",
|
||||||
|
[SPL_DIAG_KIND_NO_METHOD] = "no_method",
|
||||||
|
[SPL_DIAG_KIND_INDEX_BASE_INVALID] = "index_base_invalid",
|
||||||
|
[SPL_DIAG_KIND_TUPLE_INDEX_OOB] = "tuple_index_oob",
|
||||||
|
[SPL_DIAG_KIND_FITS_OVERFLOW] = "fits_overflow",
|
||||||
|
[SPL_DIAG_KIND_CIRCULAR_DEP] = "circular_dep",
|
||||||
|
[SPL_DIAG_KIND_BREAK_OUTSIDE_LOOP] = "break_outside_loop",
|
||||||
|
[SPL_DIAG_KIND_CONTINUE_OUTSIDE_LOOP] = "continue_outside_loop",
|
||||||
|
[SPL_DIAG_KIND_UNDEFINED_LABEL] = "undefined_label",
|
||||||
|
[SPL_DIAG_KIND_CAST_INVALID] = "cast_invalid",
|
||||||
|
[SPL_DIAG_KIND_UNKNOWN_ATTR] = "unknown_attr",
|
||||||
|
[SPL_DIAG_KIND_UNKNOWN_INTRIN] = "unknown_intrin",
|
||||||
|
[SPL_DIAG_KIND_INTRIN_ARG_COUNT] = "intrin_arg_count",
|
||||||
|
[SPL_DIAG_KIND_VAR_UNINITIALIZED] = "var_uninitialized",
|
||||||
|
[SPL_DIAG_KIND_CANNOT_INFER] = "cannot_infer",
|
||||||
|
[SPL_DIAG_KIND_MUST_RETURN_VALUE] = "must_return_value",
|
||||||
|
[SPL_DIAG_KIND_UNHANDLED_NODE] = "unhandled_node",
|
||||||
|
[SPL_DIAG_KIND_IMPLICIT_CAST_FAIL] = "implicit_cast_fail",
|
||||||
|
[SPL_DIAG_KIND_NO_LVALUE] = "no_lvalue",
|
||||||
|
[SPL_DIAG_KIND_BAD_FIELD_INDEX] = "bad_field_index",
|
||||||
|
[SPL_DIAG_KIND_BAD_BLOCK] = "bad_block",
|
||||||
|
[SPL_DIAG_KIND_IR_UNKNOWN_KIND] = "ir_unknown_kind",
|
||||||
|
[SPL_DIAG_KIND_FRAME_OVERFLOW] = "frame_overflow",
|
||||||
|
[SPL_DIAG_KIND_INTERNAL] = "internal",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *spl_diag_kind_name(spl_diag_kind_t k) {
|
||||||
|
if ((usize)k < sizeof(g_kind_names) / sizeof(g_kind_names[0]) && g_kind_names[k])
|
||||||
|
return g_kind_names[k];
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *const g_stage_names[] = {
|
||||||
|
[SPL_STAGE_NONE] = "none", [SPL_STAGE_LEX] = "lex", [SPL_STAGE_PARSE] = "parse",
|
||||||
|
[SPL_STAGE_SEMA] = "sema", [SPL_STAGE_AST2IR] = "ast2ir", [SPL_STAGE_IR2VM] = "ir2vm",
|
||||||
|
[SPL_STAGE_DRIVER] = "driver",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *spl_diag_stage_name(spl_diag_stage_t s) {
|
||||||
|
if ((usize)s < sizeof(g_stage_names) / sizeof(g_stage_names[0]) && g_stage_names[s])
|
||||||
|
return g_stage_names[s];
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *spl_diag_level_name(spl_diag_level_t l) {
|
||||||
|
switch (l) {
|
||||||
|
case SPL_DIAG_LEVEL_NOTE:
|
||||||
|
return "note";
|
||||||
|
case SPL_DIAG_LEVEL_WARN:
|
||||||
|
return "warn";
|
||||||
|
case SPL_DIAG_LEVEL_ERROR:
|
||||||
|
return "error";
|
||||||
|
case SPL_DIAG_LEVEL_FATAL:
|
||||||
|
return "fatal";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *level_color(spl_diag_level_t l) {
|
||||||
|
switch (l) {
|
||||||
|
case SPL_DIAG_LEVEL_NOTE:
|
||||||
|
return ANSI_FG_CYAN;
|
||||||
|
case SPL_DIAG_LEVEL_WARN:
|
||||||
|
return ANSI_FG_YELLOW;
|
||||||
|
case SPL_DIAG_LEVEL_ERROR:
|
||||||
|
return ANSI_FG_RED;
|
||||||
|
case SPL_DIAG_LEVEL_FATAL:
|
||||||
|
return ANSI_FG_RED ANSI_UNDERLINED;
|
||||||
|
}
|
||||||
|
return ANSI_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *diag_strdup(const char *s) {
|
||||||
|
if (!s)
|
||||||
|
return NULL;
|
||||||
|
usize n = strlen(s);
|
||||||
|
char *r = malloc(n + 1);
|
||||||
|
if (!r)
|
||||||
|
return NULL;
|
||||||
|
memcpy(r, s, n);
|
||||||
|
r[n] = '\0';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_init(spl_diag_t *d, void *fout) {
|
||||||
|
memset(d, 0, sizeof *d);
|
||||||
|
vec_init(d->ctx);
|
||||||
|
vec_init(d->records);
|
||||||
|
d->collect = true;
|
||||||
|
d->fout = fout;
|
||||||
|
d->color = true;
|
||||||
|
d->stage = SPL_STAGE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void frame_free(spl_diag_frame_t *f) {
|
||||||
|
free(f->fn_name);
|
||||||
|
free(f->label);
|
||||||
|
f->fn_name = NULL;
|
||||||
|
f->label = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void record_free(spl_diag_record_t *r) {
|
||||||
|
free(r->message);
|
||||||
|
r->message = NULL;
|
||||||
|
for (usize i = 0; i < vec_size(r->ctx); ++i)
|
||||||
|
frame_free(&vec_at(r->ctx, i));
|
||||||
|
vec_free(r->ctx);
|
||||||
|
for (usize i = 0; i < vec_size(r->notes); ++i)
|
||||||
|
free(vec_at(r->notes, i).message);
|
||||||
|
vec_free(r->notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_reset(spl_diag_t *d) {
|
||||||
|
for (usize i = 0; i < vec_size(d->ctx); ++i)
|
||||||
|
frame_free(&vec_at(d->ctx, i));
|
||||||
|
d->ctx.size = 0;
|
||||||
|
|
||||||
|
for (usize i = 0; i < vec_size(d->records); ++i)
|
||||||
|
record_free(&vec_at(d->records, i));
|
||||||
|
d->records.size = 0;
|
||||||
|
|
||||||
|
d->num_printed = 0;
|
||||||
|
d->n_errors = 0;
|
||||||
|
d->n_warns = 0;
|
||||||
|
d->n_fatals = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_drop(spl_diag_t *d) {
|
||||||
|
spl_diag_reset(d);
|
||||||
|
vec_free(d->ctx);
|
||||||
|
vec_free(d->records);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_set_stage(spl_diag_t *d, spl_diag_stage_t stage) { d->stage = stage; }
|
||||||
|
|
||||||
|
void spl_diag_set_output(spl_diag_t *d, FILE *out) { d->fout = out; }
|
||||||
|
|
||||||
|
void spl_diag_set_color(spl_diag_t *d, bool enabled) { d->color = enabled; }
|
||||||
|
|
||||||
|
void spl_diag_set_collect(spl_diag_t *d, bool enabled) { d->collect = enabled; }
|
||||||
|
|
||||||
|
void spl_diag_push(spl_diag_t *d, const spl_dbg_node_t *loc, const char *fn_name,
|
||||||
|
const char *label) {
|
||||||
|
spl_diag_frame_t f = {0};
|
||||||
|
if (loc)
|
||||||
|
f.loc = *loc;
|
||||||
|
f.fn_name = fn_name ? diag_strdup(fn_name) : NULL;
|
||||||
|
f.label = label ? diag_strdup(label) : NULL;
|
||||||
|
vec_push(d->ctx, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_pop(spl_diag_t *d) {
|
||||||
|
if (vec_size(d->ctx) == 0)
|
||||||
|
return;
|
||||||
|
frame_free(&vec_at(d->ctx, vec_size(d->ctx) - 1));
|
||||||
|
d->ctx.size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize spl_diag_depth(const spl_diag_t *d) { return vec_size(d->ctx); }
|
||||||
|
|
||||||
|
static spl_diag_frame_vec_t ctx_snapshot(const spl_diag_t *d) {
|
||||||
|
spl_diag_frame_vec_t snap;
|
||||||
|
vec_init(snap);
|
||||||
|
for (usize i = 0; i < vec_size(d->ctx); ++i) {
|
||||||
|
spl_diag_frame_t *src = &vec_at(d->ctx, i);
|
||||||
|
spl_diag_frame_t f = {0};
|
||||||
|
f.loc = src->loc;
|
||||||
|
f.fn_name = src->fn_name ? diag_strdup(src->fn_name) : NULL;
|
||||||
|
f.label = src->label ? diag_strdup(src->label) : NULL;
|
||||||
|
vec_push(snap, f);
|
||||||
|
}
|
||||||
|
return snap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void frame_desc(const spl_diag_frame_t *f, char *buf, usize cap) {
|
||||||
|
if (f->fn_name && f->label)
|
||||||
|
snprintf(buf, cap, "%s %s", f->label, f->fn_name);
|
||||||
|
else if (f->fn_name)
|
||||||
|
snprintf(buf, cap, "%s", f->fn_name);
|
||||||
|
else if (f->label)
|
||||||
|
snprintf(buf, cap, "%s", f->label);
|
||||||
|
else
|
||||||
|
snprintf(buf, cap, "?");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_loc(FILE *out, const spl_dbg_node_t *loc) {
|
||||||
|
if (loc && loc->fname)
|
||||||
|
fprintf(out, "%s:%d:%d", loc->fname, loc->line, loc->col);
|
||||||
|
else
|
||||||
|
fprintf(out, "<no-loc>");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_record(const spl_diag_t *d, const spl_diag_record_t *r) {
|
||||||
|
FILE *out = (FILE *)d->fout;
|
||||||
|
if (!out)
|
||||||
|
return;
|
||||||
|
const char *col = d->color ? level_color(r->level) : "";
|
||||||
|
const char *rst = d->color ? ANSI_NONE : "";
|
||||||
|
|
||||||
|
fprintf(out, "%s%s[%s:%s]%s: ", col, spl_diag_level_name(r->level),
|
||||||
|
spl_diag_stage_name(r->stage), spl_diag_kind_name(r->kind), rst);
|
||||||
|
print_loc(out, &r->loc);
|
||||||
|
fputc('\n', out);
|
||||||
|
|
||||||
|
fprintf(out, " %s\n", r->message ? r->message : "");
|
||||||
|
|
||||||
|
for (usize i = vec_size(r->ctx); i > 0; --i) {
|
||||||
|
char buf[256];
|
||||||
|
frame_desc(&vec_at(r->ctx, i - 1), buf, sizeof buf);
|
||||||
|
fprintf(out, " in %s at ", buf);
|
||||||
|
print_loc(out, &vec_at(r->ctx, i - 1).loc);
|
||||||
|
fputc('\n', out);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (usize i = 0; i < vec_size(r->notes); ++i) {
|
||||||
|
spl_diag_note_t *n = &vec_at(r->notes, i);
|
||||||
|
const char *ncol = d->color ? ANSI_FG_CYAN : "";
|
||||||
|
fprintf(out, "%snote%s: ", ncol, rst);
|
||||||
|
print_loc(out, &n->loc);
|
||||||
|
fputc('\n', out);
|
||||||
|
fprintf(out, " %s\n", n->message ? n->message : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit(spl_diag_t *d, spl_diag_level_t level, spl_diag_kind_t kind,
|
||||||
|
const spl_dbg_node_t *loc, const char *fmt, va_list ap) {
|
||||||
|
va_list ap2;
|
||||||
|
va_copy(ap2, ap);
|
||||||
|
int need = vsnprintf(NULL, 0, fmt, ap);
|
||||||
|
if (need < 0)
|
||||||
|
need = 0;
|
||||||
|
|
||||||
|
char *msg = malloc((usize)need + 1);
|
||||||
|
if (msg)
|
||||||
|
vsnprintf(msg, (usize)need + 1, fmt, ap2);
|
||||||
|
va_end(ap2);
|
||||||
|
|
||||||
|
spl_diag_record_t rec = {0};
|
||||||
|
rec.level = level;
|
||||||
|
rec.stage = d->stage;
|
||||||
|
rec.kind = kind;
|
||||||
|
if (loc)
|
||||||
|
rec.loc = *loc;
|
||||||
|
rec.message = msg;
|
||||||
|
rec.ctx = ctx_snapshot(d);
|
||||||
|
vec_init(rec.notes);
|
||||||
|
|
||||||
|
if (level == SPL_DIAG_LEVEL_ERROR)
|
||||||
|
d->n_errors++;
|
||||||
|
else if (level == SPL_DIAG_LEVEL_FATAL) {
|
||||||
|
d->n_errors++;
|
||||||
|
d->n_fatals++;
|
||||||
|
} else if (level == SPL_DIAG_LEVEL_WARN)
|
||||||
|
d->n_warns++;
|
||||||
|
|
||||||
|
if (d->fout) {
|
||||||
|
print_record(d, &rec);
|
||||||
|
d->num_printed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->collect)
|
||||||
|
vec_push(d->records, rec);
|
||||||
|
else
|
||||||
|
record_free(&rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_note(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||||
|
...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
emit(d, SPL_DIAG_LEVEL_NOTE, kind, loc, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_warn(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||||
|
...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
emit(d, SPL_DIAG_LEVEL_WARN, kind, loc, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_error(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||||
|
...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
emit(d, SPL_DIAG_LEVEL_ERROR, kind, loc, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_fatal(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||||
|
...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
emit(d, SPL_DIAG_LEVEL_FATAL, kind, loc, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_diag_attach_note(spl_diag_t *d, const spl_dbg_node_t *loc, const char *fmt, ...) {
|
||||||
|
if (vec_size(d->records) == 0)
|
||||||
|
return;
|
||||||
|
spl_diag_record_t *last = &vec_at(d->records, vec_size(d->records) - 1);
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int need = vsnprintf(NULL, 0, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (need < 0)
|
||||||
|
need = 0;
|
||||||
|
|
||||||
|
char *msg = malloc((usize)need + 1);
|
||||||
|
if (msg) {
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(msg, (usize)need + 1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_diag_note_t n = {0};
|
||||||
|
if (loc)
|
||||||
|
n.loc = *loc;
|
||||||
|
n.message = msg;
|
||||||
|
vec_push(last->notes, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool spl_diag_has_error(const spl_diag_t *d) { return d->n_errors > 0; }
|
||||||
|
|
||||||
|
bool spl_diag_has_fatal(const spl_diag_t *d) { return d->n_fatals > 0; }
|
||||||
|
|
||||||
|
usize spl_diag_error_count(const spl_diag_t *d) { return d->n_errors; }
|
||||||
|
|
||||||
|
usize spl_diag_warn_count(const spl_diag_t *d) { return d->n_warns; }
|
||||||
|
|
||||||
|
void spl_diag_summary(const spl_diag_t *d) {
|
||||||
|
FILE *out = (FILE *)d->fout;
|
||||||
|
if (!out)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* 把还没实时打印过的记录补打一遍。
|
||||||
|
collect == false 时 records 是空的,num_printed 可能非零,
|
||||||
|
用 records.size 兜底避免越界。 */
|
||||||
|
usize printed_limit = d->num_printed;
|
||||||
|
if (printed_limit > vec_size(d->records))
|
||||||
|
printed_limit = vec_size(d->records);
|
||||||
|
|
||||||
|
for (usize i = printed_limit; i < vec_size(d->records); ++i)
|
||||||
|
print_record(d, &vec_at(d->records, i));
|
||||||
|
|
||||||
|
/* 计数 */
|
||||||
|
const char *ecol = d->color && d->n_errors > 0 ? ANSI_FG_RED : "";
|
||||||
|
const char *rst = d->color ? ANSI_NONE : "";
|
||||||
|
fprintf(out, "%s%zu error%s, %zu warning%s%s\n", ecol, d->n_errors, d->n_errors == 1 ? "" : "s",
|
||||||
|
d->n_warns, d->n_warns == 1 ? "" : "s", rst);
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
#ifndef __SPL_DIAG_H__
|
||||||
|
#define __SPL_DIAG_H__
|
||||||
|
|
||||||
|
#include "../stage0/include/utils.h"
|
||||||
|
#include "spl_dbg.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SPL_DIAG_LEVEL_NOTE = 0,
|
||||||
|
SPL_DIAG_LEVEL_WARN,
|
||||||
|
SPL_DIAG_LEVEL_ERROR,
|
||||||
|
SPL_DIAG_LEVEL_FATAL,
|
||||||
|
} spl_diag_level_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SPL_STAGE_NONE = 0,
|
||||||
|
SPL_STAGE_LEX,
|
||||||
|
SPL_STAGE_PARSE,
|
||||||
|
SPL_STAGE_SEMA,
|
||||||
|
SPL_STAGE_AST2IR,
|
||||||
|
SPL_STAGE_IR2VM,
|
||||||
|
SPL_STAGE_DRIVER,
|
||||||
|
} spl_diag_stage_t;
|
||||||
|
|
||||||
|
/* kind 枚举:边写边补。新增时放对应分组末尾即可。 */
|
||||||
|
typedef enum {
|
||||||
|
SPL_DIAG_KIND_NONE = 0,
|
||||||
|
|
||||||
|
/* 词法 / 语法 */
|
||||||
|
SPL_DIAG_KIND_LEX_UNEXPECTED,
|
||||||
|
SPL_DIAG_KIND_PARSE_EXPECTED,
|
||||||
|
SPL_DIAG_KIND_PARSE_UNRECOGNIZED,
|
||||||
|
|
||||||
|
/* sema */
|
||||||
|
SPL_DIAG_KIND_UNDEFINED_SYMBOL,
|
||||||
|
SPL_DIAG_KIND_DUPLICATE_SYMBOL,
|
||||||
|
SPL_DIAG_KIND_TYPE_MISMATCH,
|
||||||
|
SPL_DIAG_KIND_ARG_COUNT_MISMATCH,
|
||||||
|
SPL_DIAG_KIND_NOT_A_FUNCTION,
|
||||||
|
SPL_DIAG_KIND_NO_FIELD,
|
||||||
|
SPL_DIAG_KIND_NO_METHOD,
|
||||||
|
SPL_DIAG_KIND_INDEX_BASE_INVALID,
|
||||||
|
SPL_DIAG_KIND_TUPLE_INDEX_OOB,
|
||||||
|
SPL_DIAG_KIND_FITS_OVERFLOW,
|
||||||
|
SPL_DIAG_KIND_CIRCULAR_DEP,
|
||||||
|
SPL_DIAG_KIND_BREAK_OUTSIDE_LOOP,
|
||||||
|
SPL_DIAG_KIND_CONTINUE_OUTSIDE_LOOP,
|
||||||
|
SPL_DIAG_KIND_UNDEFINED_LABEL,
|
||||||
|
SPL_DIAG_KIND_CAST_INVALID,
|
||||||
|
SPL_DIAG_KIND_UNKNOWN_ATTR,
|
||||||
|
SPL_DIAG_KIND_UNKNOWN_INTRIN,
|
||||||
|
SPL_DIAG_KIND_INTRIN_ARG_COUNT,
|
||||||
|
SPL_DIAG_KIND_VAR_UNINITIALIZED,
|
||||||
|
SPL_DIAG_KIND_CANNOT_INFER,
|
||||||
|
SPL_DIAG_KIND_MUST_RETURN_VALUE,
|
||||||
|
|
||||||
|
/* ast2ir */
|
||||||
|
SPL_DIAG_KIND_UNHANDLED_NODE,
|
||||||
|
SPL_DIAG_KIND_IMPLICIT_CAST_FAIL,
|
||||||
|
SPL_DIAG_KIND_NO_LVALUE,
|
||||||
|
SPL_DIAG_KIND_BAD_FIELD_INDEX,
|
||||||
|
SPL_DIAG_KIND_BAD_BLOCK,
|
||||||
|
|
||||||
|
/* ir2vm */
|
||||||
|
SPL_DIAG_KIND_IR_UNKNOWN_KIND,
|
||||||
|
SPL_DIAG_KIND_FRAME_OVERFLOW,
|
||||||
|
|
||||||
|
/* 通用 */
|
||||||
|
SPL_DIAG_KIND_INTERNAL,
|
||||||
|
} spl_diag_kind_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
spl_dbg_node_t loc;
|
||||||
|
char *fn_name;
|
||||||
|
char *label;
|
||||||
|
} spl_diag_frame_t;
|
||||||
|
typedef VEC(spl_diag_frame_t) spl_diag_frame_vec_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
spl_dbg_node_t loc;
|
||||||
|
char *message;
|
||||||
|
} spl_diag_note_t;
|
||||||
|
typedef VEC(spl_diag_note_t) spl_diag_note_vec_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
spl_diag_level_t level;
|
||||||
|
spl_diag_stage_t stage;
|
||||||
|
spl_diag_kind_t kind;
|
||||||
|
spl_dbg_node_t loc;
|
||||||
|
char *message;
|
||||||
|
spl_diag_frame_vec_t ctx;
|
||||||
|
spl_diag_note_vec_t notes;
|
||||||
|
} spl_diag_record_t;
|
||||||
|
typedef VEC(spl_diag_record_t) spl_diag_record_vec_t;
|
||||||
|
|
||||||
|
typedef struct spl_diag {
|
||||||
|
spl_diag_frame_vec_t ctx;
|
||||||
|
spl_diag_record_vec_t records;
|
||||||
|
usize num_printed;
|
||||||
|
bool collect;
|
||||||
|
usize n_errors;
|
||||||
|
usize n_warns;
|
||||||
|
usize n_fatals;
|
||||||
|
spl_diag_stage_t stage;
|
||||||
|
void *fout;
|
||||||
|
bool color;
|
||||||
|
} spl_diag_t;
|
||||||
|
|
||||||
|
void spl_diag_init(spl_diag_t *d, void *fout);
|
||||||
|
void spl_diag_drop(spl_diag_t *d);
|
||||||
|
void spl_diag_reset(spl_diag_t *d);
|
||||||
|
void spl_diag_set_stage(spl_diag_t *d, spl_diag_stage_t stage);
|
||||||
|
void spl_diag_set_output(spl_diag_t *d, FILE *out);
|
||||||
|
void spl_diag_set_color(spl_diag_t *d, bool enabled);
|
||||||
|
void spl_diag_set_collect(spl_diag_t *d, bool enabled);
|
||||||
|
|
||||||
|
void spl_diag_push(spl_diag_t *d, const spl_dbg_node_t *loc, const char *fn_name,
|
||||||
|
const char *label);
|
||||||
|
void spl_diag_pop(spl_diag_t *d);
|
||||||
|
usize spl_diag_depth(const spl_diag_t *d);
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
* 发射
|
||||||
|
*
|
||||||
|
* 每个级别都生成独立的 spl_diag_record_t:
|
||||||
|
* - 计入 records(collect=true 时)
|
||||||
|
* - error/fatal 计入 n_errors,warn 计入 n_warns
|
||||||
|
* - 立刻输出到 out(如果非 NULL)
|
||||||
|
*
|
||||||
|
* 四种级别的语义区别:
|
||||||
|
* note —— 一般信息;不阻塞;用在前序诊断之外的独立说明
|
||||||
|
* warn —— 警告;不阻塞;driver 可忽略
|
||||||
|
* error —— 用户代码错误;调用者应 return 0
|
||||||
|
* fatal —— 用户代码错误到数据结构已损坏;调用者必须 return 0
|
||||||
|
* ============================================================ */
|
||||||
|
void spl_diag_note(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||||
|
...);
|
||||||
|
void spl_diag_warn(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||||
|
...);
|
||||||
|
void spl_diag_error(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||||
|
...);
|
||||||
|
void spl_diag_fatal(spl_diag_t *d, spl_diag_kind_t kind, const spl_dbg_node_t *loc, const char *fmt,
|
||||||
|
...);
|
||||||
|
|
||||||
|
/* 挂到最近一条记录(records 末尾)的 notes 列表下。
|
||||||
|
* 不生成独立记录、不计入计数,输出时显示为:
|
||||||
|
* note: <loc>
|
||||||
|
* <msg>
|
||||||
|
* 使用场景:辅助说明前一条诊断,例如
|
||||||
|
* spl_diag_error(d, DUPLICATE_SYMBOL, &n->dbg, "duplicate symbol `foo`");
|
||||||
|
* spl_diag_attach_note(d, &prev->dbg, "previously defined here");
|
||||||
|
* 约束:只在 records 非空时生效;否则静默丢弃,不报错。 */
|
||||||
|
void spl_diag_attach_note(spl_diag_t *d, const spl_dbg_node_t *loc, const char *fmt, ...);
|
||||||
|
|
||||||
|
bool spl_diag_has_error(const spl_diag_t *d);
|
||||||
|
bool spl_diag_has_fatal(const spl_diag_t *d);
|
||||||
|
usize spl_diag_error_count(const spl_diag_t *d);
|
||||||
|
usize spl_diag_warn_count(const spl_diag_t *d);
|
||||||
|
|
||||||
|
void spl_diag_summary(const spl_diag_t *d);
|
||||||
|
|
||||||
|
const char *spl_diag_kind_name(spl_diag_kind_t k);
|
||||||
|
const char *spl_diag_stage_name(spl_diag_stage_t s);
|
||||||
|
const char *spl_diag_level_name(spl_diag_level_t l);
|
||||||
|
|
||||||
|
#endif /* __SPL_DIAG_H__ */
|
||||||
+23
-9
@@ -52,6 +52,23 @@ static bool ir_is_aggregate(spl_ir2vm_t *ctx, spl_type_id_t tid) {
|
|||||||
tn->kind == SPL_TYPE_UNION || tn->kind == SPL_TYPE_ENUM || tn->kind == SPL_TYPE_SHAPE;
|
tn->kind == SPL_TYPE_UNION || tn->kind == SPL_TYPE_ENUM || tn->kind == SPL_TYPE_SHAPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 从 fn_tid 取返回类型;非 fn 类型返回 0。
|
||||||
|
集中处理 fn 类型查表,避免调用点各自 spl_type_node + kind 检查。 */
|
||||||
|
static spl_type_id_t fn_ret_type(spl_ir2vm_t *ctx, spl_type_id_t fn_tid) {
|
||||||
|
spl_type_node_t *ftn = spl_type_node(ctx->type, fn_tid);
|
||||||
|
if (!ftn || ftn->kind != SPL_TYPE_FN)
|
||||||
|
return 0;
|
||||||
|
return ftn->fn_type.ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 从 fn_tid 取参数个数;非 fn 类型返回 0 */
|
||||||
|
static usize fn_nargs(spl_ir2vm_t *ctx, spl_type_id_t fn_tid) {
|
||||||
|
spl_type_node_t *ftn = spl_type_node(ctx->type, fn_tid);
|
||||||
|
if (!ftn || ftn->kind != SPL_TYPE_FN)
|
||||||
|
return 0;
|
||||||
|
return vec_size(ftn->fn_type.params);
|
||||||
|
}
|
||||||
|
|
||||||
static spl_type_id_t ir_agg_field_tid(spl_ir2vm_t *ctx, spl_type_id_t tid, usize idx) {
|
static spl_type_id_t ir_agg_field_tid(spl_ir2vm_t *ctx, spl_type_id_t tid, usize idx) {
|
||||||
spl_type_node_t *tn = spl_type_node(ctx->type, tid);
|
spl_type_node_t *tn = spl_type_node(ctx->type, tid);
|
||||||
if (!tn)
|
if (!tn)
|
||||||
@@ -304,11 +321,9 @@ static void frame_build(frame_layout_t *fl, spl_ir2vm_t *ctx, spl_ir_func_ref_t
|
|||||||
for (usize i = 0; i < n; ++i)
|
for (usize i = 0; i < n; ++i)
|
||||||
vec_push(fl->slots, (slot_t){0});
|
vec_push(fl->slots, (slot_t){0});
|
||||||
|
|
||||||
spl_type_node_t *ftn = spl_type_node(ctx->type, f->fn_tid);
|
|
||||||
usize nargs = (ftn && ftn->kind == SPL_TYPE_FN) ? vec_size(ftn->fn_type.params) : 0;
|
|
||||||
spl_type_id_t ret_t = (ftn && ftn->kind == SPL_TYPE_FN) ? ftn->fn_type.ret : 0;
|
|
||||||
/* 聚合返回时 fp+0 是 caller 传入的 sret 指针,占用一个隐藏参数槽 */
|
/* 聚合返回时 fp+0 是 caller 传入的 sret 指针,占用一个隐藏参数槽 */
|
||||||
usize hidden_sret = ir_is_aggregate(ctx, ret_t) ? 1 : 0;
|
usize nargs = fn_nargs(ctx, f->fn_tid);
|
||||||
|
usize hidden_sret = ir_is_aggregate(ctx, fn_ret_type(ctx, f->fn_tid)) ? 1 : 0;
|
||||||
fl->args_bytes = (nargs + hidden_sret) * sizeof(spl_vm_val_t);
|
fl->args_bytes = (nargs + hidden_sret) * sizeof(spl_vm_val_t);
|
||||||
|
|
||||||
usize off = fl->args_bytes;
|
usize off = fl->args_bytes;
|
||||||
@@ -747,9 +762,7 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
|||||||
idx = (usize)idx_node->type_const.int_lit;
|
idx = (usize)idx_node->type_const.int_lit;
|
||||||
}
|
}
|
||||||
/* 聚合返回时 fp+0 是 sret 指针,实参从 fp+8 起 */
|
/* 聚合返回时 fp+0 是 sret 指针,实参从 fp+8 起 */
|
||||||
spl_type_node_t *ftn = spl_type_node(ctx->type, cg->irf->fn_tid);
|
usize shift = ir_is_aggregate(ctx, fn_ret_type(ctx, cg->irf->fn_tid)) ? 1 : 0;
|
||||||
spl_type_id_t cur_ret = (ftn && ftn->kind == SPL_TYPE_FN) ? ftn->fn_type.ret : 0;
|
|
||||||
usize shift = ir_is_aggregate(ctx, cur_ret) ? 1 : 0;
|
|
||||||
CG_LADDR(cg, (idx + shift) * sizeof(spl_vm_val_t));
|
CG_LADDR(cg, (idx + shift) * sizeof(spl_vm_val_t));
|
||||||
CG_LOAD(cg, k);
|
CG_LOAD(cg, k);
|
||||||
cg_store_slot(cg, ref, k);
|
cg_store_slot(cg, ref, k);
|
||||||
@@ -1074,8 +1087,7 @@ static usize translate_function(spl_ir2vm_t *ctx, spl_ir_func_ref_t fid, fix_vec
|
|||||||
spl_vm_func_t entry = {0};
|
spl_vm_func_t entry = {0};
|
||||||
entry.name = strdup(irf->name ? irf->name : "");
|
entry.name = strdup(irf->name ? irf->name : "");
|
||||||
entry.idx_of_strtab = 0;
|
entry.idx_of_strtab = 0;
|
||||||
spl_type_node_t *ftn = spl_type_node(ctx->type, irf->fn_tid);
|
entry.nargs = fn_nargs(ctx, irf->fn_tid);
|
||||||
entry.nargs = (ftn && ftn->kind == SPL_TYPE_FN) ? vec_size(ftn->fn_type.params) : 0;
|
|
||||||
entry.ninsns = 0;
|
entry.ninsns = 0;
|
||||||
entry.address = func_ip;
|
entry.address = func_ip;
|
||||||
vec_push(ctx->prog.funcs, entry);
|
vec_push(ctx->prog.funcs, entry);
|
||||||
@@ -1121,6 +1133,8 @@ void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type
|
|||||||
ctx->attr = attr;
|
ctx->attr = attr;
|
||||||
map_init(ctx->extern_native, spl_map_hash, spl_map_cmp);
|
map_init(ctx->extern_native, spl_map_hash, spl_map_cmp);
|
||||||
spl_prog_init(&ctx->prog);
|
spl_prog_init(&ctx->prog);
|
||||||
|
|
||||||
|
ctx->diag = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_ir2vm_drop(spl_ir2vm_t *ctx) {
|
void spl_ir2vm_drop(spl_ir2vm_t *ctx) {
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
#ifndef __SPL_IR2VM_H__
|
#ifndef __SPL_IR2VM_H__
|
||||||
#define __SPL_IR2VM_H__
|
#define __SPL_IR2VM_H__
|
||||||
|
|
||||||
|
#include "spl_diag.h"
|
||||||
#include "spl_ir.h"
|
#include "spl_ir.h"
|
||||||
#include "spl_type.h"
|
#include "spl_type.h"
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ typedef struct {
|
|||||||
typedef VEC(spl_ir2vm_fdbg_t) spl_ir2vm_fdbg_vec_t;
|
typedef VEC(spl_ir2vm_fdbg_t) spl_ir2vm_fdbg_vec_t;
|
||||||
|
|
||||||
typedef MAP(spl_ir_func_ref_t, isize) spl_extern_idx_map_t;
|
typedef MAP(spl_ir_func_ref_t, isize) spl_extern_idx_map_t;
|
||||||
// MAP()
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const spl_ir_t *ir;
|
const spl_ir_t *ir;
|
||||||
const spl_type_t *type;
|
const spl_type_t *type;
|
||||||
@@ -21,7 +22,7 @@ typedef struct {
|
|||||||
spl_extern_idx_map_t extern_native;
|
spl_extern_idx_map_t extern_native;
|
||||||
spl_prog_t prog;
|
spl_prog_t prog;
|
||||||
|
|
||||||
// spl_ir2vm_fdbg_vec_t fdbg; /* ir2vm_run 后填充;splc0 -g 读取生成 debug 段 */
|
spl_diag_t *diag;
|
||||||
} spl_ir2vm_t;
|
} spl_ir2vm_t;
|
||||||
|
|
||||||
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type,
|
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type,
|
||||||
|
|||||||
+181
-216
@@ -27,16 +27,11 @@ spl_scope_id_t spl_scope_alloc(spl_scope_t *scope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol) {
|
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol) {
|
||||||
if (!id || id >= vec_size(scope->scopes)) {
|
Assert(id != 0 && id < vec_size(scope->scopes));
|
||||||
LOG_FATAL("sema scope insert error");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
spl_scope_node_t *node = &vec_at(scope->scopes, id);
|
spl_scope_node_t *node = &vec_at(scope->scopes, id);
|
||||||
spl_symbol_t old = {0};
|
spl_symbol_t old = {0};
|
||||||
if (map_get(node->symbols, symbol.name, &old)) {
|
if (map_get(node->symbols, symbol.name, &old))
|
||||||
SPL_ERROR(&(spl_dbg_node_t){0}, "duplicate symbol `%s`", symbol.name);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
map_put(node->symbols, symbol.name, symbol);
|
map_put(node->symbols, symbol.name, symbol);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -46,10 +41,9 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) {
|
|||||||
return false;
|
return false;
|
||||||
for (spl_scope_id_t id = scope->current_scope; id != 0; id = vec_at(scope->scopes, id).parent) {
|
for (spl_scope_id_t id = scope->current_scope; id != 0; id = vec_at(scope->scopes, id).parent) {
|
||||||
spl_scope_node_t *s = &vec_at(scope->scopes, id);
|
spl_scope_node_t *s = &vec_at(scope->scopes, id);
|
||||||
if (map_get(s->symbols, name, out)) {
|
if (map_get(s->symbols, name, out))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,16 +77,16 @@ static void sema_resolve_attrs(spl_sema_t *sema, spl_ast_node_ref_vec_t *raw,
|
|||||||
|
|
||||||
spl_attr_info_t *info = spl_attr_lookup(sema->attr, NULL, a->tag_item.name);
|
spl_attr_info_t *info = spl_attr_lookup(sema->attr, NULL, a->tag_item.name);
|
||||||
if (!info) {
|
if (!info) {
|
||||||
SPL_ERROR(&a->dbg, "unknown attribute `%s`", a->tag_item.name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_ATTR, &a->dbg,
|
||||||
sema->error_count++;
|
"unknown attribute `%s`", a->tag_item.name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
usize nargs = vec_size(a->tag_item.args);
|
usize nargs = vec_size(a->tag_item.args);
|
||||||
if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) {
|
if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) {
|
||||||
SPL_ERROR(&a->dbg, "attribute `%s` expects %d..%d args, got %zu", info->name,
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_ATTR, &a->dbg,
|
||||||
|
"attribute `%s` expects %d..%d args, got %zu", info->name,
|
||||||
info->min_args, info->max_args, nargs);
|
info->min_args, info->max_args, nargs);
|
||||||
sema->error_count++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,8 +114,8 @@ static void sema_resolve_attrs(spl_sema_t *sema, spl_ast_node_ref_vec_t *raw,
|
|||||||
oa.value.i = arg->int_lit.bits;
|
oa.value.i = arg->int_lit.bits;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SPL_ERROR(&a->dbg, "attribute arg #%zu has unsupported form", j);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_ATTR, &a->dbg,
|
||||||
sema->error_count++;
|
"attribute arg #%zu has unsupported form", j);
|
||||||
bad = 1;
|
bad = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -162,21 +156,6 @@ static spl_lang_type_id_t sema_lang_from_ir(spl_sema_t *sema, spl_type_id_t ir)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sema_is_literal(spl_ast_node_t *n) {
|
|
||||||
switch (n->kind) {
|
|
||||||
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_BOOL_LIT:
|
|
||||||
case SPL_AST_EXPR_NULL_LIT:
|
|
||||||
case SPL_AST_EXPR_UNDEFINED_LIT:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sema_type_to_str(spl_sema_t *sema, spl_lang_type_id_t tid, char *buf, usize cap) {
|
static void sema_type_to_str(spl_sema_t *sema, spl_lang_type_id_t tid, char *buf, usize cap) {
|
||||||
if (!buf || cap == 0)
|
if (!buf || cap == 0)
|
||||||
return;
|
return;
|
||||||
@@ -255,17 +234,14 @@ static void sema_type_to_str(spl_sema_t *sema, spl_lang_type_id_t tid, char *buf
|
|||||||
|
|
||||||
static inline void sema_push_scope(spl_sema_t *sema) {
|
static inline void sema_push_scope(spl_sema_t *sema) {
|
||||||
spl_scope_id_t new_scope = spl_scope_alloc(sema->scope);
|
spl_scope_id_t new_scope = spl_scope_alloc(sema->scope);
|
||||||
sema->store_scope = sema->scope->current_scope;
|
|
||||||
sema->scope->current_scope = new_scope;
|
sema->scope->current_scope = new_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sema_pop_scope(spl_sema_t *sema) {
|
static inline void sema_pop_scope(spl_sema_t *sema) {
|
||||||
spl_scope_id_t cur = sema->scope->current_scope;
|
spl_scope_id_t cur = sema->scope->current_scope;
|
||||||
if (cur != 0 && cur < vec_size(sema->scope->scopes)) {
|
if (cur == 0 || cur >= vec_size(sema->scope->scopes))
|
||||||
|
Panic("sema_pop_scope: bad current_scope %zu", cur);
|
||||||
sema->scope->current_scope = vec_at(sema->scope->scopes, cur).parent;
|
sema->scope->current_scope = vec_at(sema->scope->scopes, cur).parent;
|
||||||
} else {
|
|
||||||
sema->scope->current_scope = sema->store_scope;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static spl_lang_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_lang_type_id_t lang_tid) {
|
static spl_lang_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_lang_type_id_t lang_tid) {
|
||||||
@@ -394,8 +370,8 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (def->state == SPL_DECL_RESOLVING) {
|
if (def->state == SPL_DECL_RESOLVING) {
|
||||||
SPL_ERROR(&def->dbg_node, "circular dependency on `%s`", def->name ? def->name : "?");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_CIRCULAR_DEP, &def->dbg_node,
|
||||||
sema->error_count++;
|
"circular dependency on `%s`", def->name ? def->name : "?");
|
||||||
def->state = SPL_DECL_ERROR;
|
def->state = SPL_DECL_ERROR;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -457,13 +433,11 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
|
|
||||||
switch (n->kind) {
|
switch (n->kind) {
|
||||||
case SPL_AST_CONTAINER_MEMBERS: {
|
case SPL_AST_CONTAINER_MEMBERS: {
|
||||||
/* root_scope 只在第一次创建,后续 module 复用 */
|
|
||||||
if (sema->scope->root_scope == 0) {
|
if (sema->scope->root_scope == 0) {
|
||||||
spl_scope_id_t root = spl_scope_alloc(sema->scope);
|
spl_scope_id_t root = spl_scope_alloc(sema->scope);
|
||||||
sema->scope->root_scope = root;
|
sema->scope->root_scope = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 进入 root_scope,再为当前 module 开一个子 scope */
|
|
||||||
sema->scope->current_scope = sema->scope->root_scope;
|
sema->scope->current_scope = sema->scope->root_scope;
|
||||||
spl_scope_id_t mod_scope = spl_scope_alloc(sema->scope);
|
spl_scope_id_t mod_scope = spl_scope_alloc(sema->scope);
|
||||||
sema->scope->current_scope = mod_scope;
|
sema->scope->current_scope = mod_scope;
|
||||||
@@ -476,18 +450,14 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
|
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
|
||||||
sema_collect_names(sema, vec_at(n->container_members.declarations, i));
|
sema_collect_names(sema, vec_at(n->container_members.declarations, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 故意不恢复 current_scope
|
|
||||||
保持 mod_scope 交给随后的 sema_parse 使用。
|
|
||||||
恢复由 spl_sema_run_module 统一负责 */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPL_AST_TYPE_DECL: {
|
case SPL_AST_TYPE_DECL: {
|
||||||
spl_symbol_t sym = {.name = n->type_decl.name, .kind = SPL_SYMBOL_KIND_TYPE};
|
spl_symbol_t sym = {.name = n->type_decl.name, .kind = SPL_SYMBOL_KIND_TYPE};
|
||||||
spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr);
|
spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr);
|
||||||
if (!te) {
|
if (!te) {
|
||||||
SPL_ERROR(&n->dbg, "type declaration `%s` missing type expression", n->type_decl.name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"type declaration `%s` missing type expression", n->type_decl.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (te->kind == SPL_AST_TYPE_AGGREGATE)
|
if (te->kind == SPL_AST_TYPE_AGGREGATE)
|
||||||
@@ -495,14 +465,20 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
else
|
else
|
||||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, ref);
|
sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, ref);
|
||||||
n->resolved_def_id = sym.node;
|
n->resolved_def_id = sym.node;
|
||||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||||
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
|
||||||
|
"duplicate symbol `%s`", sym.name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPL_AST_FN_DECL: {
|
case SPL_AST_FN_DECL: {
|
||||||
spl_symbol_t sym = {.name = n->fn_decl.name, .kind = SPL_SYMBOL_KIND_FN};
|
spl_symbol_t sym = {.name = n->fn_decl.name, .kind = SPL_SYMBOL_KIND_FN};
|
||||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_FN, sym.name, n->dbg, ref);
|
sym.node = spl_def_alloc(sema->type, SPL_DEF_FN, sym.name, n->dbg, ref);
|
||||||
n->resolved_def_id = sym.node;
|
n->resolved_def_id = sym.node;
|
||||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||||
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
|
||||||
|
"duplicate symbol `%s`", sym.name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPL_AST_VAR_DECL:
|
case SPL_AST_VAR_DECL:
|
||||||
@@ -513,17 +489,19 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
|
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
|
||||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref);
|
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref);
|
||||||
n->resolved_def_id = sym.node;
|
n->resolved_def_id = sym.node;
|
||||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||||
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
|
||||||
|
"duplicate symbol `%s`", name);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
SPL_ERROR(&n->dbg, "unsupported variable pattern (only simple identifier)");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"unsupported variable pattern (only simple identifier)");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPL_AST_TOP_LEVEL_BLOCK:
|
case SPL_AST_TOP_LEVEL_BLOCK:
|
||||||
if (n->top_level_block.block) {
|
if (n->top_level_block.block)
|
||||||
sema_collect_names(sema, n->top_level_block.block);
|
sema_collect_names(sema, n->top_level_block.block);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -572,9 +550,9 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
|||||||
const spl_intrin_info_t *info = spl_intrin_info(in);
|
const spl_intrin_info_t *info = spl_intrin_info(in);
|
||||||
usize nargs = vec_size(*args);
|
usize nargs = vec_size(*args);
|
||||||
if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) {
|
if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) {
|
||||||
SPL_ERROR(&n->dbg, "`%s` expects %d..%d args, got %zu", info->name, info->min_args,
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_INTRIN_ARG_COUNT, &n->dbg,
|
||||||
|
"`%s` expects %d..%d args, got %zu", info->name, info->min_args,
|
||||||
info->max_args, nargs);
|
info->max_args, nargs);
|
||||||
sema->error_count++;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,7 +577,6 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
|||||||
case SPL_INTRIN_FLOAT_FROM_INT:
|
case SPL_INTRIN_FLOAT_FROM_INT:
|
||||||
case SPL_INTRIN_PTR_FROM_INT:
|
case SPL_INTRIN_PTR_FROM_INT:
|
||||||
case SPL_INTRIN_PTR_CAST: {
|
case SPL_INTRIN_PTR_CAST: {
|
||||||
/* 双参数形式:源表达式 + 目标类型 */
|
|
||||||
spl_lang_type_id_t src_lang = sema_infer(sema, vec_at(*args, 0));
|
spl_lang_type_id_t src_lang = sema_infer(sema, vec_at(*args, 0));
|
||||||
if (!src_lang)
|
if (!src_lang)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -610,17 +587,15 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
|||||||
spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang);
|
spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang);
|
||||||
spl_intrin_t expected = spl_intrin_lookup_cast(sema->type, ft, tt);
|
spl_intrin_t expected = spl_intrin_lookup_cast(sema->type, ft, tt);
|
||||||
if (expected == SPL_INTRIN_NONE) {
|
if (expected == SPL_INTRIN_NONE) {
|
||||||
SPL_ERROR(&n->dbg, "`%s`: incompatible types", info->name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
|
||||||
sema->error_count++;
|
"`%s`: incompatible types", info->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* 允许显式 builtin 覆盖 as 的默认选择(例如用 @int_cast 代替 @truncate) */
|
|
||||||
n->resolved_lang_tid = dst_lang;
|
n->resolved_lang_tid = dst_lang;
|
||||||
return dst_lang;
|
return dst_lang;
|
||||||
}
|
}
|
||||||
case SPL_INTRIN_INT_FROM_BOOL:
|
case SPL_INTRIN_INT_FROM_BOOL:
|
||||||
case SPL_INTRIN_INT_FROM_PTR: {
|
case SPL_INTRIN_INT_FROM_PTR: {
|
||||||
/* 单参数:目标类型默认 usize;双参数时以第二参数为准 */
|
|
||||||
sema_infer(sema, vec_at(*args, 0));
|
sema_infer(sema, vec_at(*args, 0));
|
||||||
if (nargs >= 2) {
|
if (nargs >= 2) {
|
||||||
spl_lang_type_id_t dst = sema_infer(sema, vec_at(*args, 1));
|
spl_lang_type_id_t dst = sema_infer(sema, vec_at(*args, 1));
|
||||||
@@ -655,6 +630,34 @@ static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static spl_lang_type_id_t sema_block_body(spl_sema_t *sema, spl_ast_node_t *n,
|
||||||
|
spl_lang_type_id_t expected) {
|
||||||
|
spl_ast_node_ref_t tail = n->block.tail_expr;
|
||||||
|
|
||||||
|
sema_push_scope(sema);
|
||||||
|
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
|
||||||
|
sema_infer(sema, vec_at(n->block.stmts, i));
|
||||||
|
|
||||||
|
spl_lang_type_id_t r = 0;
|
||||||
|
if (tail) {
|
||||||
|
if (expected) {
|
||||||
|
r = sema_coerce(sema, tail, expected);
|
||||||
|
if (!r) {
|
||||||
|
sema_pop_scope(sema);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r = sema_infer(sema, tail);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r = spl_lang_make_unit(sema->type);
|
||||||
|
}
|
||||||
|
sema_pop_scope(sema);
|
||||||
|
|
||||||
|
n->resolved_lang_tid = r;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||||
spl_lang_type_id_t expected) {
|
spl_lang_type_id_t expected) {
|
||||||
if (!ref || !expected)
|
if (!ref || !expected)
|
||||||
@@ -671,13 +674,11 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
if (already != 0) {
|
if (already != 0) {
|
||||||
spl_lang_type_node_t *an = spl_lang_type_node(sema->type, already);
|
spl_lang_type_node_t *an = spl_lang_type_node(sema->type, already);
|
||||||
spl_type_node_t *air = an ? spl_type_node(sema->type, an->ir_type_id) : NULL;
|
spl_type_node_t *air = an ? spl_type_node(sema->type, an->ir_type_id) : NULL;
|
||||||
/* comptime 与 infer 都属于"可重定型":清空 resolved 后按 expected 重新推导 */
|
|
||||||
bool a_rebindable =
|
bool a_rebindable =
|
||||||
(an && an->kind == SPL_LANG_TYPE_INFER) ||
|
(an && an->kind == SPL_LANG_TYPE_INFER) ||
|
||||||
(an && an->kind == SPL_LANG_TYPE_INT && air && air->int_type.bits == 0) ||
|
(an && an->kind == SPL_LANG_TYPE_INT && air && air->int_type.bits == 0) ||
|
||||||
(an && an->kind == SPL_LANG_TYPE_FLOAT && air && air->float_type.bits == 0);
|
(an && an->kind == SPL_LANG_TYPE_FLOAT && air && air->float_type.bits == 0);
|
||||||
if (!a_rebindable) {
|
if (!a_rebindable) {
|
||||||
/* 具体类型:只接受子类型方向 */
|
|
||||||
if (spl_lang_type_is_subtype(sema->type, already, expected)) {
|
if (spl_lang_type_is_subtype(sema->type, already, expected)) {
|
||||||
n->expected_lang_tid = expected;
|
n->expected_lang_tid = expected;
|
||||||
return expected;
|
return expected;
|
||||||
@@ -685,12 +686,11 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
char ebuf[128], gbuf[128];
|
char ebuf[128], gbuf[128];
|
||||||
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
|
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
|
||||||
sema_type_to_str(sema, already, gbuf, sizeof(gbuf));
|
sema_type_to_str(sema, already, gbuf, sizeof(gbuf));
|
||||||
SPL_ERROR(&n->dbg, "type mismatch: node kind=%d already typed as %s, expected %s",
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
|
"type mismatch: node kind=%d already typed as %s, expected %s",
|
||||||
(int)n->kind, gbuf, ebuf);
|
(int)n->kind, gbuf, ebuf);
|
||||||
sema->error_count++;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* 清空 resolved,走未定型路径,让递归按 expected 下推子节点 */
|
|
||||||
n->resolved_lang_tid = 0;
|
n->resolved_lang_tid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,9 +698,6 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
switch (n->kind) {
|
switch (n->kind) {
|
||||||
|
|
||||||
case SPL_AST_EXPR_UNARY: {
|
case SPL_AST_EXPR_UNARY: {
|
||||||
/* ADDRESS / DEREF 的结果类型由操作数决定,不能用 expected 反向定型。
|
|
||||||
* 但不能直接 return ——— 那会绕过 expected 兼容性检查。
|
|
||||||
* 走 break 落到兜底:infer 后做 is_subtype / comptime 判定。 */
|
|
||||||
if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF)
|
if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF)
|
||||||
break;
|
break;
|
||||||
if (!sema_coerce(sema, n->unary.operand, expected))
|
if (!sema_coerce(sema, n->unary.operand, expected))
|
||||||
@@ -743,8 +740,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
char lbuf[128], rbuf[128];
|
char lbuf[128], rbuf[128];
|
||||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
sema_coerce(sema, n->binary.left, common);
|
sema_coerce(sema, n->binary.left, common);
|
||||||
@@ -754,8 +751,6 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ptr +/- int:expected 是 ptr 且左侧推断为 ptr。
|
|
||||||
* 右侧保留原整型;仅 comptime_int(bits==0)收紧到 isize。 */
|
|
||||||
if (op == SPL_OP_ADD || op == SPL_OP_SUB) {
|
if (op == SPL_OP_ADD || op == SPL_OP_SUB) {
|
||||||
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
||||||
if (en && en->kind == SPL_LANG_TYPE_PTR) {
|
if (en && en->kind == SPL_LANG_TYPE_PTR) {
|
||||||
@@ -765,8 +760,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
|
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
|
||||||
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
|
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
|
||||||
if (!rn || rn->kind != SPL_LANG_TYPE_INT) {
|
if (!rn || rn->kind != SPL_LANG_TYPE_INT) {
|
||||||
SPL_ERROR(&n->dbg, "pointer offset must be integer");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"pointer offset must be integer");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
|
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
|
||||||
@@ -809,8 +804,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
usize nelems = vec_size(n->tuple.elems);
|
usize nelems = vec_size(n->tuple.elems);
|
||||||
usize ntypes = vec_size(en->extra.elems);
|
usize ntypes = vec_size(en->extra.elems);
|
||||||
if (nelems != ntypes) {
|
if (nelems != ntypes) {
|
||||||
SPL_ERROR(&n->dbg, "tuple arity mismatch (expected %zu, got %zu)", ntypes, nelems);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"tuple arity mismatch (expected %zu, got %zu)", ntypes, nelems);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (usize i = 0; i < nelems; ++i) {
|
for (usize i = 0; i < nelems; ++i) {
|
||||||
@@ -830,19 +825,18 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
en->kind != SPL_LANG_TYPE_ENUM))
|
en->kind != SPL_LANG_TYPE_ENUM))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 有名字时,名字必须与 expected 指向同一类型 */
|
|
||||||
if (n->aggregate_literal.name) {
|
if (n->aggregate_literal.name) {
|
||||||
spl_symbol_t sym;
|
spl_symbol_t sym;
|
||||||
if (!spl_scope_find(sema->scope, n->aggregate_literal.name, &sym)) {
|
if (!spl_scope_find(sema->scope, n->aggregate_literal.name, &sym)) {
|
||||||
SPL_ERROR(&n->dbg, "unknown type `%s`", n->aggregate_literal.name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||||
sema->error_count++;
|
"unknown type `%s`", n->aggregate_literal.name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
||||||
if (!def || def->lang_id != expected) {
|
if (!def || def->lang_id != expected) {
|
||||||
SPL_ERROR(&n->dbg, "aggregate `%s` does not match expected type",
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
|
"aggregate `%s` does not match expected type",
|
||||||
n->aggregate_literal.name);
|
n->aggregate_literal.name);
|
||||||
sema->error_count++;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -850,27 +844,27 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, expected);
|
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, expected);
|
||||||
spl_type_node_t *irn = spl_type_node(sema->type, agg_ir);
|
spl_type_node_t *irn = spl_type_node(sema->type, agg_ir);
|
||||||
if (!irn) {
|
if (!irn) {
|
||||||
SPL_ERROR(&n->dbg, "aggregate type unresolved");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"aggregate type unresolved");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (en->kind == SPL_LANG_TYPE_ENUM) {
|
if (en->kind == SPL_LANG_TYPE_ENUM) {
|
||||||
if (vec_size(n->aggregate_literal.fields) != 1) {
|
if (vec_size(n->aggregate_literal.fields) != 1) {
|
||||||
SPL_ERROR(&n->dbg, "enum literal must have exactly one variant");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"enum literal must have exactly one variant");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, 0));
|
spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, 0));
|
||||||
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) {
|
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) {
|
||||||
SPL_ERROR(&n->dbg, "invalid enum literal");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"invalid enum literal");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
usize idx = 0;
|
usize idx = 0;
|
||||||
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) {
|
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) {
|
||||||
SPL_ERROR(&item->dbg, "no variant `%s`", item->struct_init_item.name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no variant `%s`",
|
||||||
sema->error_count++;
|
item->struct_init_item.name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||||
@@ -889,8 +883,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
continue;
|
continue;
|
||||||
usize idx = 0;
|
usize idx = 0;
|
||||||
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) {
|
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) {
|
||||||
SPL_ERROR(&item->dbg, "no field `%s`", item->struct_init_item.name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
|
||||||
sema->error_count++;
|
item->struct_init_item.name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||||
@@ -924,25 +918,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
return expected;
|
return expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SPL_AST_EXPR_BLOCK: {
|
case SPL_AST_EXPR_BLOCK:
|
||||||
sema_push_scope(sema);
|
return sema_block_body(sema, n, expected);
|
||||||
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
|
|
||||||
sema_infer(sema, vec_at(n->block.stmts, i));
|
|
||||||
spl_lang_type_id_t r = 0;
|
|
||||||
if (n->block.tail_expr) {
|
|
||||||
spl_lang_type_id_t t = sema_coerce(sema, n->block.tail_expr, expected);
|
|
||||||
if (!t) {
|
|
||||||
sema_pop_scope(sema);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
r = t;
|
|
||||||
} else {
|
|
||||||
r = spl_lang_make_unit(sema->type);
|
|
||||||
}
|
|
||||||
sema_pop_scope(sema);
|
|
||||||
n->resolved_lang_tid = r;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -968,8 +945,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
uint32_t bits = to_ir ? (uint32_t)to_ir->int_type.bits : 0;
|
uint32_t bits = to_ir ? (uint32_t)to_ir->int_type.bits : 0;
|
||||||
if (n->kind == SPL_AST_EXPR_INT_LIT && bits != 0 &&
|
if (n->kind == SPL_AST_EXPR_INT_LIT && bits != 0 &&
|
||||||
!spl_lang_mpa_int_fits(sema->type, expected, n->int_lit)) {
|
!spl_lang_mpa_int_fits(sema->type, expected, n->int_lit)) {
|
||||||
SPL_ERROR(&n->dbg, "comptime value does not fit target type");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_FITS_OVERFLOW, &n->dbg,
|
||||||
sema->error_count++;
|
"comptime value does not fit target type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_lang_tid = expected;
|
n->resolved_lang_tid = expected;
|
||||||
@@ -988,8 +965,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
char ebuf[128], gbuf[128];
|
char ebuf[128], gbuf[128];
|
||||||
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
|
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
|
||||||
sema_type_to_str(sema, from, gbuf, sizeof(gbuf));
|
sema_type_to_str(sema, from, gbuf, sizeof(gbuf));
|
||||||
SPL_ERROR(&n->dbg, "type mismatch: expect %s, got %s (node kind=%d)", ebuf, gbuf, (int)n->kind);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"type mismatch: expect %s, got %s (node kind=%d)", ebuf, gbuf, (int)n->kind);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,18 +1022,18 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- IDENT:同时写 def_id 和 lang_tid 副本 ---------- */
|
/* ---------- IDENT ---------- */
|
||||||
case SPL_AST_EXPR_IDENT: {
|
case SPL_AST_EXPR_IDENT: {
|
||||||
const char *name = n->ident.name;
|
const char *name = n->ident.name;
|
||||||
spl_symbol_t sym;
|
spl_symbol_t sym;
|
||||||
if (!spl_scope_find(sema->scope, name, &sym)) {
|
if (!spl_scope_find(sema->scope, name, &sym)) {
|
||||||
SPL_ERROR(&n->dbg, "undefined identifier `%s`", name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||||
sema->error_count++;
|
"undefined identifier `%s`", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (sym.node == 0) {
|
if (sym.node == 0) {
|
||||||
SPL_ERROR(&n->dbg, "identifier `%s` has no definition", name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||||
sema->error_count++;
|
"identifier `%s` has no definition", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_def_id = sym.node;
|
n->resolved_def_id = sym.node;
|
||||||
@@ -1077,16 +1054,16 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
switch (n->unary.op) {
|
switch (n->unary.op) {
|
||||||
case SPL_UNARY_OP_MINUS:
|
case SPL_UNARY_OP_MINUS:
|
||||||
if (tn->kind != SPL_LANG_TYPE_INT && tn->kind != SPL_LANG_TYPE_FLOAT) {
|
if (tn->kind != SPL_LANG_TYPE_INT && tn->kind != SPL_LANG_TYPE_FLOAT) {
|
||||||
SPL_ERROR(&n->dbg, "unary minus requires numeric operand");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"unary minus requires numeric operand");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_lang_tid = op;
|
n->resolved_lang_tid = op;
|
||||||
return op;
|
return op;
|
||||||
case SPL_UNARY_OP_BIT_NOT:
|
case SPL_UNARY_OP_BIT_NOT:
|
||||||
if (tn->kind != SPL_LANG_TYPE_INT) {
|
if (tn->kind != SPL_LANG_TYPE_INT) {
|
||||||
SPL_ERROR(&n->dbg, "bitwise not requires integer operand");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"bitwise not requires integer operand");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_lang_tid = op;
|
n->resolved_lang_tid = op;
|
||||||
@@ -1104,8 +1081,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
case SPL_UNARY_OP_DEREF: {
|
case SPL_UNARY_OP_DEREF: {
|
||||||
if (tn->kind != SPL_LANG_TYPE_PTR) {
|
if (tn->kind != SPL_LANG_TYPE_PTR) {
|
||||||
SPL_ERROR(&n->dbg, "deref requires pointer operand");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"deref requires pointer operand");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t elem = tn->extra.elem;
|
spl_lang_type_id_t elem = tn->extra.elem;
|
||||||
@@ -1121,7 +1098,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
case SPL_AST_EXPR_BINARY: {
|
case SPL_AST_EXPR_BINARY: {
|
||||||
spl_binary_op_t op = n->binary.op;
|
spl_binary_op_t op = n->binary.op;
|
||||||
|
|
||||||
/* 赋值 / 复合赋值 */
|
|
||||||
if (op == SPL_OP_ASSIGN || (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT)) {
|
if (op == SPL_OP_ASSIGN || (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT)) {
|
||||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||||
if (!lt)
|
if (!lt)
|
||||||
@@ -1131,7 +1107,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
return lt;
|
return lt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 逻辑 */
|
|
||||||
if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
|
if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
|
||||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||||
sema_coerce(sema, n->binary.left, bt);
|
sema_coerce(sema, n->binary.left, bt);
|
||||||
@@ -1152,8 +1127,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
char lbuf[128], rbuf[128];
|
char lbuf[128], rbuf[128];
|
||||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1165,7 +1140,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Range */
|
|
||||||
if (op == SPL_OP_RANGE) {
|
if (op == SPL_OP_RANGE) {
|
||||||
sema_infer(sema, n->binary.left);
|
sema_infer(sema, n->binary.left);
|
||||||
sema_infer(sema, n->binary.right);
|
sema_infer(sema, n->binary.right);
|
||||||
@@ -1175,15 +1149,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 移位:结果 = 左类型 */
|
|
||||||
if (op == SPL_OP_LSHIFT || op == SPL_OP_RSHIFT) {
|
if (op == SPL_OP_LSHIFT || op == SPL_OP_RSHIFT) {
|
||||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||||
if (!lt)
|
if (!lt)
|
||||||
return 0;
|
return 0;
|
||||||
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
|
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
|
||||||
if (!ln || ln->kind != SPL_LANG_TYPE_INT) {
|
if (!ln || ln->kind != SPL_LANG_TYPE_INT) {
|
||||||
SPL_ERROR(&n->dbg, "shift requires integer operands");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"shift requires integer operands");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
sema_infer(sema, n->binary.right);
|
sema_infer(sema, n->binary.right);
|
||||||
@@ -1199,9 +1172,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
|
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
|
||||||
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
|
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
|
||||||
|
|
||||||
/* ptr +/- int 特判:右侧保留自己的整型;
|
|
||||||
* 仅当右操作数是 comptime_int(bits==0)时收紧到 isize,
|
|
||||||
* 避免 comptime 类型泄漏到 IR。 */
|
|
||||||
if (ln && ln->kind == SPL_LANG_TYPE_PTR && rn && rn->kind == SPL_LANG_TYPE_INT &&
|
if (ln && ln->kind == SPL_LANG_TYPE_PTR && rn && rn->kind == SPL_LANG_TYPE_INT &&
|
||||||
(op == SPL_OP_ADD || op == SPL_OP_SUB)) {
|
(op == SPL_OP_ADD || op == SPL_OP_SUB)) {
|
||||||
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
|
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
|
||||||
@@ -1218,8 +1188,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
char lbuf[128], rbuf[128];
|
char lbuf[128], rbuf[128];
|
||||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||||
SPL_ERROR(&n->dbg, "operand types cannot be joined: lhs=%s rhs=%s", lbuf, rbuf);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"operand types cannot be joined: lhs=%s rhs=%s", lbuf, rbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1245,8 +1215,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
spl_lang_type_id_t callee_tid = sema_infer(sema, n->call.callee);
|
spl_lang_type_id_t callee_tid = sema_infer(sema, n->call.callee);
|
||||||
spl_lang_type_node_t *fn = spl_lang_type_node(sema->type, callee_tid);
|
spl_lang_type_node_t *fn = spl_lang_type_node(sema->type, callee_tid);
|
||||||
if (!fn || fn->kind != SPL_LANG_TYPE_FN) {
|
if (!fn || fn->kind != SPL_LANG_TYPE_FN) {
|
||||||
SPL_ERROR(&n->dbg, "callee is not a function");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_NOT_A_FUNCTION, &n->dbg,
|
||||||
sema->error_count++;
|
"callee is not a function");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1264,15 +1234,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
usize nargs = vec_size(n->call.args);
|
usize nargs = vec_size(n->call.args);
|
||||||
if (has_varargs) {
|
if (has_varargs) {
|
||||||
if (nargs < fixed) {
|
if (nargs < fixed) {
|
||||||
SPL_ERROR(&n->dbg, "too few arguments (expected at least %zu)", fixed);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_ARG_COUNT_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"too few arguments (expected at least %zu)", fixed);
|
||||||
}
|
}
|
||||||
} else if (nargs != fixed) {
|
} else if (nargs != fixed) {
|
||||||
SPL_ERROR(&n->dbg, "argument count mismatch (expected %zu, got %zu)", fixed, nargs);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_ARG_COUNT_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"argument count mismatch (expected %zu, got %zu)", fixed, nargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 固定参数:check 到形参类型 */
|
|
||||||
for (usize i = 0; i < nargs && i < fixed; ++i) {
|
for (usize i = 0; i < nargs && i < fixed; ++i) {
|
||||||
spl_lang_type_id_t pt =
|
spl_lang_type_id_t pt =
|
||||||
vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i);
|
vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i);
|
||||||
@@ -1311,8 +1280,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
agg_lang = obj->extra.elem;
|
agg_lang = obj->extra.elem;
|
||||||
spl_lang_type_node_t *agg = spl_lang_type_node(sema->type, agg_lang);
|
spl_lang_type_node_t *agg = spl_lang_type_node(sema->type, agg_lang);
|
||||||
if (!agg) {
|
if (!agg) {
|
||||||
SPL_ERROR(&n->dbg, "field access on invalid type");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg,
|
||||||
sema->error_count++;
|
"field access on invalid type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1322,8 +1291,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
if (m) {
|
if (m) {
|
||||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id);
|
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id);
|
||||||
if (!ft) {
|
if (!ft) {
|
||||||
SPL_ERROR(&n->dbg, "cannot resolve field type");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg,
|
||||||
sema->error_count++;
|
"cannot resolve field type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_lang_tid = ft;
|
n->resolved_lang_tid = ft;
|
||||||
@@ -1341,8 +1310,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPL_ERROR(&n->dbg, "no field `%s`", n->field.field);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg, "no field `%s`",
|
||||||
sema->error_count++;
|
n->field.field);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1364,22 +1333,22 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
case SPL_LANG_TYPE_TUPLE: {
|
case SPL_LANG_TYPE_TUPLE: {
|
||||||
spl_ast_node_t *idx_node = spl_ast_node(sema->ast, n->index.index);
|
spl_ast_node_t *idx_node = spl_ast_node(sema->ast, n->index.index);
|
||||||
if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) {
|
if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) {
|
||||||
SPL_ERROR(&n->dbg, "tuple index must be an integer literal");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TUPLE_INDEX_OOB, &n->dbg,
|
||||||
sema->error_count++;
|
"tuple index must be an integer literal");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
isize i = (isize)idx_node->int_lit.bits;
|
isize i = (isize)idx_node->int_lit.bits;
|
||||||
if (i < 0 || (usize)i >= vec_size(obj->extra.elems)) {
|
if (i < 0 || (usize)i >= vec_size(obj->extra.elems)) {
|
||||||
SPL_ERROR(&n->dbg, "tuple index out of range");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TUPLE_INDEX_OOB, &n->dbg,
|
||||||
sema->error_count++;
|
"tuple index out of range");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
elem = vec_at(obj->extra.elems, (usize)i);
|
elem = vec_at(obj->extra.elems, (usize)i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
SPL_ERROR(&n->dbg, "index base must be array/slice/ptr/range/tuple");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_INDEX_BASE_INVALID, &n->dbg,
|
||||||
sema->error_count++;
|
"index base must be array/slice/ptr/range/tuple");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_lang_tid = elem;
|
n->resolved_lang_tid = elem;
|
||||||
@@ -1401,8 +1370,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
obj->kind == SPL_LANG_TYPE_SLICE) {
|
obj->kind == SPL_LANG_TYPE_SLICE) {
|
||||||
elem = obj->extra.elem;
|
elem = obj->extra.elem;
|
||||||
} else {
|
} else {
|
||||||
SPL_ERROR(&n->dbg, "slice base must be array/ptr/slice");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_INDEX_BASE_INVALID, &n->dbg,
|
||||||
sema->error_count++;
|
"slice base must be array/ptr/slice");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t s = spl_lang_make_slice(sema->type, elem);
|
spl_lang_type_id_t s = spl_lang_make_slice(sema->type, elem);
|
||||||
@@ -1427,7 +1396,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
sn && sn->kind == SPL_LANG_TYPE_FLOAT && sir && sir->float_type.bits == 0;
|
sn && sn->kind == SPL_LANG_TYPE_FLOAT && sir && sir->float_type.bits == 0;
|
||||||
|
|
||||||
if (src_is_literal_int || src_is_literal_float) {
|
if (src_is_literal_int || src_is_literal_float) {
|
||||||
/* 字面量目标物化:允许任意宽度,as 会按其语义处理 */
|
|
||||||
spl_ast_node_t *src_node = spl_ast_node(sema->ast, n->cast.expr);
|
spl_ast_node_t *src_node = spl_ast_node(sema->ast, n->cast.expr);
|
||||||
if (src_node && (src_node->kind == SPL_AST_EXPR_INT_LIT ||
|
if (src_node && (src_node->kind == SPL_AST_EXPR_INT_LIT ||
|
||||||
src_node->kind == SPL_AST_EXPR_FLOAT_LIT)) {
|
src_node->kind == SPL_AST_EXPR_FLOAT_LIT)) {
|
||||||
@@ -1442,14 +1410,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
spl_type_id_t ft = spl_lang_type_get_ir_type(sema->type, src_lang);
|
spl_type_id_t ft = spl_lang_type_get_ir_type(sema->type, src_lang);
|
||||||
spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang);
|
spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang);
|
||||||
if (!ft || !tt) {
|
if (!ft || !tt) {
|
||||||
SPL_ERROR(&n->dbg, "as: unresolved source or target type");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
|
||||||
sema->error_count++;
|
"as: unresolved source or target type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_intrin_t in = spl_intrin_lookup_cast(sema->type, ft, tt);
|
spl_intrin_t in = spl_intrin_lookup_cast(sema->type, ft, tt);
|
||||||
if (in == SPL_INTRIN_NONE) {
|
if (in == SPL_INTRIN_NONE) {
|
||||||
SPL_ERROR(&n->dbg, "as: invalid conversion (not supported by as)");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
|
||||||
sema->error_count++;
|
"as: invalid conversion (not supported by as)");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_lang_tid = dst_lang;
|
n->resolved_lang_tid = dst_lang;
|
||||||
@@ -1509,27 +1477,27 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
spl_symbol_t sym;
|
spl_symbol_t sym;
|
||||||
if (!spl_scope_find(sema->scope, type_name, &sym)) {
|
if (!spl_scope_find(sema->scope, type_name, &sym)) {
|
||||||
SPL_ERROR(&n->dbg, "unknown type `%s`", type_name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg, "unknown type `%s`",
|
||||||
sema->error_count++;
|
type_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
||||||
if (!def || !def->lang_id) {
|
if (!def || !def->lang_id) {
|
||||||
SPL_ERROR(&n->dbg, "type `%s` not resolved", type_name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||||
sema->error_count++;
|
"type `%s` not resolved", type_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t agg = def->lang_id;
|
spl_lang_type_id_t agg = def->lang_id;
|
||||||
spl_lang_type_node_t *an = spl_lang_type_node(sema->type, agg);
|
spl_lang_type_node_t *an = spl_lang_type_node(sema->type, agg);
|
||||||
if (!an || (an->kind != SPL_LANG_TYPE_STRUCT && an->kind != SPL_LANG_TYPE_UNION &&
|
if (!an || (an->kind != SPL_LANG_TYPE_STRUCT && an->kind != SPL_LANG_TYPE_UNION &&
|
||||||
an->kind != SPL_LANG_TYPE_ENUM)) {
|
an->kind != SPL_LANG_TYPE_ENUM)) {
|
||||||
SPL_ERROR(&n->dbg, "`%s` is not a struct/union/enum", type_name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"`%s` is not a struct/union/enum", type_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (an->kind == SPL_LANG_TYPE_ENUM && vec_size(n->aggregate_literal.fields) != 1) {
|
if (an->kind == SPL_LANG_TYPE_ENUM && vec_size(n->aggregate_literal.fields) != 1) {
|
||||||
SPL_ERROR(&n->dbg, "enum literal must have exactly one variant");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"enum literal must have exactly one variant");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg);
|
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg);
|
||||||
@@ -1543,8 +1511,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
usize idx = 0;
|
usize idx = 0;
|
||||||
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name,
|
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name,
|
||||||
&idx)) {
|
&idx)) {
|
||||||
SPL_ERROR(&item->dbg, "no field `%s`", item->struct_init_item.name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
|
||||||
sema->error_count++;
|
item->struct_init_item.name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||||
@@ -1561,8 +1529,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
case SPL_AST_EXPR_COMPTIME_CALL: {
|
case SPL_AST_EXPR_COMPTIME_CALL: {
|
||||||
spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name);
|
spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name);
|
||||||
if (in == SPL_INTRIN_NONE) {
|
if (in == SPL_INTRIN_NONE) {
|
||||||
SPL_ERROR(&n->dbg, "unknown comptime call `@%s`", n->comptime_call.name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_INTRIN, &n->dbg,
|
||||||
sema->error_count++;
|
"unknown comptime call `@%s`", n->comptime_call.name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->comptime_call.args);
|
spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->comptime_call.args);
|
||||||
@@ -1571,17 +1539,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- BLOCK ---------- */
|
/* ---------- BLOCK ---------- */
|
||||||
case SPL_AST_EXPR_BLOCK: {
|
case SPL_AST_EXPR_BLOCK:
|
||||||
sema_push_scope(sema);
|
return sema_block_body(sema, n, 0);
|
||||||
spl_lang_type_id_t last = 0;
|
|
||||||
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
|
|
||||||
sema_infer(sema, vec_at(n->block.stmts, i));
|
|
||||||
if (n->block.tail_expr)
|
|
||||||
last = sema_infer(sema, n->block.tail_expr);
|
|
||||||
sema_pop_scope(sema);
|
|
||||||
n->resolved_lang_tid = last;
|
|
||||||
return last;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- IF ---------- */
|
/* ---------- IF ---------- */
|
||||||
case SPL_AST_EXPR_IF: {
|
case SPL_AST_EXPR_IF: {
|
||||||
@@ -1666,7 +1625,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, var_name, id_node->dbg,
|
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, var_name, id_node->dbg,
|
||||||
vec_at(n->for_expr.idents, i));
|
vec_at(n->for_expr.idents, i));
|
||||||
spl_def_resolve(sema->type, sym.node, elem_tid);
|
spl_def_resolve(sema->type, sym.node, elem_tid);
|
||||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||||
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL,
|
||||||
|
&id_node->dbg, "duplicate symbol `%s`", var_name);
|
||||||
|
}
|
||||||
id_node->resolved_def_id = sym.node;
|
id_node->resolved_def_id = sym.node;
|
||||||
id_node->resolved_lang_tid = elem_tid;
|
id_node->resolved_lang_tid = elem_tid;
|
||||||
}
|
}
|
||||||
@@ -1718,8 +1680,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
spl_symbol_t sym;
|
spl_symbol_t sym;
|
||||||
if (!spl_scope_find(sema->scope, name, &sym)) {
|
if (!spl_scope_find(sema->scope, name, &sym)) {
|
||||||
SPL_ERROR(&n->dbg, "type `%s` not found", name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||||
sema->error_count++;
|
"type `%s` not found", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t t = sema_eval_decl(sema, sym.node);
|
spl_lang_type_id_t t = sema_eval_decl(sema, sym.node);
|
||||||
@@ -1785,8 +1747,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
const char *name = n->type_comptime_call.name;
|
const char *name = n->type_comptime_call.name;
|
||||||
if (name && strcmp(name, "self") == 0) {
|
if (name && strcmp(name, "self") == 0) {
|
||||||
if (sema->current_aggregate_lang == 0) {
|
if (sema->current_aggregate_lang == 0) {
|
||||||
SPL_ERROR(&n->dbg, "`@self` outside of aggregate");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||||
sema->error_count++;
|
"`@self` outside of aggregate");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_lang_tid = sema->current_aggregate_lang;
|
n->resolved_lang_tid = sema->current_aggregate_lang;
|
||||||
@@ -1842,7 +1804,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
pdef->state = p_tid ? SPL_DECL_RESOLVED : SPL_DECL_ERROR;
|
pdef->state = p_tid ? SPL_DECL_RESOLVED : SPL_DECL_ERROR;
|
||||||
}
|
}
|
||||||
pd->resolved_def_id = psym.node;
|
pd->resolved_def_id = psym.node;
|
||||||
spl_scope_insert(sema->scope, sema->scope->current_scope, psym);
|
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, psym)) {
|
||||||
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &pd->dbg,
|
||||||
|
"duplicate symbol `%s`", psym.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t old_ret = sema->current_fn_ret_tid;
|
spl_lang_type_id_t old_ret = sema->current_fn_ret_tid;
|
||||||
@@ -1885,8 +1850,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
case SPL_AST_CONST_DECL: {
|
case SPL_AST_CONST_DECL: {
|
||||||
spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern);
|
spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern);
|
||||||
if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) {
|
if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) {
|
||||||
SPL_ERROR(&n->dbg, "unsupported variable pattern");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||||
sema->error_count++;
|
"unsupported variable pattern");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const char *name = pat->pattern_ident.name;
|
const char *name = pat->pattern_ident.name;
|
||||||
@@ -1895,7 +1860,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
|
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
|
||||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref);
|
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref);
|
||||||
n->resolved_def_id = sym.node;
|
n->resolved_def_id = sym.node;
|
||||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||||
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
|
||||||
|
"duplicate symbol `%s`", name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spl_lang_type_id_t decl_tid = 0;
|
spl_lang_type_id_t decl_tid = 0;
|
||||||
@@ -1903,8 +1871,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
decl_tid = sema_infer(sema, n->var_const_decl.type);
|
decl_tid = sema_infer(sema, n->var_const_decl.type);
|
||||||
|
|
||||||
if (!n->var_const_decl.init_expr) {
|
if (!n->var_const_decl.init_expr) {
|
||||||
SPL_ERROR(&n->dbg, "variable `%s` must be initialized", name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_VAR_UNINITIALIZED, &n->dbg,
|
||||||
sema->error_count++;
|
"variable `%s` must be initialized", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1913,8 +1881,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
} else {
|
} else {
|
||||||
decl_tid = sema_infer(sema, n->var_const_decl.init_expr);
|
decl_tid = sema_infer(sema, n->var_const_decl.init_expr);
|
||||||
if (!decl_tid || sema_is_infer(sema, decl_tid)) {
|
if (!decl_tid || sema_is_infer(sema, decl_tid)) {
|
||||||
SPL_ERROR(&n->dbg, "cannot infer type of `%s`", name);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_CANNOT_INFER, &n->dbg,
|
||||||
sema->error_count++;
|
"cannot infer type of `%s`", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1925,16 +1893,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- MEMBER / PARAM ---------- */
|
/* ---------- MEMBER / PARAM ---------- */
|
||||||
case SPL_AST_MEMBER_DECL: {
|
case SPL_AST_MEMBER_DECL:
|
||||||
if (n->member_decl.type_expr)
|
if (n->member_decl.type_expr)
|
||||||
return sema_infer(sema, n->member_decl.type_expr);
|
return sema_infer(sema, n->member_decl.type_expr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
case SPL_AST_PARAM_DECL:
|
||||||
case SPL_AST_PARAM_DECL: {
|
|
||||||
if (n->param_decl.type_expr)
|
if (n->param_decl.type_expr)
|
||||||
return sema_infer(sema, n->param_decl.type_expr);
|
return sema_infer(sema, n->param_decl.type_expr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- 语句 ---------- */
|
/* ---------- 语句 ---------- */
|
||||||
case SPL_AST_STATEMENT_RET: {
|
case SPL_AST_STATEMENT_RET: {
|
||||||
@@ -1946,8 +1912,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
} else if (sema->current_fn_ret_tid) {
|
} else if (sema->current_fn_ret_tid) {
|
||||||
spl_lang_type_id_t u = spl_lang_make_unit(sema->type);
|
spl_lang_type_id_t u = spl_lang_make_unit(sema->type);
|
||||||
if (sema->current_fn_ret_tid != u) {
|
if (sema->current_fn_ret_tid != u) {
|
||||||
SPL_ERROR(&n->dbg, "function must return a value");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_MUST_RETURN_VALUE, &n->dbg,
|
||||||
sema->error_count++;
|
"function must return a value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1960,8 +1926,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
lbl = ln->label.name;
|
lbl = ln->label.name;
|
||||||
}
|
}
|
||||||
if (vec_size(sema->label_stack) == 0) {
|
if (vec_size(sema->label_stack) == 0) {
|
||||||
SPL_ERROR(&n->dbg, "`break` outside of loop");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_BREAK_OUTSIDE_LOOP, &n->dbg,
|
||||||
sema->error_count++;
|
"`break` outside of loop");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (lbl) {
|
if (lbl) {
|
||||||
@@ -1974,12 +1940,11 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_LABEL, &n->dbg,
|
||||||
sema->error_count++;
|
"undefined label `$%s`", lbl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n->statement_break.expr) {
|
if (n->statement_break.expr) {
|
||||||
/* 有值 loop:break 值 coerce 到 loop 的期望类型 */
|
|
||||||
if (sema->current_loop_break_tid != 0) {
|
if (sema->current_loop_break_tid != 0) {
|
||||||
sema_coerce(sema, n->statement_break.expr, sema->current_loop_break_tid);
|
sema_coerce(sema, n->statement_break.expr, sema->current_loop_break_tid);
|
||||||
} else {
|
} else {
|
||||||
@@ -1996,8 +1961,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
lbl = ln->label.name;
|
lbl = ln->label.name;
|
||||||
}
|
}
|
||||||
if (vec_size(sema->label_stack) == 0) {
|
if (vec_size(sema->label_stack) == 0) {
|
||||||
SPL_ERROR(&n->dbg, "`continue` outside of loop");
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_CONTINUE_OUTSIDE_LOOP, &n->dbg,
|
||||||
sema->error_count++;
|
"`continue` outside of loop");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (lbl) {
|
if (lbl) {
|
||||||
@@ -2010,8 +1975,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
|
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_LABEL, &n->dbg,
|
||||||
sema->error_count++;
|
"undefined label `$%s`", lbl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2050,14 +2015,14 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope
|
|||||||
sema->ast = ast;
|
sema->ast = ast;
|
||||||
sema->type = type;
|
sema->type = type;
|
||||||
sema->scope = scope;
|
sema->scope = scope;
|
||||||
sema->error_count = 0;
|
|
||||||
sema->current_fn_ret_tid = 0;
|
sema->current_fn_ret_tid = 0;
|
||||||
sema->current_aggregate_lang = 0;
|
sema->current_aggregate_lang = 0;
|
||||||
sema->current_loop_break_tid = 0;
|
sema->current_loop_break_tid = 0;
|
||||||
sema->attr = attr;
|
sema->attr = attr;
|
||||||
sema->root = (spl_symbol_t){0};
|
sema->root = (spl_symbol_t){0};
|
||||||
sema->store_scope = 0;
|
|
||||||
vec_init(sema->label_stack);
|
vec_init(sema->label_stack);
|
||||||
|
|
||||||
|
sema->diag = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_sema_drop(spl_sema_t *sema) { vec_free(sema->label_stack); }
|
void spl_sema_drop(spl_sema_t *sema) { vec_free(sema->label_stack); }
|
||||||
|
|||||||
+9
-6
@@ -2,11 +2,11 @@
|
|||||||
#define __SPL_SEMA_H__
|
#define __SPL_SEMA_H__
|
||||||
|
|
||||||
#include "spl_ast.h"
|
#include "spl_ast.h"
|
||||||
|
#include "spl_attr.h"
|
||||||
|
#include "spl_diag.h"
|
||||||
#include "spl_mpa.h"
|
#include "spl_mpa.h"
|
||||||
#include "spl_type.h"
|
#include "spl_type.h"
|
||||||
|
|
||||||
#include "spl_attr.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SPL_SYMBOL_KIND_ERROR,
|
SPL_SYMBOL_KIND_ERROR,
|
||||||
SPL_SYMBOL_KIND_VAR,
|
SPL_SYMBOL_KIND_VAR,
|
||||||
@@ -14,6 +14,7 @@ typedef enum {
|
|||||||
SPL_SYMBOL_KIND_FN,
|
SPL_SYMBOL_KIND_FN,
|
||||||
SPL_SYMBOL_KIND_TYPE,
|
SPL_SYMBOL_KIND_TYPE,
|
||||||
} spl_symbol_kind_t;
|
} spl_symbol_kind_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
spl_symbol_kind_t kind;
|
spl_symbol_kind_t kind;
|
||||||
@@ -21,11 +22,13 @@ typedef struct {
|
|||||||
} spl_symbol_t;
|
} spl_symbol_t;
|
||||||
|
|
||||||
typedef usize spl_scope_id_t; /* 0 is error */
|
typedef usize spl_scope_id_t; /* 0 is error */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_scope_id_t parent;
|
spl_scope_id_t parent;
|
||||||
MAP(const char *, spl_symbol_t) symbols;
|
MAP(const char *, spl_symbol_t) symbols;
|
||||||
} spl_scope_node_t;
|
} spl_scope_node_t;
|
||||||
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
|
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_scope_node_vec_t scopes;
|
spl_scope_node_vec_t scopes;
|
||||||
spl_scope_id_t root_scope;
|
spl_scope_id_t root_scope;
|
||||||
@@ -34,24 +37,24 @@ typedef struct {
|
|||||||
|
|
||||||
void spl_scope_init(spl_scope_t *scope);
|
void spl_scope_init(spl_scope_t *scope);
|
||||||
void spl_scope_drop(spl_scope_t *scope);
|
void spl_scope_drop(spl_scope_t *scope);
|
||||||
|
|
||||||
spl_scope_id_t spl_scope_alloc(spl_scope_t *scope);
|
spl_scope_id_t spl_scope_alloc(spl_scope_t *scope);
|
||||||
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol);
|
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol);
|
||||||
typedef VEC(const char *) spl_symbol_path_t;
|
|
||||||
bool spl_scope_find(spl_scope_t *scop, const char *symbol_name, spl_symbol_t *out);
|
bool spl_scope_find(spl_scope_t *scop, const char *symbol_name, spl_symbol_t *out);
|
||||||
|
|
||||||
|
typedef VEC(const char *) spl_symbol_path_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_ast_t *ast;
|
spl_ast_t *ast;
|
||||||
spl_type_t *type;
|
spl_type_t *type;
|
||||||
spl_scope_t *scope;
|
spl_scope_t *scope;
|
||||||
spl_symbol_t root;
|
spl_symbol_t root;
|
||||||
int error_count;
|
|
||||||
spl_scope_id_t store_scope;
|
|
||||||
spl_attr_t *attr;
|
spl_attr_t *attr;
|
||||||
spl_lang_type_id_t current_aggregate_lang;
|
spl_lang_type_id_t current_aggregate_lang;
|
||||||
spl_lang_type_id_t current_fn_ret_tid;
|
spl_lang_type_id_t current_fn_ret_tid;
|
||||||
spl_lang_type_id_t current_loop_break_tid;
|
spl_lang_type_id_t current_loop_break_tid;
|
||||||
spl_symbol_path_t label_stack;
|
spl_symbol_path_t label_stack;
|
||||||
|
|
||||||
|
spl_diag_t *diag;
|
||||||
} spl_sema_t;
|
} spl_sema_t;
|
||||||
|
|
||||||
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope,
|
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope,
|
||||||
|
|||||||
+40
-72
@@ -380,61 +380,43 @@ bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub,
|
|||||||
if (!nsub || !nsuper)
|
if (!nsub || !nsuper)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* never 是任何类型的子类型(undefined / null 字面量的 pointee) */
|
||||||
if (nsub->kind == SPL_LANG_TYPE_NEVER)
|
if (nsub->kind == SPL_LANG_TYPE_NEVER)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/* 任何类型是 any 的子类型 */
|
||||||
if (nsuper->kind == SPL_LANG_TYPE_ANY)
|
if (nsuper->kind == SPL_LANG_TYPE_ANY)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/* 整数:只有 comptime_int (bits==0) 能物化到具体整数 */
|
||||||
if (nsub->kind == SPL_LANG_TYPE_INT && nsuper->kind == SPL_LANG_TYPE_INT) {
|
if (nsub->kind == SPL_LANG_TYPE_INT && nsuper->kind == SPL_LANG_TYPE_INT) {
|
||||||
spl_type_node_t *ir_sub = spl_type_node(type, nsub->ir_type_id);
|
spl_type_node_t *ir_sub = spl_type_node(type, nsub->ir_type_id);
|
||||||
spl_type_node_t *ir_super = spl_type_node(type, nsuper->ir_type_id);
|
if (!ir_sub)
|
||||||
if (!ir_sub || !ir_super)
|
|
||||||
return false;
|
|
||||||
uint32_t sb = (uint32_t)ir_sub->int_type.bits;
|
|
||||||
uint32_t pb = (uint32_t)ir_super->int_type.bits;
|
|
||||||
/* comptime_int (bits==0) 是整数格的 top */
|
|
||||||
if (pb == 0)
|
|
||||||
return true; /* 任何具体整数 <: comptime_int */
|
|
||||||
if (sb == 0)
|
|
||||||
return false; /* comptime_int 不能隐式收窄到具体整数 */
|
|
||||||
bool ss = ir_sub->int_type.is_signed != 0;
|
|
||||||
bool ps = ir_super->int_type.is_signed != 0;
|
|
||||||
if (ss == ps)
|
|
||||||
return sb <= pb;
|
|
||||||
if (!ss && ps)
|
|
||||||
return sb < pb;
|
|
||||||
return false;
|
return false;
|
||||||
|
return ir_sub->int_type.bits == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 浮点:只有 comptime_float (bits==0) 能物化到具体浮点 */
|
||||||
if (nsub->kind == SPL_LANG_TYPE_FLOAT && nsuper->kind == SPL_LANG_TYPE_FLOAT) {
|
if (nsub->kind == SPL_LANG_TYPE_FLOAT && nsuper->kind == SPL_LANG_TYPE_FLOAT) {
|
||||||
spl_type_node_t *ir_sub = spl_type_node(type, nsub->ir_type_id);
|
spl_type_node_t *ir_sub = spl_type_node(type, nsub->ir_type_id);
|
||||||
spl_type_node_t *ir_super = spl_type_node(type, nsuper->ir_type_id);
|
if (!ir_sub)
|
||||||
if (!ir_sub || !ir_super)
|
|
||||||
return false;
|
return false;
|
||||||
uint32_t sb = (uint32_t)ir_sub->float_type.bits;
|
return ir_sub->float_type.bits == 0;
|
||||||
uint32_t pb = (uint32_t)ir_super->float_type.bits;
|
|
||||||
if (pb == 0)
|
|
||||||
return true;
|
|
||||||
if (sb == 0)
|
|
||||||
return false;
|
|
||||||
return sb <= pb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 指针:只保留 *never -> *T、*T -> *any、同 elem */
|
||||||
if (nsub->kind == SPL_LANG_TYPE_PTR && nsuper->kind == SPL_LANG_TYPE_PTR) {
|
if (nsub->kind == SPL_LANG_TYPE_PTR && nsuper->kind == SPL_LANG_TYPE_PTR) {
|
||||||
|
if (nsub->extra.elem == nsuper->extra.elem)
|
||||||
|
return true;
|
||||||
spl_lang_type_node_t *sub_elem = spl_lang_type_node(type, nsub->extra.elem);
|
spl_lang_type_node_t *sub_elem = spl_lang_type_node(type, nsub->extra.elem);
|
||||||
spl_lang_type_node_t *super_elem = spl_lang_type_node(type, nsuper->extra.elem);
|
spl_lang_type_node_t *super_elem = spl_lang_type_node(type, nsuper->extra.elem);
|
||||||
if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER)
|
if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER)
|
||||||
return true;
|
return true;
|
||||||
if (super_elem && super_elem->kind == SPL_LANG_TYPE_ANY)
|
if (super_elem && super_elem->kind == SPL_LANG_TYPE_ANY)
|
||||||
return true;
|
return true;
|
||||||
if (nsub->extra.elem == nsuper->extra.elem)
|
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsub->kind == nsuper->kind)
|
|
||||||
return spl_type_is_subtype(type, nsub->ir_type_id, nsuper->ir_type_id);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,29 +451,34 @@ spl_lang_type_id_t spl_lang_type_join(const spl_type_t *type, spl_lang_type_id_t
|
|||||||
if (na->kind == SPL_LANG_TYPE_ANY || nb->kind == SPL_LANG_TYPE_ANY)
|
if (na->kind == SPL_LANG_TYPE_ANY || nb->kind == SPL_LANG_TYPE_ANY)
|
||||||
return spl_lang_make_any((spl_type_t *)type);
|
return spl_lang_make_any((spl_type_t *)type);
|
||||||
|
|
||||||
/* comptime 参与:返回另一侧的具体类型(comptime 是宽度未定,优先取具体) */
|
|
||||||
bool a_int = na->kind == SPL_LANG_TYPE_INT;
|
bool a_int = na->kind == SPL_LANG_TYPE_INT;
|
||||||
bool b_int = nb->kind == SPL_LANG_TYPE_INT;
|
bool b_int = nb->kind == SPL_LANG_TYPE_INT;
|
||||||
bool a_flt = na->kind == SPL_LANG_TYPE_FLOAT;
|
bool a_flt = na->kind == SPL_LANG_TYPE_FLOAT;
|
||||||
bool b_flt = nb->kind == SPL_LANG_TYPE_FLOAT;
|
bool b_flt = nb->kind == SPL_LANG_TYPE_FLOAT;
|
||||||
|
|
||||||
|
/* int / int:仅 comptime 混具体。两侧都具体则失败 */
|
||||||
if (a_int && b_int) {
|
if (a_int && b_int) {
|
||||||
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
|
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
|
||||||
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
|
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
|
||||||
if (ira && irb) {
|
if (!ira || !irb)
|
||||||
|
return 0;
|
||||||
bool a_ct = ira->int_type.bits == 0;
|
bool a_ct = ira->int_type.bits == 0;
|
||||||
bool b_ct = irb->int_type.bits == 0;
|
bool b_ct = irb->int_type.bits == 0;
|
||||||
if (a_ct && b_ct)
|
if (a_ct && b_ct)
|
||||||
return a; /* 都是 comptime_int */
|
return a;
|
||||||
if (a_ct)
|
if (a_ct)
|
||||||
return b;
|
return b;
|
||||||
if (b_ct)
|
if (b_ct)
|
||||||
return a;
|
return a;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* float / float:同 int 策略 */
|
||||||
if (a_flt && b_flt) {
|
if (a_flt && b_flt) {
|
||||||
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
|
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
|
||||||
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
|
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
|
||||||
if (ira && irb) {
|
if (!ira || !irb)
|
||||||
|
return 0;
|
||||||
bool a_ct = ira->float_type.bits == 0;
|
bool a_ct = ira->float_type.bits == 0;
|
||||||
bool b_ct = irb->float_type.bits == 0;
|
bool b_ct = irb->float_type.bits == 0;
|
||||||
if (a_ct && b_ct)
|
if (a_ct && b_ct)
|
||||||
@@ -500,10 +487,10 @@ spl_lang_type_id_t spl_lang_type_join(const spl_type_t *type, spl_lang_type_id_t
|
|||||||
return b;
|
return b;
|
||||||
if (b_ct)
|
if (b_ct)
|
||||||
return a;
|
return a;
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* int / float 混合:仅 comptime 混 comptime 视为 comptime_float */
|
/* int / float:只有 comptime 混 comptime 才视为 comptime_float */
|
||||||
if (a_int && b_flt) {
|
if (a_int && b_flt) {
|
||||||
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
|
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
|
||||||
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
|
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
|
||||||
@@ -519,46 +506,27 @@ spl_lang_type_id_t spl_lang_type_join(const spl_type_t *type, spl_lang_type_id_t
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 现在走子类型关系(两侧均为具体类型) */
|
/* 指针:*never 与任意 *T 结合得 *T;*T 与 *any 结合得 *any */
|
||||||
if (spl_lang_type_is_subtype(type, a, b))
|
if (na->kind == SPL_LANG_TYPE_PTR && nb->kind == SPL_LANG_TYPE_PTR) {
|
||||||
return b;
|
if (na->extra.elem == nb->extra.elem)
|
||||||
if (spl_lang_type_is_subtype(type, b, a))
|
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
if (na->kind != nb->kind)
|
spl_lang_type_node_t *ea = spl_lang_type_node(type, na->extra.elem);
|
||||||
return 0;
|
spl_lang_type_node_t *eb = spl_lang_type_node(type, nb->extra.elem);
|
||||||
|
|
||||||
if (a_int) {
|
/* 一侧 elem 是 never:结果取另一侧 */
|
||||||
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
|
if (ea && ea->kind == SPL_LANG_TYPE_NEVER)
|
||||||
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
|
return b;
|
||||||
if (!ira || !irb)
|
if (eb && eb->kind == SPL_LANG_TYPE_NEVER)
|
||||||
return 0;
|
return a;
|
||||||
uint32_t ba = (uint32_t)ira->int_type.bits;
|
|
||||||
uint32_t bb = (uint32_t)irb->int_type.bits;
|
/* 一侧 elem 是 any:结果取 any 那侧 */
|
||||||
bool sa = ira->int_type.is_signed != 0;
|
if (ea && ea->kind == SPL_LANG_TYPE_ANY)
|
||||||
bool sb = irb->int_type.is_signed != 0;
|
return a;
|
||||||
if (sa == sb) {
|
if (eb && eb->kind == SPL_LANG_TYPE_ANY)
|
||||||
uint32_t bits = ba > bb ? ba : bb;
|
return b;
|
||||||
return spl_lang_make_int((spl_type_t *)type, bits, sa);
|
|
||||||
}
|
|
||||||
uint32_t s_bits = sa ? ba : bb;
|
|
||||||
uint32_t u_bits = sa ? bb : ba;
|
|
||||||
uint32_t need = s_bits > (u_bits + 1) ? s_bits : (u_bits + 1);
|
|
||||||
uint32_t std_bits = spl_type_std_int_bits_up(need);
|
|
||||||
if (std_bits == 0)
|
|
||||||
return 0;
|
|
||||||
return spl_lang_make_int((spl_type_t *)type, std_bits, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a_flt) {
|
|
||||||
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
|
|
||||||
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
|
|
||||||
if (!ira || !irb)
|
|
||||||
return 0;
|
return 0;
|
||||||
uint32_t ba = (uint32_t)ira->float_type.bits;
|
|
||||||
uint32_t bb = (uint32_t)irb->float_type.bits;
|
|
||||||
uint32_t bits = ba > bb ? ba : bb;
|
|
||||||
return spl_lang_make_float((spl_type_t *)type, bits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+23
-8
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "spl_ast.h"
|
#include "spl_ast.h"
|
||||||
#include "spl_ast2ir.h"
|
#include "spl_ast2ir.h"
|
||||||
|
#include "spl_diag.h"
|
||||||
#include "spl_ir2vm.h"
|
#include "spl_ir2vm.h"
|
||||||
#include "spl_lexer.h"
|
#include "spl_lexer.h"
|
||||||
#include "spl_sema.h"
|
#include "spl_sema.h"
|
||||||
@@ -77,11 +78,17 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
|||||||
// memory leak
|
// memory leak
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spl_diag_t diag;
|
||||||
|
spl_diag_init(&diag, stderr);
|
||||||
|
|
||||||
spl_ast_t ast;
|
spl_ast_t ast;
|
||||||
spl_ast_init(&ast, &toks);
|
spl_ast_init(&ast, &toks);
|
||||||
|
spl_diag_set_stage(&diag, SPL_STAGE_PARSE);
|
||||||
|
ast.diag = &diag;
|
||||||
spl_ast_parse(&ast);
|
spl_ast_parse(&ast);
|
||||||
if (ast.parsed < 0) {
|
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
|
||||||
printf("parse failed, no output\n");
|
spl_diag_summary(&diag);
|
||||||
// memory leak
|
// memory leak
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -101,10 +108,12 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
|||||||
spl_scope_init(&scope);
|
spl_scope_init(&scope);
|
||||||
spl_sema_init(&sema, &ast, &type, &scope, &attr);
|
spl_sema_init(&sema, &ast, &type, &scope, &attr);
|
||||||
sema.ast = *
|
sema.ast = *
|
||||||
|
spl_diag_set_stage(&diag, SPL_STAGE_SEMA);
|
||||||
|
sema.diag = &diag;
|
||||||
spl_sema_run(&sema);
|
spl_sema_run(&sema);
|
||||||
if (sema.error_count) {
|
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
|
||||||
printf("sema errors=%d, no output\n", sema.error_count);
|
|
||||||
// memory leak
|
// memory leak
|
||||||
|
spl_diag_summary(&diag);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (dump == DUMP_SEMA) {
|
if (dump == DUMP_SEMA) {
|
||||||
@@ -118,9 +127,12 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
|||||||
spl_ir_builder_t ir_builder;
|
spl_ir_builder_t ir_builder;
|
||||||
spl_ir_builder_init(&ir_builder);
|
spl_ir_builder_init(&ir_builder);
|
||||||
spl_ast2ir_init(&a2ir, &ir_builder, &sema);
|
spl_ast2ir_init(&a2ir, &ir_builder, &sema);
|
||||||
|
spl_diag_set_stage(&diag, SPL_STAGE_AST2IR);
|
||||||
|
a2ir.diag = &diag;
|
||||||
spl_ast2ir_run(&a2ir);
|
spl_ast2ir_run(&a2ir);
|
||||||
if (a2ir.err_count) {
|
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
|
||||||
printf("ast2ir errors=%d, no output\n", a2ir.err_count);
|
spl_diag_summary(&diag);
|
||||||
|
// memory leak
|
||||||
spl_ast2ir_drop(&a2ir);
|
spl_ast2ir_drop(&a2ir);
|
||||||
spl_sema_drop(&sema);
|
spl_sema_drop(&sema);
|
||||||
spl_ast_drop(&ast);
|
spl_ast_drop(&ast);
|
||||||
@@ -134,9 +146,12 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
|||||||
|
|
||||||
spl_ir2vm_t ir2vm;
|
spl_ir2vm_t ir2vm;
|
||||||
spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &type, &attr);
|
spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &type, &attr);
|
||||||
|
// ir2vm.diag = &diag;
|
||||||
|
spl_diag_set_stage(&diag, SPL_STAGE_IR2VM);
|
||||||
|
ir2vm.diag = &diag;
|
||||||
int rc = spl_ir2vm_run(&ir2vm);
|
int rc = spl_ir2vm_run(&ir2vm);
|
||||||
if (rc != 0) {
|
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
|
||||||
printf("ir2vm error %d", rc);
|
spl_diag_summary(&diag);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if (dump == DUMP_VM) {
|
if (dump == DUMP_VM) {
|
||||||
|
|||||||
Reference in new issue
Block a user