feat: struct参数/返回值 + SourceLoc + 测试补全
- struct 可作函数参数和返回值 (fn make_point -> Point) - SourceLoc 抽象: 所有 ast_make_* 参数 + AstNode 迁移完毕 - sema: +4 struct 类型检查测试 (字段类型/未定义/数量/嵌套) - codegen: +2 struct IR 生成测试 (decl + field_access) - 新增集成测试 14_struct_fn.l 测试: 104 单元 + 14 集成 = 全部通过
This commit is contained in:
@@ -115,6 +115,76 @@ void test_str_concat_type_ok() {
|
||||
arena_destroy(&a);
|
||||
}
|
||||
|
||||
/* === struct 类型检查测试 === */
|
||||
|
||||
void test_struct_field_type_mismatch() {
|
||||
Arena a = arena_create(1);
|
||||
size_t tc; ErrorInfo lex_err = {0};
|
||||
Token* toks = lex(&a,
|
||||
"struct Point { x: i64, y: i64 } fn main() { let p: Point = Point { x: 10, y: true }; return; }",
|
||||
"test", &tc, &lex_err);
|
||||
ASSERT(toks != NULL);
|
||||
ErrorInfo parse_err = {0};
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // y 字段类型不匹配: true 是 bool, 不是 i64
|
||||
arena_destroy(&a);
|
||||
}
|
||||
|
||||
void test_struct_undefined() {
|
||||
Arena a = arena_create(1);
|
||||
size_t tc; ErrorInfo lex_err = {0};
|
||||
Token* toks = lex(&a,
|
||||
"fn main() { let p: Unknown = Unknown { x: 1 }; return; }",
|
||||
"test", &tc, &lex_err);
|
||||
ASSERT(toks != NULL);
|
||||
ErrorInfo parse_err = {0};
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // Unknown 未定义
|
||||
arena_destroy(&a);
|
||||
}
|
||||
|
||||
void test_struct_field_count_mismatch() {
|
||||
Arena a = arena_create(1);
|
||||
size_t tc; ErrorInfo lex_err = {0};
|
||||
Token* toks = lex(&a,
|
||||
"struct Point { x: i64, y: i64 } fn main() { let p: Point = Point { x: 10 }; return; }",
|
||||
"test", &tc, &lex_err);
|
||||
ASSERT(toks != NULL);
|
||||
ErrorInfo parse_err = {0};
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // 缺少字段 'y'
|
||||
arena_destroy(&a);
|
||||
}
|
||||
|
||||
void test_struct_nested_type_ok() {
|
||||
Arena a = arena_create(1);
|
||||
size_t tc; ErrorInfo lex_err = {0};
|
||||
Token* toks = lex(&a,
|
||||
"struct Point { x: i64, y: i64 } struct Rect { tl: Point, br: Point } fn main() { let r: Rect = Rect { tl: Point { x: 0, y: 0 }, br: Point { x: 1, y: 1 } }; print_i64(r.tl.x); return; }",
|
||||
"test", &tc, &lex_err);
|
||||
ASSERT(toks != NULL);
|
||||
ErrorInfo parse_err = {0};
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0); // 嵌套结构体类型检查应通过
|
||||
arena_destroy(&a);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
TEST_RUN(test_type_error);
|
||||
TEST_RUN(test_undefined_var);
|
||||
@@ -123,5 +193,9 @@ int main(void) {
|
||||
TEST_RUN(test_assign_immutable_error);
|
||||
TEST_RUN(test_str_type_ok);
|
||||
TEST_RUN(test_str_concat_type_ok);
|
||||
TEST_RUN(test_struct_field_type_mismatch);
|
||||
TEST_RUN(test_struct_undefined);
|
||||
TEST_RUN(test_struct_field_count_mismatch);
|
||||
TEST_RUN(test_struct_nested_type_ok);
|
||||
return test_summary();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user