diff options
Diffstat (limited to 'src/parser/parser_struct.c')
| -rw-r--r-- | src/parser/parser_struct.c | 120 |
1 files changed, 113 insertions, 7 deletions
diff --git a/src/parser/parser_struct.c b/src/parser/parser_struct.c index 7dea30c..cbe34c0 100644 --- a/src/parser/parser_struct.c +++ b/src/parser/parser_struct.c @@ -187,6 +187,19 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) Token t2 = lexer_next(l); char *name2 = token_strdup(t2); + char *target_gen_param = NULL; + if (lexer_peek(l).type == TOK_LANGLE) + { + lexer_next(l); // eat < + Token gt = lexer_next(l); + target_gen_param = token_strdup(gt); + if (lexer_next(l).type != TOK_RANGLE) + { + zpanic_at(lexer_peek(l), "Expected > in impl struct generic"); + } + register_generic(ctx, target_gen_param); + } + register_impl(ctx, name1, name2); // RAII: Check for "Drop" trait implementation @@ -231,6 +244,18 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) lexer_next(l); // eat { ASTNode *h = 0, *tl = 0; + + char *full_target_name = name2; + if (target_gen_param) + { + full_target_name = xmalloc(strlen(name2) + strlen(target_gen_param) + 3); + sprintf(full_target_name, "%s<%s>", name2, target_gen_param); + } + else + { + full_target_name = xstrdup(name2); + } + while (1) { skip_comments(l); @@ -247,7 +272,9 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) sprintf(mangled, "%s__%s_%s", name2, name1, f->func.name); free(f->func.name); f->func.name = mangled; - char *na = patch_self_args(f->func.args, name2); + + // Use full_target_name (Vec<T>) for self patching + char *na = patch_self_args(f->func.args, full_target_name); free(f->func.args); f->func.args = na; @@ -286,7 +313,8 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) sprintf(mangled, "%s__%s_%s", name2, name1, f->func.name); free(f->func.name); f->func.name = mangled; - char *na = patch_self_args(f->func.args, name2); + + char *na = patch_self_args(f->func.args, full_target_name); free(f->func.args); f->func.args = na; @@ -322,6 +350,16 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) lexer_next(l); } } + + if (target_gen_param) + { + free(full_target_name); + } + else + { + free(full_target_name); // It was strdup/ref. Wait, xstrdup needs free. + } + ctx->current_impl_struct = NULL; // Restore context ASTNode *n = ast_create(NODE_IMPL_TRAIT); n->impl_trait.trait_name = name1; @@ -331,11 +369,15 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) // If target struct is generic, register this impl as a template ASTNode *def = find_struct_def(ctx, name2); - if (def && ((def->type == NODE_STRUCT && def->strct.is_template) || - (def->type == NODE_ENUM && def->enm.is_template))) + if (target_gen_param || (def && ((def->type == NODE_STRUCT && def->strct.is_template) || + (def->type == NODE_ENUM && def->enm.is_template)))) { const char *gp = "T"; - if (def->type == NODE_STRUCT && def->strct.generic_param_count > 0) + if (target_gen_param) + { + gp = target_gen_param; + } + else if (def && def->type == NODE_STRUCT && def->strct.generic_param_count > 0) { gp = def->strct.generic_params[0]; } @@ -347,6 +389,10 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) { ctx->known_generics_count--; } + if (target_gen_param) + { + ctx->known_generics_count--; + } return n; } else @@ -935,8 +981,50 @@ ASTNode *parse_enum(ParserContext *ctx, Lexer *l) Type *payload = NULL; if (lexer_peek(l).type == TOK_LPAREN) { - lexer_next(l); - payload = parse_type_obj(ctx, l); + lexer_next(l); // eat ( + Type *first_t = parse_type_obj(ctx, l); + + if (lexer_peek(l).type == TOK_COMMA) + { + // Multi-arg variant -> Tuple + char sig[512]; + sig[0] = 0; + + char *s = type_to_string(first_t); + if (strlen(s) > 250) + { // Safety check + zpanic_at(lexer_peek(l), "Type name too long for tuple generation"); + } + strcpy(sig, s); + free(s); + + while (lexer_peek(l).type == TOK_COMMA) + { + lexer_next(l); // eat , + strcat(sig, "_"); + Type *next_t = parse_type_obj(ctx, l); + char *ns = type_to_string(next_t); + if (strlen(sig) + strlen(ns) + 2 > 510) + { + zpanic_at(lexer_peek(l), "Tuple signature too long"); + } + strcat(sig, ns); + free(ns); + } + + register_tuple(ctx, sig); + + char *tuple_name = xmalloc(strlen(sig) + 7); + sprintf(tuple_name, "Tuple_%s", sig); + + payload = type_new(TYPE_STRUCT); + payload->name = tuple_name; + } + else + { + payload = first_t; + } + if (lexer_next(l).type != TOK_RPAREN) { zpanic_at(lexer_peek(l), "Expected )"); @@ -953,6 +1041,24 @@ ASTNode *parse_enum(ParserContext *ctx, Lexer *l) sprintf(mangled, "%s_%s", ename, vname); register_enum_variant(ctx, ename, mangled, va->variant.tag_id); + // Register Constructor Function Signature + if (payload && !gp) // Only for non-generic enums for now + { + Type **at = xmalloc(sizeof(Type *)); + at[0] = payload; + Type *ret_t = type_new(TYPE_ENUM); + ret_t->name = xstrdup(ename); + + register_func(ctx, mangled, 1, NULL, at, ret_t, 0, 0, vt); + } + else if (!gp) + { + // No payload: fn Name() -> Enum + Type *ret_t = type_new(TYPE_ENUM); + ret_t->name = xstrdup(ename); + register_func(ctx, mangled, 0, NULL, NULL, ret_t, 0, 0, vt); + } + // Handle explicit assignment: Ok = 5 if (lexer_peek(l).type == TOK_OP && *lexer_peek(l).start == '=') { |
