summaryrefslogtreecommitdiff
path: root/src/parser/parser_stmt.c
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-16 21:22:20 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-16 21:22:20 +0000
commita5d5a97818fb4fbd26c4fb25a5c410b1a60a1b18 (patch)
tree41b4fa9a4952db1496127031f22de988b7d45418 /src/parser/parser_stmt.c
parent73d0a63df903445ecd32f5b95bb3ff34e3dc2976 (diff)
Added multi-type generics support.
Diffstat (limited to 'src/parser/parser_stmt.c')
-rw-r--r--src/parser/parser_stmt.c57
1 files changed, 36 insertions, 21 deletions
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c
index f391f97..ac2d622 100644
--- a/src/parser/parser_stmt.c
+++ b/src/parser/parser_stmt.c
@@ -3238,14 +3238,33 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union)
Token n = lexer_next(l);
char *name = token_strdup(n);
- // Generic Param <T>
- char *gp = NULL;
+ // Generic Params <T> or <K, V>
+ char **gps = NULL;
+ int gp_count = 0;
if (lexer_peek(l).type == TOK_LANGLE)
{
- lexer_next(l);
- Token g = lexer_next(l);
- gp = token_strdup(g);
- lexer_next(l);
+ lexer_next(l); // eat <
+ while (1)
+ {
+ Token g = lexer_next(l);
+ gps = realloc(gps, sizeof(char *) * (gp_count + 1));
+ gps[gp_count++] = token_strdup(g);
+
+ Token next = lexer_peek(l);
+ if (next.type == TOK_COMMA)
+ {
+ lexer_next(l); // eat ,
+ }
+ else if (next.type == TOK_RANGLE)
+ {
+ lexer_next(l); // eat >
+ break;
+ }
+ else
+ {
+ zpanic_at(next, "Expected ',' or '>' in generic parameter list");
+ }
+ }
register_generic(ctx, name);
}
@@ -3255,16 +3274,13 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union)
lexer_next(l);
ASTNode *n = ast_create(NODE_STRUCT);
n->strct.name = name;
- n->strct.is_template = (gp != NULL);
- n->strct.generic_param = gp;
+ n->strct.is_template = (gp_count > 0);
+ n->strct.generic_params = gps;
+ n->strct.generic_param_count = gp_count;
n->strct.is_union = is_union;
n->strct.fields = NULL;
n->strct.is_incomplete = 1;
- if (!gp)
- {
- add_to_struct_list(ctx, n);
- }
return n;
}
@@ -3390,7 +3406,7 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union)
add_to_struct_list(ctx, node);
// Auto-prefix struct name if in module context
- if (ctx->current_module_prefix && !gp)
+ if (ctx->current_module_prefix && gp_count == 0)
{ // Don't prefix generic templates
char *prefixed_name = xmalloc(strlen(ctx->current_module_prefix) + strlen(name) + 2);
sprintf(prefixed_name, "%s_%s", ctx->current_module_prefix, name);
@@ -3403,24 +3419,25 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union)
// Initialize Type Info so we can track traits (like Drop)
node->type_info = type_new(TYPE_STRUCT);
node->type_info->name = xstrdup(name);
- if (gp)
+ if (gp_count > 0)
{
node->type_info->kind = TYPE_GENERIC;
// TODO: track generic params
}
node->strct.fields = h;
- node->strct.generic_param = gp;
+ node->strct.generic_params = gps;
+ node->strct.generic_param_count = gp_count;
node->strct.is_union = is_union;
- if (gp)
+ if (gp_count > 0)
{
node->strct.is_template = 1;
register_template(ctx, name, node);
}
// Register definition for 'use' lookups and LSP
- if (!gp)
+ if (gp_count == 0)
{
register_struct_def(ctx, name, node);
}
@@ -3430,10 +3447,10 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union)
Type *parse_type_obj(ParserContext *ctx, Lexer *l)
{
- // 1. Parse the base type (int, U32, MyStruct, etc.)
+ // Parse the base type (int, U32, MyStruct, etc.)
Type *t = parse_type_base(ctx, l);
- // 2. Handle Pointers (e.g. int***)
+ // Handle Pointers
while (lexer_peek(l).type == TOK_OP && lexer_peek(l).start[0] == '*')
{
lexer_next(l); // eat *
@@ -3443,8 +3460,6 @@ Type *parse_type_obj(ParserContext *ctx, Lexer *l)
t = ptr;
}
- // (Optional: You can add array parsing here later if needed)
-
return t;
}