#include "test_utils.h" #include "parser.h" #include "lexer.h" #include "sema.h" #include "arena.h" void test_type_error() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; Token* toks = lex(&a, "fn main() { let x: i64 = 1; let y: i64 = x + 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); arena_destroy(&a); } void test_undefined_var() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; Token* toks = lex(&a, "fn main() { let x: i64 = y; 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); } void test_simple_ok() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; Token* toks = lex(&a, "fn main() { let x: i64 = 42; print_i64(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); } void test_let_mut_assign_ok() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; Token* toks = lex(&a, "fn main() { let mut x: i64 = 0; x = 42; print_i64(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); } void test_assign_immutable_error() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; Token* toks = lex(&a, "fn main() { let x: i64 = 0; x = 42; 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); } void test_str_type_ok() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; Token* toks = lex(&a, "fn main() { let msg: str = \"hello\"; print_str(msg); 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); } void test_str_concat_type_ok() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; Token* toks = lex(&a, "fn main() { let a: str = \"a\"; let b: str = \"b\"; let c: str = a + b; print_str(c); 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); TEST_RUN(test_simple_ok); TEST_RUN(test_let_mut_assign_ok); TEST_RUN(test_assign_immutable_error); TEST_RUN(test_str_type_ok); TEST_RUN(test_str_concat_type_ok); return test_summary(); }