stage1 重写进行代码设计并重构 提供diag替换老旧错误处理

This commit is contained in:
zzy committed 2026-09-16 15:21:59 +08:00
1 parent 7cbe2d2b9a
commit e4347cc3ea
14 files changed
+983 -526

No files matched your search

+104 -99
View File
@@ -59,12 +59,34 @@ const char *spl_unary_op_name(spl_unary_op_t op) {
typedef struct {
spl_ast_t *ast;
spl_diag_t *diag;
usize pos;
int failed;
int stop_as;
int stop_agg;
} 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 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) {
t = peek(p);
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;
}
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);
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;
}
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;
t = peek(p);
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;
}
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)
advance(p);
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 {
SPL_FATAL(t, "unexpected token in parameter list");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t,
"unexpected token in parameter list");
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);
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;
}
advance(p);
const spl_tok_t *t = peek(p);
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;
}
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);
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;
}
advance(p);
const spl_tok_t *t = peek(p);
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;
}
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, &params);
t = peek(p);
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;
}
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) {
advance(p);
} 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;
}
@@ -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);
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;
}
advance(p);
const spl_tok_t *t = peek(p);
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;
}
advance(p);
@@ -636,7 +653,7 @@ static spl_ast_node_ref_t parse_container_declaration(parser_t *p) {
return ref;
}
default:
SPL_FATAL(t, "unrecognized declaration");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unrecognized declaration");
vec_free(tag_list);
return 0;
}
@@ -659,7 +676,8 @@ static spl_ast_node_ref_t parse_var_pattern_atom(parser_t *p) {
advance(p);
const spl_tok_t *name = peek(p);
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;
}
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;
t = peek(p);
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;
}
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);
t = peek(p);
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;
}
advance(p);
@@ -700,7 +718,7 @@ static spl_ast_node_ref_t parse_var_pattern_atom(parser_t *p) {
}
return ref;
} else {
SPL_FATAL(t, "unexpected token in pattern");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unexpected token in pattern");
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) {
const spl_tok_t *bt = peek(p);
if (!bt) {
SPL_FATAL(bt, "expected type");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, bt, "expected type");
return 0;
}
@@ -762,7 +780,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
advance(p);
const spl_tok_t *t = peek(p);
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;
}
advance(p);
@@ -785,7 +803,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
t = peek(p);
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;
}
advance(p);
@@ -808,7 +826,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
advance(p);
const spl_tok_t *t = peek(p);
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;
}
advance(p);
@@ -822,7 +840,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
while (!p->failed) {
t = peek(p);
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;
}
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 == 3 && strncmp(name, "f32", 3) == 0) ||
(len == 3 && strncmp(name, "f64", 3) == 0) ||
(len == 4 && strncmp(name, "bool", 4) == 0)
// (len == 4 && strncmp(name, "void", 4) == 0) ||
// (len == 3 && strncmp(name, "any", 3) == 0)
) {
(len == 4 && strncmp(name, "bool", 4) == 0)) {
advance(p);
spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PATH, bt);
spl_ast_node_t *tp = node_at(p->ast, ref);
@@ -885,7 +900,8 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
advance(p);
const spl_tok_t *seg = peek(p);
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;
}
advance(p);
@@ -906,7 +922,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
return ref;
}
SPL_FATAL(bt, "unrecognized type");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, bt, "unrecognized type");
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);
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;
}
advance(p);
@@ -932,7 +948,7 @@ static spl_ast_node_ref_t parse_type_comptime_call(parser_t *p) {
args = parse_expr_list(p);
t = peek(p);
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);
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) {
const spl_tok_t *t = peek(p);
if (!t) {
SPL_FATAL(t, "expected type");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected type");
return 0;
}
@@ -980,7 +996,7 @@ static spl_ast_node_ref_t parse_type_expr(parser_t *p) {
t = peek(p);
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;
}
advance(p);
@@ -1027,7 +1043,7 @@ static spl_ast_node_ref_t parse_type_expr(parser_t *p) {
t = peek(p);
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;
}
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);
if (!t || t->type != TOK_L_BRACE) {
SPL_FATAL(t, "expected '{' in aggregate literal");
return fields; // 空 vec,调用者处理
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '{' in aggregate literal");
return fields;
}
advance(p); // 消费 '{'
advance(p);
while (!p->failed) {
t = peek(p);
if (!t || t->type == TOK_R_BRACE || t->type == TOK_EOF)
break;
// 字段必须由 '.' 开头
if (t->type != TOK_DOT) {
SPL_FATAL(t, "expected '.' in aggregate field initializer");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t,
"expected '.' in aggregate field initializer");
break;
}
advance(p);
t = peek(p);
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;
}
advance(p);
// 创建 struct_init_item 节点
spl_ast_node_ref_t item_ref = new_node(p, SPL_AST_STRUCT_INIT_ITEM, t);
spl_ast_node_t *item = node_at(p->ast, item_ref);
SET_STR_FIELD(p->ast, item->struct_init_item.name, t);
item->struct_init_item.expr = 0;
// 可选:= 表达式
if (peek(p) && peek(p)->type == TOK_ASSIGN) {
advance(p);
spl_ast_node_ref_t expr_ref = parse_expr(p);
@@ -1111,7 +1125,6 @@ static spl_ast_node_ref_vec_t parse_aggregate_fields(parser_t *p) {
vec_push(fields, item_ref);
// 分隔符
t = peek(p);
if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) {
advance(p);
@@ -1122,9 +1135,9 @@ static spl_ast_node_ref_vec_t parse_aggregate_fields(parser_t *p) {
t = peek(p);
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 {
advance(p); // 消费 '}'
advance(p);
}
return fields;
@@ -1295,7 +1308,7 @@ static spl_ast_node_ref_t parse_prefix(parser_t *p) {
else if (kw && kw->type == KW_FOR)
ref = parse_for_expr(p);
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;
}
if (!ref)
@@ -1357,7 +1370,7 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
t = peek(p);
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;
}
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);
expr = ref;
} else {
SPL_FATAL(next, "expected identifier or '*' after '.'");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, next,
"expected identifier or '*' after '.'");
break;
}
} 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);
t = peek(p);
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;
}
advance(p);
@@ -1404,7 +1418,7 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
} else {
t = peek(p);
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;
}
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) {
const spl_tok_t *t = peek(p);
if (!t) {
SPL_FATAL(t, "unexpected end of expression");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unexpected end of expression");
return 0;
}
@@ -1491,7 +1505,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
advance(p);
const spl_tok_t *nx = peek(p);
if (!nx) {
SPL_FATAL(t, "unexpected '.'");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unexpected '.'");
return 0;
}
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);
const spl_tok_t *close = peek(p);
if (!close || close->type != TOK_R_BRACKET) {
SPL_FATAL(close, "expected ']'");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, close, "expected ']'");
return 0;
}
advance(p); // 消费 ']'
@@ -1518,7 +1532,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
arr->array_literal.elem_type = 0;
return ref;
} else {
SPL_FATAL(nx, "expected '{' or '[' after '.'");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, nx, "expected '{' or '[' after '.'");
return 0;
}
}
@@ -1552,7 +1566,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
}
t = peek(p);
if (!t || t->type != TOK_R_PAREN) {
SPL_FATAL(t, "expected ')'");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')'");
return 0;
}
advance(p);
@@ -1562,7 +1576,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
} else {
t = peek(p);
if (!t || t->type != TOK_R_PAREN) {
SPL_FATAL(t, "expected ')'");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected ')'");
return 0;
}
advance(p);
@@ -1581,7 +1595,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
case KW_MATCH:
return parse_match_expr(p);
default:
SPL_FATAL(t, "unrecognized expression");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unrecognized expression");
return 0;
}
}
@@ -1609,7 +1623,7 @@ static spl_ast_node_ref_t parse_array_literal(parser_t *p) {
t = peek(p);
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;
}
advance(p);
@@ -1618,7 +1632,7 @@ static spl_ast_node_ref_t parse_array_literal(parser_t *p) {
t = peek(p);
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;
}
advance(p);
@@ -1627,7 +1641,7 @@ static spl_ast_node_ref_t parse_array_literal(parser_t *p) {
t = peek(p);
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;
}
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);
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;
}
advance(p);
@@ -1666,7 +1680,7 @@ static spl_ast_node_ref_t parse_comptime_call(parser_t *p) {
args = parse_expr_list(p);
t = peek(p);
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);
return 0;
}
@@ -1688,7 +1702,7 @@ static spl_ast_node_ref_t parse_label(parser_t *p) {
advance(p);
const spl_tok_t *name = peek(p);
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;
}
advance(p);
@@ -1726,14 +1740,15 @@ static spl_ast_node_ref_t parse_if_expr(parser_t *p) {
advance(p);
init_expr = parse_expr(p);
} else {
SPL_FATAL(t, "expected '=' in if var");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected '=' in if var");
return 0;
}
} else if (t && t->type == TOK_ASSIGN) {
advance(p);
init_expr = parse_expr(p);
} else {
SPL_FATAL(t, "expected type annotation or '=' in if var");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t,
"expected type annotation or '=' in if var");
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);
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;
}
advance(p);
@@ -1856,7 +1871,7 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
vec_init(idents);
t = peek(p);
if (!t || (t->type != TOK_IDENT && t->type != KW_UNDERSCORE)) {
SPL_FATAL(t, "expected binding variable or '_' in for");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "expected binding variable or '_' in for");
return 0;
}
advance(p);
@@ -1868,7 +1883,8 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
advance(p);
t = peek(p);
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;
}
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);
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;
}
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;
t = peek(p);
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;
}
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);
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;
}
advance(p);
@@ -1973,7 +1989,7 @@ static spl_ast_node_ref_t parse_match_expr(parser_t *p) {
t = peek(p);
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;
}
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;
return ref;
} else {
SPL_FATAL(t, "unrecognized statement");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unrecognized statement");
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) {
const spl_tok_t *start = peek(p);
if (!start || start->type != TOK_L_BRACE) {
SPL_FATAL(start, "expected '{'");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, start, "expected '{'");
return 0;
}
advance(p);
@@ -2168,7 +2184,7 @@ static spl_ast_node_ref_t parse_block(parser_t *p) {
while (!p->failed) {
const spl_tok_t *t = peek(p);
if (!t || t->type == TOK_EOF) {
SPL_FATAL(t, "block missing '}'");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t, "block missing '}'");
return ref;
}
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);
} else if (t && t->type == TOK_R_BRACE) {
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;
} else {
@@ -2202,12 +2219,13 @@ static spl_ast_node_ref_t parse_block(parser_t *p) {
if (block_like) {
vec_push(block->block.stmts, expr);
} else {
SPL_FATAL(t, "expected ';' or '}' after expression");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, t,
"expected ';' or '}' after expression");
break;
}
}
} else {
SPL_FATAL(t, "unrecognized token in block");
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_UNRECOGNIZED, t, "unrecognized token in block");
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->str_buckets);
ast->root = 0;
ast->parsed = 0;
ast->diag = NULL;
spl_ast_node_t n = {0};
vec_push(ast->node_buckets, n);
@@ -2232,11 +2250,11 @@ void spl_ast_parse(spl_ast_t *ast) {
parser_t p;
p.ast = ast;
p.diag = ast->diag;
p.pos = 0;
p.failed = 0;
p.stop_as = 0;
p.stop_agg = 0;
ast->parsed = 0;
spl_ast_node_ref_vec_t 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;
ast->root = root;
ast->parsed = p.failed ? -1 : 1;
}
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_free(ast->node_buckets);
vec_free(ast->input);
ast->parsed = 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];
}
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;
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;
case SPL_AST_EXPR_AGGREGATE_LIT:
dump_vec(ast, node->aggregate_literal.fields, stack);
break;
+3 -2
View File
@@ -4,6 +4,7 @@
#include "../stage0/include/utils.h"
#include "spl_attr.h"
#include "spl_dbg.h"
#include "spl_diag.h"
#include "spl_lexer.h"
#include "spl_mpa.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(char *) spl_ast_cstr_ref_vec_t;
typedef struct {
int parsed;
spl_tok_vec_t input;
spl_ast_node_vec_t node_buckets;
spl_ast_cstr_ref_vec_t str_buckets;
spl_ast_node_ref_t root;
spl_diag_t *diag;
} spl_ast_t;
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);
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);
#endif /* __SPL_AST_H__ */
+24 -87
View File
@@ -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);
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_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_type_id_t ft, spl_type_id_t tt,
spl_ir_node_ref_t v);
static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n, spl_type_id_t ft,
spl_type_id_t tt, 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,
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;
}
}
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)
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) {
usize nargs = vec_size(*args);
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;
}
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));
tt = node_ir(a, targ);
} else {
/* 单参数形式:目标类型由 sema 在节点上标好的 resolved 类型给出 */
tt = node_ir(a, n);
}
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: {
if (n->unary.op != SPL_UNARY_OP_DEREF)
return 0;
/* *p 作为左值,地址就是指针 p 的值 */
return emit_expr(a, n->unary.operand);
}
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;
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_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:
return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v);
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;
}
}
@@ -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);
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 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)
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) {
@@ -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) {
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_node_t *itn = spl_type_node(a->sema->type, it);
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_GT:
case SPL_OP_CMP_GE: {
/* 比较的操作数类型从左侧子节点读(sema 已 coerce 到共同类型) */
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;
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)
return 0;
/* 先求所有参数 */
usize nargs = vec_size(n->call.args);
spl_ir_node_ref_vec_t arg_refs;
vec_init(arg_refs);
for (usize i = 0; i < nargs; ++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_ir_node_ref_t call = spl_ir_builder_control_call(a->ir, ret_t, fn);
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_type_id_t usize_ir = to_ir_type(a, usize_lang);
/* base = 元素数据首地址 */
spl_ir_node_ref_t base = 0;
if (obj_kind == SPL_LANG_TYPE_PTR) {
/* ptr 值本身就是首元素地址 */
base = emit_expr(a, n->slice.obj);
} else if (obj_kind == SPL_LANG_TYPE_SLICE) {
/* 取 slice 的 ptr 字段 */
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
if (!slice_val)
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,
slice_val);
} else {
/* ARRAY:&arr 即首元素地址 */
base = emit_lvalue(a, n->slice.obj);
}
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) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
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);
spl_ir_builder_block_end(a->ir);
/* while 需要独立 head 块(含 cond + br);
loop 没有头块,body_blk 同时是入口和回跳目标 */
usize head_blk = 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};
ctx.cont_blk = cont_blk;
ctx.brk_blk = 0;
ctx.label = NULL;
ctx.result_slot = result_slot;
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)
return;
/* 有值 loop:先把 break 值写入 result_slot 再跳转 */
if (n->statement_break.expr && target->result_slot) {
spl_ir_node_ref_t bv = emit_expr(a, n->statement_break.expr);
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: {
spl_type_id_t ret_ir = to_ir_type(a, a->cur_ret_lang);
/* 先求值 ret 表达式,结果保存在 v 中 */
spl_ir_node_ref_t v = 0;
if (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) {
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
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,
spl_ir_node_ref_t v) {
static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n, spl_type_id_t ft,
spl_type_id_t tt, spl_ir_node_ref_t v) {
if (!ft || !tt || ft == tt)
return v;
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_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->float_type.bits > ts->float_type.bits)
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)
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)
return spl_ir_builder_cast_ptr2int(a->ir, ft, tt, v);
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_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); }
@@ -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);
vec_init(ast2ir->loop_stack);
vec_init(ast2ir->defer_stack);
ast2ir->err_count = 0;
ast2ir->cur_ret_lang = 0;
ast2ir->cur_defer_base = 0;
ast2ir->diag = NULL;
}
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {
+3 -2
View File
@@ -1,6 +1,7 @@
#ifndef __SPL_AST2IR_H__
#define __SPL_AST2IR_H__
#include "spl_diag.h"
#include "spl_ir.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 {
usize cont_blk;
usize brk_blk;
const char *label;
spl_ir_node_ref_vec_t breaks;
spl_ir_node_ref_t result_slot;
@@ -26,7 +26,8 @@ typedef struct {
spl_defer_stack_t defer_stack;
spl_lang_type_id_t cur_ret_lang;
usize cur_defer_base;
int err_count;
spl_diag_t *diag;
} spl_ast2ir_t;
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema);
+368
View File
@@ -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);
}
+165
View File
@@ -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
View File
@@ -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;
}
/* 从 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) {
spl_type_node_t *tn = spl_type_node(ctx->type, tid);
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)
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 指针,占用一个隐藏参数槽 */
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);
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;
}
/* 聚合返回时 fp+0 是 sret 指针,实参从 fp+8 起 */
spl_type_node_t *ftn = spl_type_node(ctx->type, cg->irf->fn_tid);
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;
usize shift = ir_is_aggregate(ctx, fn_ret_type(ctx, cg->irf->fn_tid)) ? 1 : 0;
CG_LADDR(cg, (idx + shift) * sizeof(spl_vm_val_t));
CG_LOAD(cg, 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};
entry.name = strdup(irf->name ? irf->name : "");
entry.idx_of_strtab = 0;
spl_type_node_t *ftn = spl_type_node(ctx->type, irf->fn_tid);
entry.nargs = (ftn && ftn->kind == SPL_TYPE_FN) ? vec_size(ftn->fn_type.params) : 0;
entry.nargs = fn_nargs(ctx, irf->fn_tid);
entry.ninsns = 0;
entry.address = func_ip;
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;
map_init(ctx->extern_native, spl_map_hash, spl_map_cmp);
spl_prog_init(&ctx->prog);
ctx->diag = NULL;
}
void spl_ir2vm_drop(spl_ir2vm_t *ctx) {
+3 -2
View File
@@ -1,6 +1,7 @@
#ifndef __SPL_IR2VM_H__
#define __SPL_IR2VM_H__
#include "spl_diag.h"
#include "spl_ir.h"
#include "spl_type.h"
@@ -13,7 +14,7 @@ typedef struct {
typedef VEC(spl_ir2vm_fdbg_t) spl_ir2vm_fdbg_vec_t;
typedef MAP(spl_ir_func_ref_t, isize) spl_extern_idx_map_t;
// MAP()
typedef struct {
const spl_ir_t *ir;
const spl_type_t *type;
@@ -21,7 +22,7 @@ typedef struct {
spl_extern_idx_map_t extern_native;
spl_prog_t prog;
// spl_ir2vm_fdbg_vec_t fdbg; /* ir2vm_run 后填充;splc0 -g 读取生成 debug 段 */
spl_diag_t *diag;
} spl_ir2vm_t;
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type,
+186 -221
View File
@@ -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) {
if (!id || id >= vec_size(scope->scopes)) {
LOG_FATAL("sema scope insert error");
return false;
}
Assert(id != 0 && id < vec_size(scope->scopes));
spl_scope_node_t *node = &vec_at(scope->scopes, id);
spl_symbol_t old = {0};
if (map_get(node->symbols, symbol.name, &old)) {
SPL_ERROR(&(spl_dbg_node_t){0}, "duplicate symbol `%s`", symbol.name);
if (map_get(node->symbols, symbol.name, &old))
return false;
}
map_put(node->symbols, symbol.name, symbol);
return true;
}
@@ -46,9 +41,8 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) {
return false;
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);
if (map_get(s->symbols, name, out)) {
if (map_get(s->symbols, name, out))
return true;
}
}
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);
if (!info) {
SPL_ERROR(&a->dbg, "unknown attribute `%s`", a->tag_item.name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_ATTR, &a->dbg,
"unknown attribute `%s`", a->tag_item.name);
continue;
}
usize nargs = vec_size(a->tag_item.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,
info->min_args, info->max_args, nargs);
sema->error_count++;
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);
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;
break;
default:
SPL_ERROR(&a->dbg, "attribute arg #%zu has unsupported form", j);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_ATTR, &a->dbg,
"attribute arg #%zu has unsupported form", j);
bad = 1;
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;
}
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) {
if (!buf || cap == 0)
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) {
spl_scope_id_t new_scope = spl_scope_alloc(sema->scope);
sema->store_scope = sema->scope->current_scope;
sema->scope->current_scope = new_scope;
}
static inline void sema_pop_scope(spl_sema_t *sema) {
spl_scope_id_t cur = sema->scope->current_scope;
if (cur != 0 && cur < vec_size(sema->scope->scopes)) {
sema->scope->current_scope = vec_at(sema->scope->scopes, cur).parent;
} else {
sema->scope->current_scope = sema->store_scope;
}
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;
}
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) {
SPL_ERROR(&def->dbg_node, "circular dependency on `%s`", def->name ? def->name : "?");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_CIRCULAR_DEP, &def->dbg_node,
"circular dependency on `%s`", def->name ? def->name : "?");
def->state = SPL_DECL_ERROR;
return 0;
}
@@ -457,13 +433,11 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
switch (n->kind) {
case SPL_AST_CONTAINER_MEMBERS: {
/* root_scope 只在第一次创建,后续 module 复用 */
if (sema->scope->root_scope == 0) {
spl_scope_id_t root = spl_scope_alloc(sema->scope);
sema->scope->root_scope = root;
}
/* 进入 root_scope,再为当前 module 开一个子 scope */
sema->scope->current_scope = sema->scope->root_scope;
spl_scope_id_t mod_scope = spl_scope_alloc(sema->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) {
sema_collect_names(sema, vec_at(n->container_members.declarations, i));
}
/* 故意不恢复 current_scope
保持 mod_scope 交给随后的 sema_parse 使用。
恢复由 spl_sema_run_module 统一负责 */
break;
}
case SPL_AST_TYPE_DECL: {
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);
if (!te) {
SPL_ERROR(&n->dbg, "type declaration `%s` missing type expression", n->type_decl.name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"type declaration `%s` missing type expression", n->type_decl.name);
return;
}
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
sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, ref);
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;
}
case SPL_AST_FN_DECL: {
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);
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;
}
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};
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref);
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 {
SPL_ERROR(&n->dbg, "unsupported variable pattern (only simple identifier)");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"unsupported variable pattern (only simple identifier)");
}
break;
}
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);
}
break;
default:
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);
usize nargs = vec_size(*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,
info->max_args, nargs);
sema->error_count++;
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);
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_PTR_FROM_INT:
case SPL_INTRIN_PTR_CAST: {
/* 双参数形式:源表达式 + 目标类型 */
spl_lang_type_id_t src_lang = sema_infer(sema, vec_at(*args, 0));
if (!src_lang)
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_intrin_t expected = spl_intrin_lookup_cast(sema->type, ft, tt);
if (expected == SPL_INTRIN_NONE) {
SPL_ERROR(&n->dbg, "`%s`: incompatible types", info->name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
"`%s`: incompatible types", info->name);
return 0;
}
/* 允许显式 builtin 覆盖 as 的默认选择(例如用 @int_cast 代替 @truncate) */
n->resolved_lang_tid = dst_lang;
return dst_lang;
}
case SPL_INTRIN_INT_FROM_BOOL:
case SPL_INTRIN_INT_FROM_PTR: {
/* 单参数:目标类型默认 usize;双参数时以第二参数为准 */
sema_infer(sema, vec_at(*args, 0));
if (nargs >= 2) {
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;
}
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,
spl_lang_type_id_t 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) {
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;
/* comptime 与 infer 都属于"可重定型":清空 resolved 后按 expected 重新推导 */
bool a_rebindable =
(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_FLOAT && air && air->float_type.bits == 0);
if (!a_rebindable) {
/* 具体类型:只接受子类型方向 */
if (spl_lang_type_is_subtype(sema->type, already, expected)) {
n->expected_lang_tid = 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];
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
sema_type_to_str(sema, already, gbuf, sizeof(gbuf));
SPL_ERROR(&n->dbg, "type mismatch: node kind=%d already typed as %s, expected %s",
(int)n->kind, gbuf, ebuf);
sema->error_count++;
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);
return 0;
}
/* 清空 resolved,走未定型路径,让递归按 expected 下推子节点 */
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) {
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)
break;
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];
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
SPL_ERROR(&n->dbg, "comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
return 0;
}
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;
}
/* ptr +/- int:expected 是 ptr 且左侧推断为 ptr。
* 右侧保留原整型;仅 comptime_int(bits==0)收紧到 isize。 */
if (op == SPL_OP_ADD || op == SPL_OP_SUB) {
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
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_node_t *rn = spl_lang_type_node(sema->type, rt);
if (!rn || rn->kind != SPL_LANG_TYPE_INT) {
SPL_ERROR(&n->dbg, "pointer offset must be integer");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"pointer offset must be integer");
return 0;
}
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 ntypes = vec_size(en->extra.elems);
if (nelems != ntypes) {
SPL_ERROR(&n->dbg, "tuple arity mismatch (expected %zu, got %zu)", ntypes, nelems);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"tuple arity mismatch (expected %zu, got %zu)", ntypes, nelems);
return 0;
}
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))
break;
/* 有名字时,名字必须与 expected 指向同一类型 */
if (n->aggregate_literal.name) {
spl_symbol_t sym;
if (!spl_scope_find(sema->scope, n->aggregate_literal.name, &sym)) {
SPL_ERROR(&n->dbg, "unknown type `%s`", n->aggregate_literal.name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
"unknown type `%s`", n->aggregate_literal.name);
return 0;
}
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
if (!def || def->lang_id != expected) {
SPL_ERROR(&n->dbg, "aggregate `%s` does not match expected type",
n->aggregate_literal.name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"aggregate `%s` does not match expected type",
n->aggregate_literal.name);
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_node_t *irn = spl_type_node(sema->type, agg_ir);
if (!irn) {
SPL_ERROR(&n->dbg, "aggregate type unresolved");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"aggregate type unresolved");
return 0;
}
if (en->kind == SPL_LANG_TYPE_ENUM) {
if (vec_size(n->aggregate_literal.fields) != 1) {
SPL_ERROR(&n->dbg, "enum literal must have exactly one variant");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"enum literal must have exactly one variant");
return 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) {
SPL_ERROR(&n->dbg, "invalid enum literal");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"invalid enum literal");
return 0;
}
usize idx = 0;
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);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no variant `%s`",
item->struct_init_item.name);
return 0;
}
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;
usize idx = 0;
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);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
item->struct_init_item.name);
continue;
}
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;
}
case SPL_AST_EXPR_BLOCK: {
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 (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;
}
case SPL_AST_EXPR_BLOCK:
return sema_block_body(sema, n, expected);
default:
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;
if (n->kind == SPL_AST_EXPR_INT_LIT && bits != 0 &&
!spl_lang_mpa_int_fits(sema->type, expected, n->int_lit)) {
SPL_ERROR(&n->dbg, "comptime value does not fit target type");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_FITS_OVERFLOW, &n->dbg,
"comptime value does not fit target type");
return 0;
}
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];
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
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);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"type mismatch: expect %s, got %s (node kind=%d)", ebuf, gbuf, (int)n->kind);
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;
}
/* ---------- IDENT:同时写 def_id 和 lang_tid 副本 ---------- */
/* ---------- IDENT ---------- */
case SPL_AST_EXPR_IDENT: {
const char *name = n->ident.name;
spl_symbol_t sym;
if (!spl_scope_find(sema->scope, name, &sym)) {
SPL_ERROR(&n->dbg, "undefined identifier `%s`", name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
"undefined identifier `%s`", name);
return 0;
}
if (sym.node == 0) {
SPL_ERROR(&n->dbg, "identifier `%s` has no definition", name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
"identifier `%s` has no definition", name);
return 0;
}
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) {
case SPL_UNARY_OP_MINUS:
if (tn->kind != SPL_LANG_TYPE_INT && tn->kind != SPL_LANG_TYPE_FLOAT) {
SPL_ERROR(&n->dbg, "unary minus requires numeric operand");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"unary minus requires numeric operand");
return 0;
}
n->resolved_lang_tid = op;
return op;
case SPL_UNARY_OP_BIT_NOT:
if (tn->kind != SPL_LANG_TYPE_INT) {
SPL_ERROR(&n->dbg, "bitwise not requires integer operand");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"bitwise not requires integer operand");
return 0;
}
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: {
if (tn->kind != SPL_LANG_TYPE_PTR) {
SPL_ERROR(&n->dbg, "deref requires pointer operand");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"deref requires pointer operand");
return 0;
}
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: {
spl_binary_op_t op = n->binary.op;
/* 赋值 / 复合赋值 */
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);
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;
}
/* 逻辑 */
if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
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];
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
SPL_ERROR(&n->dbg, "comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
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;
}
/* Range */
if (op == SPL_OP_RANGE) {
sema_infer(sema, n->binary.left);
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;
}
/* 移位:结果 = 左类型 */
if (op == SPL_OP_LSHIFT || op == SPL_OP_RSHIFT) {
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
if (!lt)
return 0;
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
if (!ln || ln->kind != SPL_LANG_TYPE_INT) {
SPL_ERROR(&n->dbg, "shift requires integer operands");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"shift requires integer operands");
return 0;
}
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 *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 &&
(op == SPL_OP_ADD || op == SPL_OP_SUB)) {
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];
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
SPL_ERROR(&n->dbg, "operand types cannot be joined: lhs=%s rhs=%s", lbuf, rbuf);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"operand types cannot be joined: lhs=%s rhs=%s", lbuf, rbuf);
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_node_t *fn = spl_lang_type_node(sema->type, callee_tid);
if (!fn || fn->kind != SPL_LANG_TYPE_FN) {
SPL_ERROR(&n->dbg, "callee is not a function");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_NOT_A_FUNCTION, &n->dbg,
"callee is not a function");
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);
if (has_varargs) {
if (nargs < fixed) {
SPL_ERROR(&n->dbg, "too few arguments (expected at least %zu)", fixed);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_ARG_COUNT_MISMATCH, &n->dbg,
"too few arguments (expected at least %zu)", fixed);
}
} else if (nargs != fixed) {
SPL_ERROR(&n->dbg, "argument count mismatch (expected %zu, got %zu)", fixed, nargs);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_ARG_COUNT_MISMATCH, &n->dbg,
"argument count mismatch (expected %zu, got %zu)", fixed, nargs);
}
/* 固定参数:check 到形参类型 */
for (usize i = 0; i < nargs && i < fixed; ++i) {
spl_lang_type_id_t pt =
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;
spl_lang_type_node_t *agg = spl_lang_type_node(sema->type, agg_lang);
if (!agg) {
SPL_ERROR(&n->dbg, "field access on invalid type");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg,
"field access on invalid type");
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) {
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id);
if (!ft) {
SPL_ERROR(&n->dbg, "cannot resolve field type");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg,
"cannot resolve field type");
return 0;
}
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;
}
SPL_ERROR(&n->dbg, "no field `%s`", n->field.field);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg, "no field `%s`",
n->field.field);
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: {
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) {
SPL_ERROR(&n->dbg, "tuple index must be an integer literal");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TUPLE_INDEX_OOB, &n->dbg,
"tuple index must be an integer literal");
return 0;
}
isize i = (isize)idx_node->int_lit.bits;
if (i < 0 || (usize)i >= vec_size(obj->extra.elems)) {
SPL_ERROR(&n->dbg, "tuple index out of range");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TUPLE_INDEX_OOB, &n->dbg,
"tuple index out of range");
return 0;
}
elem = vec_at(obj->extra.elems, (usize)i);
break;
}
default:
SPL_ERROR(&n->dbg, "index base must be array/slice/ptr/range/tuple");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_INDEX_BASE_INVALID, &n->dbg,
"index base must be array/slice/ptr/range/tuple");
return 0;
}
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) {
elem = obj->extra.elem;
} else {
SPL_ERROR(&n->dbg, "slice base must be array/ptr/slice");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_INDEX_BASE_INVALID, &n->dbg,
"slice base must be array/ptr/slice");
return 0;
}
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;
if (src_is_literal_int || src_is_literal_float) {
/* 字面量目标物化:允许任意宽度,as 会按其语义处理 */
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 ||
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 tt = spl_lang_type_get_ir_type(sema->type, dst_lang);
if (!ft || !tt) {
SPL_ERROR(&n->dbg, "as: unresolved source or target type");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
"as: unresolved source or target type");
return 0;
}
spl_intrin_t in = spl_intrin_lookup_cast(sema->type, ft, tt);
if (in == SPL_INTRIN_NONE) {
SPL_ERROR(&n->dbg, "as: invalid conversion (not supported by as)");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
"as: invalid conversion (not supported by as)");
return 0;
}
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;
if (!spl_scope_find(sema->scope, type_name, &sym)) {
SPL_ERROR(&n->dbg, "unknown type `%s`", type_name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg, "unknown type `%s`",
type_name);
return 0;
}
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
if (!def || !def->lang_id) {
SPL_ERROR(&n->dbg, "type `%s` not resolved", type_name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
"type `%s` not resolved", type_name);
return 0;
}
spl_lang_type_id_t agg = def->lang_id;
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 &&
an->kind != SPL_LANG_TYPE_ENUM)) {
SPL_ERROR(&n->dbg, "`%s` is not a struct/union/enum", type_name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"`%s` is not a struct/union/enum", type_name);
return 0;
}
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");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"enum literal must have exactly one variant");
return 0;
}
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;
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);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
item->struct_init_item.name);
continue;
}
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: {
spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name);
if (in == SPL_INTRIN_NONE) {
SPL_ERROR(&n->dbg, "unknown comptime call `@%s`", n->comptime_call.name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_INTRIN, &n->dbg,
"unknown comptime call `@%s`", n->comptime_call.name);
return 0;
}
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 ---------- */
case SPL_AST_EXPR_BLOCK: {
sema_push_scope(sema);
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;
}
case SPL_AST_EXPR_BLOCK:
return sema_block_body(sema, n, 0);
/* ---------- 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,
vec_at(n->for_expr.idents, i));
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_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;
if (!spl_scope_find(sema->scope, name, &sym)) {
SPL_ERROR(&n->dbg, "type `%s` not found", name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
"type `%s` not found", name);
return 0;
}
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;
if (name && strcmp(name, "self") == 0) {
if (sema->current_aggregate_lang == 0) {
SPL_ERROR(&n->dbg, "`@self` outside of aggregate");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
"`@self` outside of aggregate");
return 0;
}
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;
}
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;
@@ -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: {
spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern);
if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) {
SPL_ERROR(&n->dbg, "unsupported variable pattern");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"unsupported variable pattern");
return 0;
}
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};
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref);
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;
@@ -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);
if (!n->var_const_decl.init_expr) {
SPL_ERROR(&n->dbg, "variable `%s` must be initialized", name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_VAR_UNINITIALIZED, &n->dbg,
"variable `%s` must be initialized", name);
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 {
decl_tid = sema_infer(sema, n->var_const_decl.init_expr);
if (!decl_tid || sema_is_infer(sema, decl_tid)) {
SPL_ERROR(&n->dbg, "cannot infer type of `%s`", name);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_CANNOT_INFER, &n->dbg,
"cannot infer type of `%s`", name);
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 ---------- */
case SPL_AST_MEMBER_DECL: {
case SPL_AST_MEMBER_DECL:
if (n->member_decl.type_expr)
return sema_infer(sema, n->member_decl.type_expr);
return 0;
}
case SPL_AST_PARAM_DECL: {
case SPL_AST_PARAM_DECL:
if (n->param_decl.type_expr)
return sema_infer(sema, n->param_decl.type_expr);
return 0;
}
/* ---------- 语句 ---------- */
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) {
spl_lang_type_id_t u = spl_lang_make_unit(sema->type);
if (sema->current_fn_ret_tid != u) {
SPL_ERROR(&n->dbg, "function must return a value");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_MUST_RETURN_VALUE, &n->dbg,
"function must return a value");
}
}
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;
}
if (vec_size(sema->label_stack) == 0) {
SPL_ERROR(&n->dbg, "`break` outside of loop");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_BREAK_OUTSIDE_LOOP, &n->dbg,
"`break` outside of loop");
return 0;
}
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) {
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_LABEL, &n->dbg,
"undefined label `$%s`", lbl);
}
}
if (n->statement_break.expr) {
/* 有值 loop:break 值 coerce 到 loop 的期望类型 */
if (sema->current_loop_break_tid != 0) {
sema_coerce(sema, n->statement_break.expr, sema->current_loop_break_tid);
} 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;
}
if (vec_size(sema->label_stack) == 0) {
SPL_ERROR(&n->dbg, "`continue` outside of loop");
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_CONTINUE_OUTSIDE_LOOP, &n->dbg,
"`continue` outside of loop");
return 0;
}
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) {
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
sema->error_count++;
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_LABEL, &n->dbg,
"undefined label `$%s`", lbl);
}
}
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->type = type;
sema->scope = scope;
sema->error_count = 0;
sema->current_fn_ret_tid = 0;
sema->current_aggregate_lang = 0;
sema->current_loop_break_tid = 0;
sema->attr = attr;
sema->root = (spl_symbol_t){0};
sema->store_scope = 0;
vec_init(sema->label_stack);
sema->diag = NULL;
}
void spl_sema_drop(spl_sema_t *sema) { vec_free(sema->label_stack); }
+9 -6
View File
@@ -2,11 +2,11 @@
#define __SPL_SEMA_H__
#include "spl_ast.h"
#include "spl_attr.h"
#include "spl_diag.h"
#include "spl_mpa.h"
#include "spl_type.h"
#include "spl_attr.h"
typedef enum {
SPL_SYMBOL_KIND_ERROR,
SPL_SYMBOL_KIND_VAR,
@@ -14,6 +14,7 @@ typedef enum {
SPL_SYMBOL_KIND_FN,
SPL_SYMBOL_KIND_TYPE,
} spl_symbol_kind_t;
typedef struct {
const char *name;
spl_symbol_kind_t kind;
@@ -21,11 +22,13 @@ typedef struct {
} spl_symbol_t;
typedef usize spl_scope_id_t; /* 0 is error */
typedef struct {
spl_scope_id_t parent;
MAP(const char *, spl_symbol_t) symbols;
} spl_scope_node_t;
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
typedef struct {
spl_scope_node_vec_t scopes;
spl_scope_id_t root_scope;
@@ -34,24 +37,24 @@ typedef struct {
void spl_scope_init(spl_scope_t *scope);
void spl_scope_drop(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);
typedef VEC(const char *) spl_symbol_path_t;
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 {
spl_ast_t *ast;
spl_type_t *type;
spl_scope_t *scope;
spl_symbol_t root;
int error_count;
spl_scope_id_t store_scope;
spl_attr_t *attr;
spl_lang_type_id_t current_aggregate_lang;
spl_lang_type_id_t current_fn_ret_tid;
spl_lang_type_id_t current_loop_break_tid;
spl_symbol_path_t label_stack;
spl_diag_t *diag;
} spl_sema_t;
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope,
+58 -90
View File
@@ -380,61 +380,43 @@ bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub,
if (!nsub || !nsuper)
return false;
/* never 是任何类型的子类型(undefined / null 字面量的 pointee) */
if (nsub->kind == SPL_LANG_TYPE_NEVER)
return true;
/* 任何类型是 any 的子类型 */
if (nsuper->kind == SPL_LANG_TYPE_ANY)
return true;
/* 整数:只有 comptime_int (bits==0) 能物化到具体整数 */
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_super = spl_type_node(type, nsuper->ir_type_id);
if (!ir_sub || !ir_super)
if (!ir_sub)
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 ir_sub->int_type.bits == 0;
}
/* 浮点:只有 comptime_float (bits==0) 能物化到具体浮点 */
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_super = spl_type_node(type, nsuper->ir_type_id);
if (!ir_sub || !ir_super)
if (!ir_sub)
return false;
uint32_t sb = (uint32_t)ir_sub->float_type.bits;
uint32_t pb = (uint32_t)ir_super->float_type.bits;
if (pb == 0)
return true;
if (sb == 0)
return false;
return sb <= pb;
return ir_sub->float_type.bits == 0;
}
/* 指针:只保留 *never -> *T、*T -> *any、同 elem */
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 *super_elem = spl_lang_type_node(type, nsuper->extra.elem);
if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER)
return true;
if (super_elem && super_elem->kind == SPL_LANG_TYPE_ANY)
return true;
if (nsub->extra.elem == nsuper->extra.elem)
return true;
return false;
}
if (nsub->kind == nsuper->kind)
return spl_type_is_subtype(type, nsub->ir_type_id, nsuper->ir_type_id);
return false;
}
@@ -469,41 +451,46 @@ 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)
return spl_lang_make_any((spl_type_t *)type);
/* comptime 参与:返回另一侧的具体类型(comptime 是宽度未定,优先取具体) */
bool a_int = na->kind == SPL_LANG_TYPE_INT;
bool b_int = nb->kind == SPL_LANG_TYPE_INT;
bool a_flt = na->kind == SPL_LANG_TYPE_FLOAT;
bool b_flt = nb->kind == SPL_LANG_TYPE_FLOAT;
/* int / int:仅 comptime 混具体。两侧都具体则失败 */
if (a_int && b_int) {
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) {
bool a_ct = ira->int_type.bits == 0;
bool b_ct = irb->int_type.bits == 0;
if (a_ct && b_ct)
return a; /* 都是 comptime_int */
if (a_ct)
return b;
if (b_ct)
return a;
}
if (!ira || !irb)
return 0;
bool a_ct = ira->int_type.bits == 0;
bool b_ct = irb->int_type.bits == 0;
if (a_ct && b_ct)
return a;
if (a_ct)
return b;
if (b_ct)
return a;
return 0;
}
/* float / float:同 int 策略 */
if (a_flt && b_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) {
bool a_ct = ira->float_type.bits == 0;
bool b_ct = irb->float_type.bits == 0;
if (a_ct && b_ct)
return a;
if (a_ct)
return b;
if (b_ct)
return a;
}
if (!ira || !irb)
return 0;
bool a_ct = ira->float_type.bits == 0;
bool b_ct = irb->float_type.bits == 0;
if (a_ct && b_ct)
return a;
if (a_ct)
return b;
if (b_ct)
return a;
return 0;
}
/* int / float 混合:仅 comptime 混 comptime 视为 comptime_float */
/* int / float:只有 comptime 混 comptime 才视为 comptime_float */
if (a_int && b_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);
@@ -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;
}
/* 现在走子类型关系(两侧均为具体类型) */
if (spl_lang_type_is_subtype(type, a, b))
return b;
if (spl_lang_type_is_subtype(type, b, a))
return a;
/* 指针:*never 与任意 *T 结合得 *T;*T 与 *any 结合得 *any */
if (na->kind == SPL_LANG_TYPE_PTR && nb->kind == SPL_LANG_TYPE_PTR) {
if (na->extra.elem == nb->extra.elem)
return a;
spl_lang_type_node_t *ea = spl_lang_type_node(type, na->extra.elem);
spl_lang_type_node_t *eb = spl_lang_type_node(type, nb->extra.elem);
/* 一侧 elem 是 never:结果取另一侧 */
if (ea && ea->kind == SPL_LANG_TYPE_NEVER)
return b;
if (eb && eb->kind == SPL_LANG_TYPE_NEVER)
return a;
/* 一侧 elem 是 any:结果取 any 那侧 */
if (ea && ea->kind == SPL_LANG_TYPE_ANY)
return a;
if (eb && eb->kind == SPL_LANG_TYPE_ANY)
return b;
if (na->kind != nb->kind)
return 0;
if (a_int) {
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;
uint32_t ba = (uint32_t)ira->int_type.bits;
uint32_t bb = (uint32_t)irb->int_type.bits;
bool sa = ira->int_type.is_signed != 0;
bool sb = irb->int_type.is_signed != 0;
if (sa == sb) {
uint32_t bits = ba > bb ? ba : bb;
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;
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;
+23 -8
View File
@@ -12,6 +12,7 @@
#include "spl_ast.h"
#include "spl_ast2ir.h"
#include "spl_diag.h"
#include "spl_ir2vm.h"
#include "spl_lexer.h"
#include "spl_sema.h"
@@ -77,11 +78,17 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
// memory leak
return 0;
}
spl_diag_t diag;
spl_diag_init(&diag, stderr);
spl_ast_t ast;
spl_ast_init(&ast, &toks);
spl_diag_set_stage(&diag, SPL_STAGE_PARSE);
ast.diag = &diag;
spl_ast_parse(&ast);
if (ast.parsed < 0) {
printf("parse failed, no output\n");
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
spl_diag_summary(&diag);
// memory leak
return 1;
}
@@ -101,10 +108,12 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
spl_scope_init(&scope);
spl_sema_init(&sema, &ast, &type, &scope, &attr);
sema.ast = &ast;
spl_diag_set_stage(&diag, SPL_STAGE_SEMA);
sema.diag = &diag;
spl_sema_run(&sema);
if (sema.error_count) {
printf("sema errors=%d, no output\n", sema.error_count);
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
// memory leak
spl_diag_summary(&diag);
return 1;
}
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_init(&ir_builder);
spl_ast2ir_init(&a2ir, &ir_builder, &sema);
spl_diag_set_stage(&diag, SPL_STAGE_AST2IR);
a2ir.diag = &diag;
spl_ast2ir_run(&a2ir);
if (a2ir.err_count) {
printf("ast2ir errors=%d, no output\n", a2ir.err_count);
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
spl_diag_summary(&diag);
// memory leak
spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema);
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_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);
if (rc != 0) {
printf("ir2vm error %d", rc);
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
spl_diag_summary(&diag);
return rc;
}
if (dump == DUMP_VM) {