diff --git a/src/ast/ast.c b/src/ast/ast.c index 18d8db6..c6541dc 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -41,6 +41,9 @@ AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size n->as.function.is_pub = is_pub; n->as.function.type_params = type_params; n->as.function.type_param_count = tp_count; + n->as.function.multi_ret_types = NULL; + n->as.function.multi_ret_snames = NULL; + n->as.function.multi_ret_count = 0; return n; } diff --git a/src/ast/ast.h b/src/ast/ast.h index 5e2422e..aa4b9dc 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -71,7 +71,8 @@ struct AstNode { struct { const char* name; struct AstNode** params; size_t param_count; TypeKind return_type; const char* return_struct_type_name; struct AstNode* body; bool is_pub; - const char** type_params; size_t type_param_count; } function; + const char** type_params; size_t type_param_count; + TypeKind* multi_ret_types; const char** multi_ret_snames; size_t multi_ret_count; } function; // AST_PARAMETER (也用作结构体字段: name + type) struct { const char* name; TypeKind type; const char* struct_type_name; } parameter; // AST_BLOCK diff --git a/src/parser/parser.c b/src/parser/parser.c index 4a6c76a..de95cd0 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -4,6 +4,9 @@ #include #include +// 当前解析的函数的多返回值 struct 名 (用于 return 语句) +static const char* current_multi_ret_name = NULL; + // === 结构体声明解析 === AstNode* parse_struct_decl(Parser* p, ErrorInfo* error) { const Token* s_tok = advance(p); // 跳过 'struct' @@ -195,8 +198,30 @@ AstNode* parse_statement(Parser* p, ErrorInfo* error) { if (t->kind == TOK_RETURN) { advance(p); - if (match(p, TOK_SEMICOLON)) { + if (match(p, TOK_SEMICOLON)) return ast_make_return(p->arena, NULL, tok_loc(t)); + // 多返回值: return (e1, e2, ...) + if (current_multi_ret_name && peek(p)->kind == TOK_LPAREN) { + advance(p); // 跳过 '(' + AstNode* vals[8]; int vcount = 0; + while (peek(p)->kind != TOK_RPAREN && !error->message) { + if (vcount >= 8) { error->message = "返回表达式过多(最多8)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; } + vals[vcount++] = parse_expr(p, error); + if (!vals[vcount-1]) return NULL; + if (peek(p)->kind == TOK_COMMA) advance(p); else break; + } + if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL; + if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL; + // 创建 struct init: __ret_funcname { _0: v0, _1: v1, ... } + const char** fnames = arena_alloc_impl(p->arena, vcount * sizeof(const char*)); + for (int i = 0; i < vcount; i++) { + char fbuf[4]; snprintf(fbuf, sizeof(fbuf), "_%d", i); + fnames[i] = arena_strdup_impl(p->arena, fbuf, strlen(fbuf)); + } + AstNode** varr = arena_alloc_impl(p->arena, vcount * sizeof(AstNode*)); + memcpy(varr, vals, vcount * sizeof(AstNode*)); + AstNode* init = ast_make_struct_init(p->arena, current_multi_ret_name, fnames, varr, vcount, tok_loc(t)); + return ast_make_return(p->arena, init, tok_loc(t)); } AstNode* expr = parse_expr(p, error); if (!expr) return NULL; @@ -327,22 +352,63 @@ AstNode* parse_function(Parser* p, bool is_pub, ErrorInfo* error) { } if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL; + // 多返回值 + TypeKind* multi_ret_types = NULL; + const char** multi_ret_snames = NULL; + size_t multi_ret_count = 0; // 返回类型 TypeKind ret = TYPE_VOID; const char* ret_struct_name = NULL; if (match(p, TOK_ARROW)) { - TypeInfo rti = parse_type_expr(p, error); - if (rti.kind == TYPE_ERROR) return NULL; - ret = rti.kind; - ret_struct_name = rti.struct_name; + // 多返回值: -> (T1, T2, ...) + if (peek(p)->kind == TOK_LPAREN) { + advance(p); // 跳过 '(' + TypeKind ttypes[8]; const char* tstructs[8]; int tcount = 0; + while (peek(p)->kind != TOK_RPAREN && !error->message) { + if (tcount >= 8) { error->message = "返回类型过多(最多8)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; } + TypeInfo ti = parse_type_expr(p, error); + if (ti.kind == TYPE_ERROR) return NULL; + ttypes[tcount] = ti.kind; + tstructs[tcount] = ti.struct_name; + tcount++; + if (peek(p)->kind == TOK_COMMA) advance(p); else break; + } + if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL; + if (tcount == 0) { error->message = "返回元组不能为空"; error->filename = p->filename; return NULL; } + if (tcount == 1) { + ret = ttypes[0]; ret_struct_name = tstructs[0]; + } else { + // 生成隐式 struct 名: __ret_ + size_t nlen = name->length; + char* sname = arena_alloc_impl(p->arena, nlen + 7); + memcpy(sname, "__ret_", 6); + memcpy(sname + 6, name->start, nlen); + sname[nlen + 6] = '\0'; + ret_struct_name = sname; + ret = TYPE_STRUCT; + // 暂存多返回类型, parse() 中创建隐式 struct + multi_ret_types = arena_alloc_impl(p->arena, tcount * sizeof(TypeKind)); + memcpy(multi_ret_types, ttypes, tcount * sizeof(TypeKind)); + multi_ret_snames = arena_alloc_impl(p->arena, tcount * sizeof(const char*)); + memcpy(multi_ret_snames, tstructs, tcount * sizeof(const char*)); + multi_ret_count = tcount; + } + } else { + TypeInfo rti = parse_type_expr(p, error); + if (rti.kind == TYPE_ERROR) return NULL; + ret = rti.kind; + ret_struct_name = rti.struct_name; + } } // trait 方法签名或普通函数体 AstNode* body = NULL; if (match(p, TOK_SEMICOLON)) { - body = NULL; // trait 方法签名,无实现 + body = NULL; } else { + current_multi_ret_name = (multi_ret_count > 0) ? ret_struct_name : NULL; body = parse_block(p, error); + current_multi_ret_name = NULL; if (!body) return NULL; } @@ -353,9 +419,15 @@ AstNode* parse_function(Parser* p, bool is_pub, ErrorInfo* error) { tparr = arena_alloc_impl(p->arena, tp_count * sizeof(const char*)); memcpy(tparr, type_params, tp_count * sizeof(const char*)); } - return ast_make_function(p->arena, + AstNode* fn = ast_make_function(p->arena, arena_strdup_impl(p->arena, name->start, name->length), parr, pcount, ret, ret_struct_name, body, is_pub, tparr, tp_count, tok_loc(fn_tok)); + if (multi_ret_count > 0) { + fn->as.function.multi_ret_types = multi_ret_types; + fn->as.function.multi_ret_snames = multi_ret_snames; + fn->as.function.multi_ret_count = multi_ret_count; + } + return fn; } // === 模块文件加载 === @@ -402,6 +474,7 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count, const char* filename, ErrorInfo* error) { Parser p = {.tokens = tokens, .count = count, .pos = 0, .filename = filename, .arena = a}; + current_multi_ret_name = NULL; AstNode* functions[256]; int fn_count = 0; AstNode* structs[64]; int struct_count = 0; AstNode* aliases[64]; int alias_count = 0; @@ -605,7 +678,25 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count, } } 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; } - functions[fn_count++] = parse_function(&p, is_pub, error); + AstNode* fn = parse_function(&p, is_pub, error); + if (!fn) return NULL; + // 多返回值: 注册隐式 struct + if (fn->as.function.multi_ret_count > 0) { + size_t mc = fn->as.function.multi_ret_count; + AstNode** flds = arena_alloc_impl(p.arena, mc * sizeof(AstNode*)); + for (size_t i = 0; i < mc; i++) { + char fbuf[4]; snprintf(fbuf, sizeof(fbuf), "_%zu", i); + flds[i] = ast_make_parameter(p.arena, + arena_strdup_impl(p.arena, fbuf, strlen(fbuf)), + fn->as.function.multi_ret_types[i], + fn->as.function.multi_ret_snames[i], + tok_loc(peek(&p))); + } + if (struct_count >= 64) { error->message = "结构体过多"; return NULL; } + structs[struct_count++] = ast_make_struct_decl(p.arena, + fn->as.function.return_struct_type_name, flds, mc, fn->loc); + } + functions[fn_count++] = fn; } else { error->message = "顶层只允许 fn、struct、type、enum、extend、mod 或 use"; error->filename = p.filename; diff --git a/test/programs/40_multi_ret.l b/test/programs/40_multi_ret.l new file mode 100644 index 0000000..eee841b --- /dev/null +++ b/test/programs/40_multi_ret.l @@ -0,0 +1,10 @@ +fn div_mod(a: i64, b: i64) -> (i64, i64) { + return (a / b, a % b); +} + +fn main() -> i64 { + let result = div_mod(10, 3); + print_i64(result._0); // 3 + print_i64(result._1); // 1 + return 0; +}