summaryrefslogtreecommitdiff
path: root/src/parser/parser_type.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/parser_type.c')
-rw-r--r--src/parser/parser_type.c105
1 files changed, 80 insertions, 25 deletions
diff --git a/src/parser/parser_type.c b/src/parser/parser_type.c
index 3b4abf3..7dded00 100644
--- a/src/parser/parser_type.c
+++ b/src/parser/parser_type.c
@@ -382,44 +382,99 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l)
Type *ty = type_new(TYPE_STRUCT);
ty->name = name;
- // Handle Generics <T>
+ // Handle Generics <T> or <K, V>
if (lexer_peek(l).type == TOK_LANGLE)
{
lexer_next(l); // eat <
- Type *arg = parse_type_formal(ctx, l);
+ Type *first_arg = parse_type_formal(ctx, l);
+ char *first_arg_str = type_to_string(first_arg);
- // Handle nested generics like Vec<Vec<int>> where >> is tokenized as one
- // op
+ // Check for multi-arg: <K, V>
Token next_tok = lexer_peek(l);
- if (next_tok.type == TOK_RANGLE)
- {
- lexer_next(l); // Consume >
- }
- else if (next_tok.type == TOK_OP && next_tok.len == 2 &&
- strncmp(next_tok.start, ">>", 2) == 0)
+ if (next_tok.type == TOK_COMMA)
{
- // Split >> into two > tokens
- // Consume the first > by advancing lexer manually
- l->pos += 1;
- l->col += 1;
+ // Multi-arg case
+ char **args = xmalloc(sizeof(char *) * 8);
+ int arg_count = 0;
+ args[arg_count++] = xstrdup(first_arg_str);
+
+ while (lexer_peek(l).type == TOK_COMMA)
+ {
+ lexer_next(l); // eat ,
+ Type *arg = parse_type_formal(ctx, l);
+ char *arg_str = type_to_string(arg);
+ args = realloc(args, sizeof(char *) * (arg_count + 1));
+ args[arg_count++] = xstrdup(arg_str);
+ free(arg_str);
+ }
+
+ // Consume >
+ next_tok = lexer_peek(l);
+ if (next_tok.type == TOK_RANGLE)
+ {
+ lexer_next(l);
+ }
+ else if (next_tok.type == TOK_OP && next_tok.len == 2 &&
+ strncmp(next_tok.start, ">>", 2) == 0)
+ {
+ l->pos += 1;
+ l->col += 1;
+ }
+ else
+ {
+ zpanic_at(t, "Expected > after generic");
+ }
+
+ // Call multi-arg instantiation
+ instantiate_generic_multi(ctx, name, args, arg_count, t);
+
+ // Build mangled name
+ char mangled[256];
+ strcpy(mangled, name);
+ for (int i = 0; i < arg_count; i++)
+ {
+ char *clean = sanitize_mangled_name(args[i]);
+ strcat(mangled, "_");
+ strcat(mangled, clean);
+ free(clean);
+ free(args[i]);
+ }
+ free(args);
+
+ free(ty->name);
+ ty->name = xstrdup(mangled);
}
else
{
- zpanic_at(t, "Expected > after generic");
- }
+ // Single-arg case - PRESERVE ORIGINAL FLOW EXACTLY
+ if (next_tok.type == TOK_RANGLE)
+ {
+ lexer_next(l); // Consume >
+ }
+ else if (next_tok.type == TOK_OP && next_tok.len == 2 &&
+ strncmp(next_tok.start, ">>", 2) == 0)
+ {
+ // Split >> into two > tokens
+ l->pos += 1;
+ l->col += 1;
+ }
+ else
+ {
+ zpanic_at(t, "Expected > after generic");
+ }
- char *arg_str = type_to_string(arg);
- instantiate_generic(ctx, name, arg_str, t);
+ instantiate_generic(ctx, name, first_arg_str, t);
- char *clean_arg = sanitize_mangled_name(arg_str);
- char mangled[256];
- sprintf(mangled, "%s_%s", name, clean_arg);
- free(clean_arg);
+ char *clean_arg = sanitize_mangled_name(first_arg_str);
+ char mangled[256];
+ sprintf(mangled, "%s_%s", name, clean_arg);
+ free(clean_arg);
- free(ty->name);
- ty->name = xstrdup(mangled);
- free(arg_str);
+ free(ty->name);
+ ty->name = xstrdup(mangled);
+ }
+ free(first_arg_str);
ty->kind = TYPE_STRUCT;
ty->args = NULL;
ty->arg_count = 0;