feat: 模块系统 mod + pub — 多文件编译支持

This commit is contained in:
2026-06-06 16:09:30 +08:00
parent e02cc7b1d6
commit fa734b8a23
9 changed files with 197 additions and 22 deletions
+17 -1
View File
@@ -30,12 +30,14 @@ AstNode* ast_make_program(void* alloc, AstNode** fns, size_t fn_count,
} }
AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size_t pcount, AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size_t pcount,
TypeKind ret, const char* ret_struct_name, AstNode* body, SourceLoc loc) { TypeKind ret, const char* ret_struct_name, AstNode* body,
bool is_pub, SourceLoc loc) {
NEW(alloc, AST_FUNCTION); NEW(alloc, AST_FUNCTION);
n->as.function.name = name; n->as.function.params = params; n->as.function.name = name; n->as.function.params = params;
n->as.function.param_count = pcount; n->as.function.return_type = ret; n->as.function.param_count = pcount; n->as.function.return_type = ret;
n->as.function.return_struct_type_name = ret_struct_name; n->as.function.return_struct_type_name = ret_struct_name;
n->as.function.body = body; n->as.function.body = body;
n->as.function.is_pub = is_pub;
return n; return n;
} }
@@ -255,3 +257,17 @@ AstNode* ast_make_method_call(void* alloc, AstNode* receiver, const char* method
n->as.method_call.arg_count = count; n->as.method_call.arg_count = count;
return n; return n;
} }
AstNode* ast_make_mod_decl(void* alloc, const char* name, AstNode* sub_ast, SourceLoc loc) {
NEW(alloc, AST_MOD_DECL);
n->as.mod_decl.name = name;
n->as.mod_decl.ast = sub_ast;
return n;
}
AstNode* ast_make_use_decl(void* alloc, const char* path, const char* item, SourceLoc loc) {
NEW(alloc, AST_USE_DECL);
n->as.use_decl.path = path;
n->as.use_decl.item = item;
return n;
}
+11 -2
View File
@@ -30,6 +30,8 @@ typedef enum {
AST_ARRAY_ASSIGN_STMT,// arr[i] = expr AST_ARRAY_ASSIGN_STMT,// arr[i] = expr
AST_IMPL_BLOCK, // impl StructName { fn method(...) ... } AST_IMPL_BLOCK, // impl StructName { fn method(...) ... }
AST_METHOD_CALL, // receiver.method(args) AST_METHOD_CALL, // receiver.method(args)
AST_MOD_DECL, // mod foo;
AST_USE_DECL, // use foo::bar;
} AstKind; } AstKind;
typedef enum { typedef enum {
@@ -65,7 +67,7 @@ struct AstNode {
// AST_FUNCTION // AST_FUNCTION
struct { const char* name; struct AstNode** params; size_t param_count; struct { const char* name; struct AstNode** params; size_t param_count;
TypeKind return_type; const char* return_struct_type_name; TypeKind return_type; const char* return_struct_type_name;
struct AstNode* body; } function; struct AstNode* body; bool is_pub; } function;
// AST_PARAMETER (也用作结构体字段: name + type) // AST_PARAMETER (也用作结构体字段: name + type)
struct { const char* name; TypeKind type; const char* struct_type_name; } parameter; struct { const char* name; TypeKind type; const char* struct_type_name; } parameter;
// AST_BLOCK // AST_BLOCK
@@ -120,6 +122,10 @@ struct AstNode {
struct { const char* struct_name; struct AstNode** methods; size_t method_count; } impl_block; struct { const char* struct_name; struct AstNode** methods; size_t method_count; } impl_block;
// AST_METHOD_CALL // AST_METHOD_CALL
struct { struct AstNode* receiver; const char* method_name; struct AstNode** args; const char** arg_names; size_t arg_count; } method_call; struct { struct AstNode* receiver; const char* method_name; struct AstNode** args; const char** arg_names; size_t arg_count; } method_call;
// AST_MOD_DECL
struct { const char* name; struct AstNode* ast; } mod_decl;
// AST_USE_DECL
struct { const char* path; const char* item; } use_decl;
} as; } as;
}; };
@@ -130,7 +136,8 @@ AstNode* ast_make_program(void* alloc, AstNode** fns, size_t fn_count,
AstNode** enums, size_t enum_count, AstNode** enums, size_t enum_count,
AstNode** impls, size_t impl_count, SourceLoc loc); AstNode** impls, size_t impl_count, SourceLoc loc);
AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size_t pcount, AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size_t pcount,
TypeKind ret, const char* ret_struct_name, AstNode* body, SourceLoc loc); TypeKind ret, const char* ret_struct_name, AstNode* body,
bool is_pub, SourceLoc loc);
AstNode* ast_make_parameter(void* alloc, const char* name, TypeKind type, const char* struct_type_name, SourceLoc loc); AstNode* ast_make_parameter(void* alloc, const char* name, TypeKind type, const char* struct_type_name, SourceLoc loc);
AstNode* ast_make_block(void* alloc, AstNode** stmts, size_t count, SourceLoc loc); AstNode* ast_make_block(void* alloc, AstNode** stmts, size_t count, SourceLoc loc);
AstNode* ast_make_let(void* alloc, const char* name, TypeKind annot_type, bool has_type_annot, AstNode* ast_make_let(void* alloc, const char* name, TypeKind annot_type, bool has_type_annot,
@@ -164,5 +171,7 @@ AstNode* ast_make_index_expr(void* alloc, AstNode* array, AstNode* index, Source
AstNode* ast_make_array_assign(void* alloc, const char* name, AstNode* index, AstNode* value, SourceLoc loc); AstNode* ast_make_array_assign(void* alloc, const char* name, AstNode* index, AstNode* value, SourceLoc loc);
AstNode* ast_make_impl_block(void* alloc, const char* struct_name, AstNode** methods, size_t count, SourceLoc loc); AstNode* ast_make_impl_block(void* alloc, const char* struct_name, AstNode** methods, size_t count, SourceLoc loc);
AstNode* ast_make_method_call(void* alloc, AstNode* receiver, const char* method, AstNode** args, const char** arg_names, size_t count, SourceLoc loc); AstNode* ast_make_method_call(void* alloc, AstNode* receiver, const char* method, AstNode** args, const char** arg_names, size_t count, SourceLoc loc);
AstNode* ast_make_mod_decl(void* alloc, const char* name, AstNode* sub_ast, SourceLoc loc);
AstNode* ast_make_use_decl(void* alloc, const char* path, const char* item, SourceLoc loc);
#endif #endif
+1
View File
@@ -66,6 +66,7 @@ static TokenKind check_keyword(const Token* tok) {
KW("str", TOK_STR); KW("void", TOK_VOID); KW("str", TOK_STR); KW("void", TOK_VOID);
KW("struct", TOK_STRUCT); KW("type", TOK_TYPE); KW("struct", TOK_STRUCT); KW("type", TOK_TYPE);
KW("enum", TOK_ENUM); KW("extend", TOK_EXTEND); KW("match", TOK_MATCH); KW("enum", TOK_ENUM); KW("extend", TOK_EXTEND); KW("match", TOK_MATCH);
KW("pub", TOK_PUB); KW("mod", TOK_MOD); KW("use", TOK_USE);
KW("_", TOK_UNDERSCORE); KW("_", TOK_UNDERSCORE);
KW("true", TOK_TRUE); KW("false", TOK_FALSE); KW("true", TOK_TRUE); KW("false", TOK_FALSE);
#undef KW #undef KW
+1
View File
@@ -6,6 +6,7 @@
static const char* NAMES[] = { static const char* NAMES[] = {
[TOK_FN] = "fn", [TOK_LET] = "let", [TOK_VAR] = "var", [TOK_IF] = "if", [TOK_GUARD] = "guard", [TOK_FN] = "fn", [TOK_LET] = "let", [TOK_VAR] = "var", [TOK_IF] = "if", [TOK_GUARD] = "guard",
[TOK_PUB] = "pub", [TOK_MOD] = "mod", [TOK_USE] = "use",
[TOK_ELSE] = "else", [TOK_WHILE] = "while", [TOK_FOR] = "for", [TOK_IN] = "in", [TOK_RETURN] = "return", [TOK_ELSE] = "else", [TOK_WHILE] = "while", [TOK_FOR] = "for", [TOK_IN] = "in", [TOK_RETURN] = "return",
[TOK_STRUCT] = "struct", [TOK_TYPE] = "type", [TOK_ENUM] = "enum", [TOK_EXTEND] = "extend", [TOK_STRUCT] = "struct", [TOK_TYPE] = "type", [TOK_ENUM] = "enum", [TOK_EXTEND] = "extend",
[TOK_MATCH] = "match", [TOK_MATCH] = "match",
+1 -1
View File
@@ -7,7 +7,7 @@
typedef enum { typedef enum {
// 关键字 // 关键字
TOK_FN, TOK_LET, TOK_VAR, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN, TOK_GUARD, TOK_FN, TOK_LET, TOK_VAR, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN, TOK_GUARD,
TOK_STRUCT, TOK_TYPE, TOK_ENUM, TOK_EXTEND, TOK_MATCH, TOK_STRUCT, TOK_TYPE, TOK_ENUM, TOK_EXTEND, TOK_MATCH, TOK_PUB, TOK_MOD, TOK_USE,
// 类型关键字 // 类型关键字
TOK_I32, TOK_I64, TOK_U64, TOK_F64, TOK_BOOL, TOK_CHAR, TOK_STR, TOK_VOID, TOK_I32, TOK_I64, TOK_U64, TOK_F64, TOK_BOOL, TOK_CHAR, TOK_STR, TOK_VOID,
// 字面量 // 字面量
+145 -7
View File
@@ -1,4 +1,5 @@
#include "parser.h" #include "parser.h"
#include "lexer.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -72,7 +73,7 @@ static AstNode* parse_expr(Parser* p, ErrorInfo* error);
static AstNode* parse_expr_prec(Parser* p, Precedence prec, ErrorInfo* error); static AstNode* parse_expr_prec(Parser* p, Precedence prec, ErrorInfo* error);
static AstNode* parse_block(Parser* p, ErrorInfo* error); static AstNode* parse_block(Parser* p, ErrorInfo* error);
static AstNode* parse_statement(Parser* p, ErrorInfo* error); static AstNode* parse_statement(Parser* p, ErrorInfo* error);
static AstNode* parse_function(Parser* p, ErrorInfo* error); static AstNode* parse_function(Parser* p, bool is_pub, ErrorInfo* error);
// === 前缀解析 === // === 前缀解析 ===
static AstNode* parse_unary(Parser* p, ErrorInfo* error) { static AstNode* parse_unary(Parser* p, ErrorInfo* error) {
@@ -188,11 +189,56 @@ static AstNode* parse_struct_init(Parser* p, const Token* name, ErrorInfo* error
static AstNode* parse_ident_or_call(Parser* p, ErrorInfo* error) { static AstNode* parse_ident_or_call(Parser* p, ErrorInfo* error) {
const Token* name = advance(p); const Token* name = advance(p);
// 枚举变体引用: Name::Variant 或 Name::Variant(payload) // 枚举变体或模块函数: Name::Variant 或 Name::fn
if (peek(p)->kind == TOK_COLON_COLON) { if (peek(p)->kind == TOK_COLON_COLON) {
advance(p); // 跳过 :: advance(p); // 跳过 ::
const Token* variant = expect(p, TOK_IDENT, error, "枚举变体名"); const Token* variant = expect(p, TOK_IDENT, error, "枚举变体名");
if (!variant) return NULL; if (!variant) return NULL;
// Name::fn 或 Name::Variant 或 Name::Variant(payload)
if (peek(p)->kind == TOK_LPAREN) {
// 前进探测: 检查括号内是否有多参数或命名参数(→函数调用)还是单表达式(→枚举payload)
size_t probe = p->pos + 1;
int paren_depth = 1;
bool has_comma = false, has_named = false;
while (paren_depth > 0 && p->tokens[probe].kind != TOK_EOF) {
if (p->tokens[probe].kind == TOK_LPAREN) paren_depth++;
else if (p->tokens[probe].kind == TOK_RPAREN) { paren_depth--; if (paren_depth == 0) break; }
else if (paren_depth == 1 && p->tokens[probe].kind == TOK_COMMA) has_comma = true;
else if (paren_depth == 1 && p->tokens[probe].kind == TOK_COLON) has_named = true;
probe++;
}
if (has_comma || has_named) {
// 模块函数调用: Name::fn(a, b) 或 Name::fn(x: 1)
advance(p); // 跳过 '('
AstNode* args[16]; const char* arg_names[16]; int arg_count = 0;
bool seen_named = false;
while (peek(p)->kind != TOK_RPAREN && !error->message) {
if (arg_count >= 16) { error->message = "参数过多"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
if (peek(p)->kind == TOK_IDENT && (p->tokens[p->pos + 1].kind == TOK_COLON)) {
const Token* aname = advance(p); advance(p);
arg_names[arg_count] = arena_strdup_impl(p->arena, aname->start, aname->length);
seen_named = true;
} else {
if (seen_named) { error->message = "命名参数必须放在位置参数之后"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
arg_names[arg_count] = NULL;
}
args[arg_count] = parse_expr(p, error);
if (!args[arg_count]) return NULL;
arg_count++;
if (peek(p)->kind == TOK_COMMA) advance(p); else break;
}
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
AstNode** arg_arr = arena_alloc_impl(p->arena, arg_count * sizeof(AstNode*));
memcpy(arg_arr, args, arg_count * sizeof(AstNode*));
const char** name_arr = seen_named
? memcpy(arena_alloc_impl(p->arena, arg_count * sizeof(const char*)), arg_names, arg_count * sizeof(const char*))
: NULL;
char* full_name = arena_alloc_impl(p->arena, name->length + variant->length + 4);
sprintf(full_name, "%.*s::%.*s", name->length, name->start, variant->length, variant->start);
return ast_make_call(p->arena, full_name, arg_arr, name_arr, arg_count, tok_loc(name));
}
}
// 枚举 payload: Name::Variant 或 Name::Variant(expr)
AstNode* payload = NULL; AstNode* payload = NULL;
if (match(p, TOK_LPAREN)) { if (match(p, TOK_LPAREN)) {
payload = parse_expr(p, error); payload = parse_expr(p, error);
@@ -857,7 +903,7 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
} }
// === 函数解析 === // === 函数解析 ===
static AstNode* parse_function(Parser* p, ErrorInfo* error) { static AstNode* parse_function(Parser* p, bool is_pub, ErrorInfo* error) {
const Token* fn_tok = advance(p); // fn const Token* fn_tok = advance(p); // fn
const Token* name = expect(p, TOK_IDENT, error, "fn 后应为函数名"); const Token* name = expect(p, TOK_IDENT, error, "fn 后应为函数名");
if (!name) return NULL; if (!name) return NULL;
@@ -897,7 +943,51 @@ static AstNode* parse_function(Parser* p, ErrorInfo* error) {
memcpy(parr, params, pcount * sizeof(AstNode*)); memcpy(parr, params, pcount * sizeof(AstNode*));
return ast_make_function(p->arena, return ast_make_function(p->arena,
arena_strdup_impl(p->arena, name->start, name->length), arena_strdup_impl(p->arena, name->start, name->length),
parr, pcount, ret, ret_struct_name, body, tok_loc(fn_tok)); parr, pcount, ret, ret_struct_name, body, is_pub, tok_loc(fn_tok));
}
// === 模块文件加载辅助 ===
// parse 前向声明(定义在后面)
AstNode* parse(Arena* a, const Token* tokens, size_t count,
const char* filename, ErrorInfo* error);
static AstNode* load_module(Arena* a, const char* parent_file,
const char* mod_name, ErrorInfo* error) {
// 构造模块文件路径: 同目录下 mod_name.l
char mod_path[512];
const char* last_slash = strrchr(parent_file, '/');
const char* last_bs = strrchr(parent_file, '\\');
const char* dir_end = parent_file;
if (last_slash && last_slash > dir_end) dir_end = last_slash;
if (last_bs && last_bs > dir_end) dir_end = last_bs;
if (dir_end != parent_file) {
size_t dir_len = dir_end - parent_file + 1;
memcpy(mod_path, parent_file, dir_len);
snprintf(mod_path + dir_len, sizeof(mod_path) - dir_len, "%s.l", mod_name);
} else {
snprintf(mod_path, sizeof(mod_path), "%s.l", mod_name);
}
// 读取文件
FILE* f = fopen(mod_path, "rb");
if (!f) {
error->message = "无法打开模块文件"; error->filename = mod_path;
error->line = 0; error->col = 0;
return NULL;
}
fseek(f, 0, SEEK_END);
size_t sz = ftell(f); fseek(f, 0, SEEK_SET);
char* src = malloc(sz + 1);
if (!src) { fclose(f); return NULL; }
fread(src, 1, sz, f); src[sz] = '\0'; fclose(f);
size_t tc;
ErrorInfo lex_err = {0};
Token* toks = lex(a, src, mod_path, &tc, &lex_err);
free(src);
if (!toks) { *error = lex_err; return NULL; }
AstNode* ast = parse(a, toks, tc, mod_path, error);
return ast;
} }
// === 程序入口 === // === 程序入口 ===
@@ -910,7 +1000,14 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
AstNode* aliases[64]; int alias_count = 0; AstNode* aliases[64]; int alias_count = 0;
AstNode* enums[64]; int enum_count = 0; AstNode* enums[64]; int enum_count = 0;
AstNode* impls[64]; int impl_count = 0; AstNode* impls[64]; int impl_count = 0;
AstNode* mods[64]; int mod_count = 0;
AstNode* uses[64]; int use_count = 0;
while (peek(&p)->kind != TOK_EOF && !error->message) { while (peek(&p)->kind != TOK_EOF && !error->message) {
// pub 前缀
bool is_pub = false;
if (peek(&p)->kind == TOK_PUB) {
is_pub = true; advance(&p);
}
if (peek(&p)->kind == TOK_STRUCT) { if (peek(&p)->kind == TOK_STRUCT) {
if (struct_count >= 64) { error->message = "结构体过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } if (struct_count >= 64) { error->message = "结构体过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
structs[struct_count++] = parse_struct_decl(&p, error); structs[struct_count++] = parse_struct_decl(&p, error);
@@ -975,7 +1072,7 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
while (peek(&p)->kind != TOK_RBRACE && !error->message) { while (peek(&p)->kind != TOK_RBRACE && !error->message) {
if (mcount >= 64) { error->message = "方法过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } if (mcount >= 64) { error->message = "方法过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
if (peek(&p)->kind != TOK_FN) { error->message = "extend 块内只允许 fn"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } if (peek(&p)->kind != TOK_FN) { error->message = "extend 块内只允许 fn"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
methods[mcount++] = parse_function(&p, error); methods[mcount++] = parse_function(&p, false, error);
} }
if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL; if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
AstNode** m_arr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*)); AstNode** m_arr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*));
@@ -984,11 +1081,52 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
impls[impl_count++] = ast_make_impl_block(p.arena, impls[impl_count++] = ast_make_impl_block(p.arena,
arena_strdup_impl(p.arena, st_name->start, st_name->length), arena_strdup_impl(p.arena, st_name->start, st_name->length),
m_arr, mcount, tok_loc(i_tok)); m_arr, mcount, tok_loc(i_tok));
} else if (peek(&p)->kind == TOK_MOD) {
advance(&p);
const Token* mn = expect(&p, TOK_IDENT, error, "mod 后应为模块名");
if (!mn) return NULL;
if (!expect(&p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
const char* mod_name = arena_strdup_impl(p.arena, mn->start, mn->length);
AstNode* sub = load_module(a, filename, mod_name, error);
if (!sub) return NULL;
// 合并子模块项到当前文件(以 mod_name:: 为前缀)
for (size_t i = 0; i < sub->as.program.fn_count; i++) {
AstNode* fn = sub->as.program.functions[i];
if (fn->as.function.is_pub) {
char* mangled = arena_alloc_impl(p.arena, strlen(mod_name) + strlen(fn->as.function.name) + 4);
sprintf(mangled, "%s::%s", mod_name, fn->as.function.name);
fn->as.function.name = mangled;
if (fn_count >= 256) { error->message = "函数过多"; error->filename = p.filename; return NULL; }
functions[fn_count++] = fn;
}
}
for (size_t i = 0; i < sub->as.program.struct_count; i++) {
if (struct_count >= 64) break;
structs[struct_count++] = sub->as.program.structs[i];
}
for (size_t i = 0; i < sub->as.program.enum_count; i++) {
if (enum_count >= 64) break;
enums[enum_count++] = sub->as.program.enums[i];
}
if (mod_count < 64) mods[mod_count++] = ast_make_mod_decl(a, mod_name, sub, tok_loc(mn));
} else if (peek(&p)->kind == TOK_USE) {
advance(&p);
const Token* path_tok = expect(&p, TOK_IDENT, error, "use 后应为模块名");
if (!path_tok) return NULL;
if (!expect(&p, TOK_COLON_COLON, error, "缺少 '::'")) return NULL;
const Token* item_tok = expect(&p, TOK_IDENT, error, "use 后应为项目名");
if (!item_tok) return NULL;
if (!expect(&p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
if (use_count >= 64) { error->message = "use 过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
uses[use_count++] = ast_make_use_decl(a,
arena_strdup_impl(p.arena, path_tok->start, path_tok->length),
arena_strdup_impl(p.arena, item_tok->start, item_tok->length),
tok_loc(path_tok));
} else if (peek(&p)->kind == TOK_FN) { } else if (peek(&p)->kind == TOK_FN) {
if (fn_count >= 256) { error->message = "函数过多 (最多256)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } if (fn_count >= 256) { error->message = "函数过多 (最多256)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
functions[fn_count++] = parse_function(&p, error); functions[fn_count++] = parse_function(&p, is_pub, error);
} else { } else {
error->message = "顶层只允许 fn、struct、type、enumextend"; error->message = "顶层只允许 fn、struct、type、enumextend、mod 或 use";
error->filename = p.filename; error->filename = p.filename;
error->line = peek(&p)->line; error->line = peek(&p)->line;
error->col = peek(&p)->col; error->col = peek(&p)->col;
+7
View File
@@ -0,0 +1,7 @@
mod math_mod;
fn main() -> i64 {
let result = math_mod::add(3, 4);
print_i64(result); // 7
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
pub fn add(a: i64, b: i64) -> i64 {
return a + b;
}
+11 -11
View File
@@ -12,7 +12,7 @@ void test_codegen_simple_function() {
AstNode* ret = ast_make_return(&a, ast_make_literal_i64(&a, 42, loc_at(1, 1)), loc_at(1, 1)); AstNode* ret = ast_make_return(&a, ast_make_literal_i64(&a, 42, loc_at(1, 1)), loc_at(1, 1));
AstNode* stmts[] = { ret }; AstNode* stmts[] = { ret };
AstNode* body = ast_make_block(&a, stmts, 1, loc_at(1, 1)); AstNode* body = ast_make_block(&a, stmts, 1, loc_at(1, 1));
AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, loc_at(1, 1)); AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, false, loc_at(1, 1));
AstNode* fns[] = { fn }; AstNode* fns[] = { fn };
AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1));
@@ -46,7 +46,7 @@ void test_codegen_if_else() {
ast_make_literal_bool(&a, true, loc_at(1, 1)), then_block, else_block, loc_at(1, 1)); ast_make_literal_bool(&a, true, loc_at(1, 1)), then_block, else_block, loc_at(1, 1));
AstNode* stmts[] = { if_stmt }; AstNode* stmts[] = { if_stmt };
AstNode* body = ast_make_block(&a, stmts, 1, loc_at(1, 1)); AstNode* body = ast_make_block(&a, stmts, 1, loc_at(1, 1));
AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, loc_at(1, 1)); AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, false, loc_at(1, 1));
AstNode* fns[] = { fn }; AstNode* fns[] = { fn };
AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1));
@@ -77,7 +77,7 @@ void test_codegen_binary_ops() {
AstNode* ret = ast_make_return(&a, expr, loc_at(1, 1)); AstNode* ret = ast_make_return(&a, expr, loc_at(1, 1));
AstNode* stmts[] = { ret }; AstNode* stmts[] = { ret };
AstNode* body = ast_make_block(&a, stmts, 1, loc_at(1, 1)); AstNode* body = ast_make_block(&a, stmts, 1, loc_at(1, 1));
AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, loc_at(1, 1)); AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, false, loc_at(1, 1));
AstNode* fns[] = { fn }; AstNode* fns[] = { fn };
AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1));
@@ -107,7 +107,7 @@ void test_codegen_while_loop() {
AstNode* ret = ast_make_return(&a, ast_make_literal_i64(&a, 1, loc_at(1, 1)), loc_at(1, 1)); AstNode* ret = ast_make_return(&a, ast_make_literal_i64(&a, 1, loc_at(1, 1)), loc_at(1, 1));
AstNode* stmts[] = { while_stmt, ret }; AstNode* stmts[] = { while_stmt, ret };
AstNode* fn_body = ast_make_block(&a, stmts, 2, loc_at(1, 1)); AstNode* fn_body = ast_make_block(&a, stmts, 2, loc_at(1, 1));
AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, fn_body, loc_at(1, 1)); AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, fn_body, false, loc_at(1, 1));
AstNode* fns[] = { fn }; AstNode* fns[] = { fn };
AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1));
@@ -160,7 +160,7 @@ void test_codegen_struct_decl() {
AstNode* ret = ast_make_return(&a, field_x, loc_at(1, 1)); AstNode* ret = ast_make_return(&a, field_x, loc_at(1, 1));
AstNode* stmts[] = { let_stmt, ret }; AstNode* stmts[] = { let_stmt, ret };
AstNode* body = ast_make_block(&a, stmts, 2, loc_at(1, 1)); AstNode* body = ast_make_block(&a, stmts, 2, loc_at(1, 1));
AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, loc_at(1, 1)); AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, false, loc_at(1, 1));
AstNode* fns[] = { fn }; AstNode* fns[] = { fn };
AstNode* prog = ast_make_program(&a, fns, 1, structs, 1, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, structs, 1, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1));
@@ -215,7 +215,7 @@ void test_codegen_struct_field_access() {
AstNode* ret = ast_make_return(&a, field_y, loc_at(1, 1)); AstNode* ret = ast_make_return(&a, field_y, loc_at(1, 1));
AstNode* stmts[] = { let_stmt, ret }; AstNode* stmts[] = { let_stmt, ret };
AstNode* body = ast_make_block(&a, stmts, 2, loc_at(1, 1)); AstNode* body = ast_make_block(&a, stmts, 2, loc_at(1, 1));
AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, loc_at(1, 1)); AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, false, loc_at(1, 1));
AstNode* fns[] = { fn }; AstNode* fns[] = { fn };
AstNode* prog = ast_make_program(&a, fns, 1, structs, 1, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, structs, 1, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1));
@@ -265,7 +265,7 @@ void test_codegen_enum() {
AstNode* stmts[] = { let_stmt, print_call, ret }; AstNode* stmts[] = { let_stmt, print_call, ret };
AstNode* body = ast_make_block(&a, stmts, 3, loc_at(1, 1)); AstNode* body = ast_make_block(&a, stmts, 3, loc_at(1, 1));
AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, loc_at(1, 1)); AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, false, loc_at(1, 1));
AstNode* fns[] = { fn }; AstNode* fns[] = { fn };
AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, enums, 1, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, enums, 1, NULL, 0, loc_at(1, 1));
@@ -330,7 +330,7 @@ void test_codegen_array() {
AstNode* stmts[] = { let_stmt, arr_assign, print_call, ret }; AstNode* stmts[] = { let_stmt, arr_assign, print_call, ret };
AstNode* body = ast_make_block(&a, stmts, 4, loc_at(1, 1)); AstNode* body = ast_make_block(&a, stmts, 4, loc_at(1, 1));
AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, loc_at(1, 1)); AstNode* fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, body, false, loc_at(1, 1));
AstNode* fns[] = { fn }; AstNode* fns[] = { fn };
AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1));
@@ -373,7 +373,7 @@ void test_codegen_method_call() {
AstNode* ret_body = ast_make_return(&a, field_x, loc_at(1, 1)); AstNode* ret_body = ast_make_return(&a, field_x, loc_at(1, 1));
AstNode* ret_stmts[] = { ret_body }; AstNode* ret_stmts[] = { ret_body };
AstNode* body = ast_make_block(&a, ret_stmts, 1, loc_at(1, 1)); AstNode* body = ast_make_block(&a, ret_stmts, 1, loc_at(1, 1));
AstNode* get_x_fn = ast_make_function(&a, "Point$get_x", params, 1, TYPE_I64, NULL, body, loc_at(1, 1)); AstNode* get_x_fn = ast_make_function(&a, "Point$get_x", params, 1, TYPE_I64, NULL, body, false, loc_at(1, 1));
/* fn main() -> i64 { /* fn main() -> i64 {
let p = Point { x: 42, y: 0 }; let p = Point { x: 42, y: 0 };
@@ -399,7 +399,7 @@ void test_codegen_method_call() {
AstNode* ret_main = ast_make_return(&a, method_call, loc_at(1, 1)); AstNode* ret_main = ast_make_return(&a, method_call, loc_at(1, 1));
AstNode* main_stmts[] = { let_stmt, ret_main }; AstNode* main_stmts[] = { let_stmt, ret_main };
AstNode* main_body = ast_make_block(&a, main_stmts, 2, loc_at(1, 1)); AstNode* main_body = ast_make_block(&a, main_stmts, 2, loc_at(1, 1));
AstNode* main_fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, main_body, loc_at(1, 1)); AstNode* main_fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, main_body, false, loc_at(1, 1));
AstNode* fns[] = { get_x_fn, main_fn }; AstNode* fns[] = { get_x_fn, main_fn };
AstNode* prog = ast_make_program(&a, fns, 2, structs, 1, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 2, structs, 1, NULL, 0, NULL, 0, NULL, 0, loc_at(1, 1));
@@ -486,7 +486,7 @@ void test_codegen_match() {
AstNode* main_stmts[] = { let_stmt, outer_if }; AstNode* main_stmts[] = { let_stmt, outer_if };
AstNode* main_body = ast_make_block(&a, main_stmts, 2, loc_at(1, 1)); AstNode* main_body = ast_make_block(&a, main_stmts, 2, loc_at(1, 1));
AstNode* main_fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, main_body, loc_at(1, 1)); AstNode* main_fn = ast_make_function(&a, "main", NULL, 0, TYPE_I64, NULL, main_body, false, loc_at(1, 1));
AstNode* fns[] = { main_fn }; AstNode* fns[] = { main_fn };
AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, enums, 1, NULL, 0, loc_at(1, 1)); AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, enums, 1, NULL, 0, loc_at(1, 1));