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:
+87
-45
@@ -3,6 +3,7 @@
|
||||
|
||||
// === 类型关系 ===
|
||||
static TypeKind current_return_type = TYPE_VOID;
|
||||
static const char* current_return_struct_name = NULL;
|
||||
|
||||
static TypeKind promote(TypeKind a, TypeKind b) {
|
||||
if (a == TYPE_F64 || b == TYPE_F64) return TYPE_F64;
|
||||
@@ -26,11 +27,11 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
case AST_IDENT_EXPR: {
|
||||
Symbol* sym = scope_lookup(scope, node->as.ident.name);
|
||||
if (!sym) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的变量 '%s'", node->as.ident.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else if (sym->kind == SYM_FUNCTION) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"'%s' 是函数,不能作为表达式使用", node->as.ident.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else {
|
||||
@@ -47,7 +48,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
TypeKind inner = node->as.unary.operand->type.kind;
|
||||
if (node->as.unary.op == OP_NEG) {
|
||||
if (!is_numeric(inner)) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"一元 '-' 只能用于数值类型");
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else {
|
||||
@@ -55,7 +56,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
}
|
||||
} else { // OP_NOT
|
||||
if (inner != TYPE_BOOL) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"'!' 只能用于布尔类型,得到 '%s'", type_name(inner));
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else {
|
||||
@@ -77,7 +78,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
if (l == TYPE_STR || r == TYPE_STR) {
|
||||
// 字符串拼接:两边都必须是 str 类型
|
||||
if (l != TYPE_STR || r != TYPE_STR) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"字符串拼接需要两边都是 str 类型,得到 '%s' + '%s'",
|
||||
type_name(l), type_name(r));
|
||||
node->type.kind = TYPE_ERROR;
|
||||
@@ -85,7 +86,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
node->type.kind = TYPE_STR;
|
||||
}
|
||||
} else if (!is_numeric(l) || !is_numeric(r)) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"算术运算需要数值类型");
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else {
|
||||
@@ -94,7 +95,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
break;
|
||||
case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD:
|
||||
if (!is_numeric(l) || !is_numeric(r)) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"算术运算需要数值类型");
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else {
|
||||
@@ -103,7 +104,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
break;
|
||||
case OP_EQ: case OP_NE: case OP_LT: case OP_GT: case OP_LE: case OP_GE:
|
||||
if (!is_comparable(l, r)) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"类型 '%s' 和 '%s' 无法比较", type_name(l), type_name(r));
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else {
|
||||
@@ -112,7 +113,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
break;
|
||||
case OP_AND: case OP_OR:
|
||||
if (l != TYPE_BOOL || r != TYPE_BOOL) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"逻辑运算需要布尔类型");
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else {
|
||||
@@ -127,7 +128,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
case AST_CALL_EXPR: {
|
||||
Symbol* sym = scope_lookup(scope, node->as.call.name);
|
||||
if (!sym || sym->kind != SYM_FUNCTION) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的函数 '%s'", node->as.call.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
// 即使函数未定义,也要分析参数表达式(它们可能有更多错误)
|
||||
@@ -137,7 +138,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
break;
|
||||
}
|
||||
if (node->as.call.arg_count != sym->param_count) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"函数 '%s' 需要 %zu 个参数,但提供了 %zu 个",
|
||||
node->as.call.name, sym->param_count, node->as.call.arg_count);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
@@ -151,13 +152,30 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
analyze_expr(node->as.call.args[i], scope, errors, a);
|
||||
TypeKind actual = node->as.call.args[i]->type.kind;
|
||||
TypeKind expected = sym->param_types[i];
|
||||
if (actual != TYPE_ERROR && actual != expected) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
"参数 %zu 类型不匹配: 期望 '%s',得到 '%s'",
|
||||
i + 1, type_name(expected), type_name(actual));
|
||||
if (actual != TYPE_ERROR) {
|
||||
if (expected == TYPE_STRUCT) {
|
||||
// 结构体参数:比较具体类型名
|
||||
const char* actual_name = node->as.call.args[i]->type.struct_name;
|
||||
const char* expected_name = sym->param_struct_names ? sym->param_struct_names[i] : NULL;
|
||||
if (actual != TYPE_STRUCT || !actual_name || !expected_name ||
|
||||
strcmp(actual_name, expected_name) != 0) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"参数 %zu 类型不匹配: 期望 '%s',得到 '%s'",
|
||||
i + 1,
|
||||
expected_name ? expected_name : "struct",
|
||||
actual_name ? actual_name : type_name(actual));
|
||||
}
|
||||
} else if (actual != expected) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"参数 %zu 类型不匹配: 期望 '%s',得到 '%s'",
|
||||
i + 1, type_name(expected), type_name(actual));
|
||||
}
|
||||
}
|
||||
}
|
||||
node->type.kind = sym->return_type;
|
||||
if (sym->return_type == TYPE_STRUCT && sym->return_struct_type_name) {
|
||||
node->type.struct_name = sym->return_struct_type_name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -169,7 +187,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
break;
|
||||
}
|
||||
if (obj->type.kind != TYPE_STRUCT) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"类型 '%s' 不是结构体,不能访问字段 '%s'",
|
||||
type_name(obj->type.kind), node->as.field_access.field);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
@@ -178,21 +196,21 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
// 查找结构体定义
|
||||
const char* struct_name = obj->type.struct_name;
|
||||
if (!struct_name) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"无法确定结构体类型");
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
}
|
||||
Symbol* struct_sym = scope_lookup_struct(scope, struct_name);
|
||||
if (!struct_sym) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的结构体 '%s'", struct_name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
}
|
||||
int fi = scope_struct_field_index(struct_sym, node->as.field_access.field);
|
||||
if (fi < 0) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"结构体 '%s' 没有字段 '%s'", struct_name, node->as.field_access.field);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
@@ -211,13 +229,13 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
case AST_STRUCT_INIT: {
|
||||
Symbol* struct_sym = scope_lookup_struct(scope, node->as.struct_init.type_name);
|
||||
if (!struct_sym) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的结构体类型 '%s'", node->as.struct_init.type_name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
}
|
||||
if (node->as.struct_init.field_count != struct_sym->struct_field_count) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"结构体 '%s' 有 %zu 个字段,但提供了 %zu 个",
|
||||
node->as.struct_init.type_name,
|
||||
struct_sym->struct_field_count,
|
||||
@@ -233,7 +251,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
|
||||
int fi = scope_struct_field_index(struct_sym, fname);
|
||||
if (fi < 0) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"结构体 '%s' 没有字段 '%s'",
|
||||
node->as.struct_init.type_name, fname);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
@@ -242,7 +260,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
TypeKind expected = struct_sym->struct_field_types[fi];
|
||||
TypeKind actual = fval->type.kind;
|
||||
if (actual != TYPE_ERROR && actual != expected) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"字段 '%s' 类型不匹配: 期望 '%s',得到 '%s'",
|
||||
fname, type_name(expected), type_name(actual));
|
||||
}
|
||||
@@ -285,11 +303,15 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
for (size_t i = 0; i < node->as.program.fn_count; i++) {
|
||||
AstNode* fn = node->as.program.functions[i];
|
||||
TypeKind* pts = (TypeKind*)arena_alloc_impl(a, fn->as.function.param_count * sizeof(TypeKind));
|
||||
const char** pstruct_names = (const char**)arena_alloc_impl(a, fn->as.function.param_count * sizeof(const char*));
|
||||
for (size_t j = 0; j < fn->as.function.param_count; j++) {
|
||||
pts[j] = fn->as.function.params[j]->as.parameter.type;
|
||||
pstruct_names[j] = fn->as.function.params[j]->as.parameter.struct_type_name;
|
||||
}
|
||||
scope_insert_function(scope, a, fn->as.function.name,
|
||||
fn->as.function.return_type, pts,
|
||||
fn->as.function.return_type,
|
||||
fn->as.function.return_struct_type_name,
|
||||
pts, pstruct_names,
|
||||
fn->as.function.param_count);
|
||||
}
|
||||
// 第三遍:分析每个函数体
|
||||
@@ -303,12 +325,18 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
// 注册参数
|
||||
for (size_t i = 0; i < node->as.function.param_count; i++) {
|
||||
AstNode* p = node->as.function.params[i];
|
||||
scope_insert(fn_scope, a, p->as.parameter.name, SYM_PARAMETER, p->as.parameter.type);
|
||||
Symbol* sym = scope_insert(fn_scope, a, p->as.parameter.name, SYM_PARAMETER, p->as.parameter.type);
|
||||
if (sym && p->as.parameter.type == TYPE_STRUCT && p->as.parameter.struct_type_name) {
|
||||
sym->struct_type_name = p->as.parameter.struct_type_name;
|
||||
}
|
||||
}
|
||||
TypeKind saved = current_return_type;
|
||||
const char* saved_name = current_return_struct_name;
|
||||
current_return_type = node->as.function.return_type;
|
||||
current_return_struct_name = node->as.function.return_struct_type_name;
|
||||
analyze_node(node->as.function.body, fn_scope, errors, a);
|
||||
current_return_type = saved;
|
||||
current_return_struct_name = saved_name;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -330,7 +358,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
// struct 类型标注
|
||||
Symbol* st_sym = scope_lookup_struct(scope, annot_struct);
|
||||
if (!st_sym) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的结构体类型 '%s'", annot_struct);
|
||||
break;
|
||||
}
|
||||
@@ -340,7 +368,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
var_type = node->as.let_stmt.annot_type;
|
||||
}
|
||||
if (inferred != TYPE_ERROR && inferred != var_type) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"变量 '%s' 类型标注为 '%s',但初始化表达式类型为 '%s'",
|
||||
node->as.let_stmt.name,
|
||||
annot_struct ? annot_struct : type_name(var_type),
|
||||
@@ -349,7 +377,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
} else {
|
||||
// 类型推断
|
||||
if (inferred == TYPE_ERROR || inferred == TYPE_VOID) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"无法从表达式推断变量 '%s' 的类型", node->as.let_stmt.name);
|
||||
break;
|
||||
}
|
||||
@@ -363,7 +391,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
node->type.struct_name = var_struct_name;
|
||||
Symbol* sym = scope_insert(scope, a, node->as.let_stmt.name, SYM_VARIABLE, var_type);
|
||||
if (!sym) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"变量 '%s' 重复定义", node->as.let_stmt.name);
|
||||
} else {
|
||||
sym->is_mut = node->as.let_stmt.is_mut;
|
||||
@@ -378,19 +406,19 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
case AST_ASSIGN_STMT: {
|
||||
Symbol* sym = scope_lookup(scope, node->as.assign_stmt.name);
|
||||
if (!sym) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的变量 '%s'", node->as.assign_stmt.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
}
|
||||
if (sym->kind != SYM_VARIABLE) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"'%s' 不是变量,不能赋值", node->as.assign_stmt.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
}
|
||||
if (!sym->is_mut) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"不能对不可变变量 '%s' 赋值(需用 let mut 声明)",
|
||||
node->as.assign_stmt.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
@@ -399,7 +427,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
analyze_expr(node->as.assign_stmt.value, scope, errors, a);
|
||||
TypeKind value_ty = node->as.assign_stmt.value->type.kind;
|
||||
if (value_ty != TYPE_ERROR && value_ty != sym->type) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"赋值类型不匹配: 变量 '%s' 类型为 '%s',但表达式类型为 '%s'",
|
||||
node->as.assign_stmt.name, type_name(sym->type), type_name(value_ty));
|
||||
}
|
||||
@@ -411,7 +439,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
analyze_expr(node->as.if_stmt.cond, scope, errors, a);
|
||||
if (node->as.if_stmt.cond->type.kind != TYPE_BOOL &&
|
||||
node->as.if_stmt.cond->type.kind != TYPE_ERROR) {
|
||||
error_add(errors, "<sema>", node->line, node->col, "if 条件必须是布尔类型");
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col, "if 条件必须是布尔类型");
|
||||
}
|
||||
analyze_node(node->as.if_stmt.then_block, scope, errors, a);
|
||||
if (node->as.if_stmt.else_block) {
|
||||
@@ -423,7 +451,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
analyze_expr(node->as.while_stmt.cond, scope, errors, a);
|
||||
if (node->as.while_stmt.cond->type.kind != TYPE_BOOL &&
|
||||
node->as.while_stmt.cond->type.kind != TYPE_ERROR) {
|
||||
error_add(errors, "<sema>", node->line, node->col, "while 条件必须是布尔类型");
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col, "while 条件必须是布尔类型");
|
||||
}
|
||||
analyze_node(node->as.while_stmt.body, scope, errors, a);
|
||||
break;
|
||||
@@ -434,14 +462,28 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
node->type.kind = node->as.return_stmt.expr->type.kind;
|
||||
TypeKind actual = node->as.return_stmt.expr->type.kind;
|
||||
TypeKind expected = current_return_type;
|
||||
if (actual != TYPE_ERROR && expected != TYPE_VOID && actual != expected) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
"返回类型不匹配: 期望 '%s',得到 '%s'",
|
||||
type_name(expected), type_name(actual));
|
||||
if (actual != TYPE_ERROR && expected != TYPE_VOID) {
|
||||
if (expected == TYPE_STRUCT) {
|
||||
// 结构体返回类型:比较具体类型名
|
||||
const char* actual_name = node->as.return_stmt.expr->type.struct_name;
|
||||
const char* expected_name = current_return_struct_name;
|
||||
if (actual != TYPE_STRUCT || !actual_name || !expected_name ||
|
||||
strcmp(actual_name, expected_name) != 0) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"返回类型不匹配: 期望 '%s',得到 '%s'",
|
||||
expected_name ? expected_name : "struct",
|
||||
actual_name ? actual_name : type_name(actual));
|
||||
}
|
||||
} else if (actual != expected) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"返回类型不匹配: 期望 '%s',得到 '%s'",
|
||||
type_name(expected), type_name(actual));
|
||||
}
|
||||
}
|
||||
} else if (current_return_type != TYPE_VOID) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
"函数应返回值类型 '%s'", type_name(current_return_type));
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"函数应返回值类型 '%s'",
|
||||
current_return_struct_name ? current_return_struct_name : type_name(current_return_type));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -460,13 +502,13 @@ void sema_analyze(AstNode* ast, ErrorList* errors, Arena* arena) {
|
||||
|
||||
// 注册内置函数
|
||||
TypeKind params_i64[] = {TYPE_I64};
|
||||
scope_insert_function(global_scope, arena, "print_i64", TYPE_VOID, params_i64, 1);
|
||||
scope_insert_function(global_scope, arena, "print_i64", TYPE_VOID, NULL, params_i64, NULL, 1);
|
||||
TypeKind params_f64[] = {TYPE_F64};
|
||||
scope_insert_function(global_scope, arena, "print_f64", TYPE_VOID, params_f64, 1);
|
||||
scope_insert_function(global_scope, arena, "print_f64", TYPE_VOID, NULL, params_f64, NULL, 1);
|
||||
TypeKind params_bool[] = {TYPE_BOOL};
|
||||
scope_insert_function(global_scope, arena, "print_bool", TYPE_VOID, params_bool, 1);
|
||||
scope_insert_function(global_scope, arena, "print_bool", TYPE_VOID, NULL, params_bool, NULL, 1);
|
||||
TypeKind params_str[] = {TYPE_STR};
|
||||
scope_insert_function(global_scope, arena, "print_str", TYPE_VOID, params_str, 1);
|
||||
scope_insert_function(global_scope, arena, "print_str", TYPE_VOID, NULL, params_str, NULL, 1);
|
||||
|
||||
analyze_node(ast, global_scope, errors, arena);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user