diff options
Diffstat (limited to 'src/parser')
| -rw-r--r-- | src/parser/parser_decl.c | 30 | ||||
| -rw-r--r-- | src/parser/parser_expr.c | 56 | ||||
| -rw-r--r-- | src/parser/parser_struct.c | 56 |
3 files changed, 126 insertions, 16 deletions
diff --git a/src/parser/parser_decl.c b/src/parser/parser_decl.c index bd56350..5d5af1e 100644 --- a/src/parser/parser_decl.c +++ b/src/parser/parser_decl.c @@ -207,17 +207,43 @@ char *patch_self_args(const char *args, const char *struct_name) { return NULL; } - char *new_args = xmalloc(strlen(args) + strlen(struct_name) + 10); + + // Sanitize struct name for C usage (Vec<T> -> Vec_T) + char *safe_name = xmalloc(strlen(struct_name) + 1); + int j = 0; + for (int i = 0; struct_name[i]; i++) + { + if (struct_name[i] == '<') + { + safe_name[j++] = '_'; + } + else if (struct_name[i] == '>') + { + // skip + } + else if (struct_name[i] == ' ') + { + // skip + } + else + { + safe_name[j++] = struct_name[i]; + } + } + safe_name[j] = 0; + + char *new_args = xmalloc(strlen(args) + strlen(safe_name) + 10); // Check if it starts with "void* self" if (strncmp(args, "void* self", 10) == 0) { - sprintf(new_args, "%s* self%s", struct_name, args + 10); + sprintf(new_args, "%s* self%s", safe_name, args + 10); } else { strcpy(new_args, args); } + free(safe_name); return new_args; } // Helper for Value-Returning Defer diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index 07f133e..b07b544 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -1646,13 +1646,59 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) v = v->next; } } + int resolved = 0; if (is_variant) { sprintf(tmp, "%s_%.*s", acc, suffix.len, suffix.start); + resolved = 1; } else { - sprintf(tmp, "%s__%.*s", acc, suffix.len, suffix.start); + char inherent_name[256]; + sprintf(inherent_name, "%s__%.*s", acc, suffix.len, + suffix.start); + + if (find_func(ctx, inherent_name)) + { + strcpy(tmp, inherent_name); + resolved = 1; + } + else + { + GenericImplTemplate *it = ctx->impl_templates; + while (it) + { + if (strcmp(it->struct_name, gname) == 0) + { + char *tname = NULL; + if (it->impl_node && + it->impl_node->type == NODE_IMPL_TRAIT) + { + tname = it->impl_node->impl_trait + .trait_name; + } + if (tname) + { + char cand[512]; + sprintf(cand, "%s__%s_%.*s", acc, tname, + suffix.len, suffix.start); + + if (find_func(ctx, cand)) + { + strcpy(tmp, cand); + resolved = 1; + break; + } + } + } + it = it->next; + } + } + if (!resolved) + { + sprintf(tmp, "%s__%.*s", acc, suffix.len, + suffix.start); + } } handled_as_generic = 1; break; // Found and handled @@ -5588,14 +5634,6 @@ ASTNode *parse_arrow_lambda_single(ParserContext *ctx, Lexer *l, char *param_nam } t->inner = ret_val->type_info; } - else - { - if (param_name[0] == 'x') - { - fprintf(stderr, "DEBUG: Return type unknown/null! ret=%p kind=%d\n", - ret_val->type_info, ret_val->type_info ? ret_val->type_info->kind : -1); - } - } } // Update parameter types from symbol table (in case inference happened) diff --git a/src/parser/parser_struct.c b/src/parser/parser_struct.c index 3e5c73d..8eed017 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 |
