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-31 01:15:25 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-31 01:15:25 +0000
commit856c9fe56b412779e045ef86a767b93d5c7f563b (patch)
tree6f851bb9bf300970c4a0d7186db0de86e510a18d /src/parser/parser_stmt.c
parent03a6a57f500ee4230ce2cee887866b3850ed7ed9 (diff)
Improvements for slice + better iteration for arrays
Diffstat (limited to 'src/parser/parser_stmt.c')
-rw-r--r--src/parser/parser_stmt.c152
1 files changed, 139 insertions, 13 deletions
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c
index a471fe6..4c24de3 100644
--- a/src/parser/parser_stmt.c
+++ b/src/parser/parser_stmt.c
@@ -1133,6 +1133,7 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
ASTNode *obj_expr = start_expr;
char *iter_method = "iterator";
+ ASTNode *slice_decl = NULL; // Track if we need to add a slice declaration
// Check for reference iteration: for x in &vec
if (obj_expr->type == NODE_EXPR_UNARY && obj_expr->unary.op &&
@@ -1142,6 +1143,78 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
iter_method = "iter_ref";
}
+ // Check for array iteration: wrap with Slice<T>::from_array
+ if (obj_expr->type_info && obj_expr->type_info->kind == TYPE_ARRAY &&
+ obj_expr->type_info->array_size > 0)
+ {
+ // Create a var decl for the slice
+ slice_decl = ast_create(NODE_VAR_DECL);
+ slice_decl->var_decl.name = xstrdup("__zc_arr_slice");
+
+ // Build type string: Slice<elem_type>
+ char *elem_type_str = type_to_string(obj_expr->type_info->inner);
+ char slice_type[256];
+ sprintf(slice_type, "Slice<%s>", elem_type_str);
+ slice_decl->var_decl.type_str = xstrdup(slice_type);
+
+ ASTNode *from_array_call = ast_create(NODE_EXPR_CALL);
+ ASTNode *static_method = ast_create(NODE_EXPR_VAR);
+
+ // The function name for static methods is Type::method format
+ char func_name[512];
+ snprintf(func_name, 511, "%s::from_array", slice_type);
+ static_method->var_ref.name = xstrdup(func_name);
+
+ from_array_call->call.callee = static_method;
+
+ // Create arguments
+ ASTNode *arr_addr = ast_create(NODE_EXPR_UNARY);
+ arr_addr->unary.op = xstrdup("&");
+ arr_addr->unary.operand = obj_expr;
+
+ ASTNode *arr_cast = ast_create(NODE_EXPR_CAST);
+ char cast_type[256];
+ sprintf(cast_type, "%s*", elem_type_str);
+ arr_cast->cast.target_type = xstrdup(cast_type);
+ arr_cast->cast.expr = arr_addr;
+
+ ASTNode *size_arg = ast_create(NODE_EXPR_LITERAL);
+ size_arg->literal.type_kind = LITERAL_INT;
+ size_arg->literal.int_val = obj_expr->type_info->array_size;
+ char size_buf[32];
+ sprintf(size_buf, "%d", obj_expr->type_info->array_size);
+ size_arg->literal.string_val = xstrdup(size_buf);
+
+ arr_cast->next = size_arg;
+ from_array_call->call.args = arr_cast;
+ from_array_call->call.arg_count = 2;
+
+ slice_decl->var_decl.init_expr = from_array_call;
+
+ // Manually trigger generic instantiation for Slice<T>
+ // This ensures that Slice_int, Slice_float, etc. structures are generated
+ Token dummy_tok = {0};
+ instantiate_generic(ctx, "Slice", elem_type_str, elem_type_str, dummy_tok);
+
+ // Instantiate SliceIter and Option too for the loop logic
+ char iter_type[256];
+ sprintf(iter_type, "SliceIter<%s>", elem_type_str);
+ instantiate_generic(ctx, "SliceIter", elem_type_str, elem_type_str, dummy_tok);
+
+ char option_type[256];
+ sprintf(option_type, "Option<%s>", elem_type_str);
+ instantiate_generic(ctx, "Option", elem_type_str, elem_type_str, dummy_tok);
+
+ // Replace obj_expr with a reference to the slice variable
+ ASTNode *slice_ref = ast_create(NODE_EXPR_VAR);
+ slice_ref->var_ref.name = xstrdup("__zc_arr_slice");
+ slice_ref->resolved_type =
+ xstrdup(slice_type); // Explicitly set type for codegen
+ obj_expr = slice_ref;
+
+ free(elem_type_str);
+ }
+
// var __it = obj.iterator();
ASTNode *it_decl = ast_create(NODE_VAR_DECL);
it_decl->var_decl.name = xstrdup("__it");
@@ -1182,6 +1255,34 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
stmts_tail = node; \
}
+ char *iter_type_ptr = NULL;
+ char *option_type_ptr = NULL;
+
+ if (slice_decl)
+ {
+ char *slice_t = slice_decl->var_decl.type_str;
+ char *start = strchr(slice_t, '<');
+ if (start)
+ {
+ char *end = strrchr(slice_t, '>');
+ if (end)
+ {
+ int len = end - start - 1;
+ char *elem = xmalloc(len + 1);
+ strncpy(elem, start + 1, len);
+ elem[len] = 0;
+
+ iter_type_ptr = xmalloc(256);
+ sprintf(iter_type_ptr, "SliceIter<%s>", elem);
+
+ option_type_ptr = xmalloc(256);
+ sprintf(option_type_ptr, "Option<%s>", elem);
+
+ free(elem);
+ }
+ }
+ }
+
// var __opt = __it.next();
ASTNode *opt_decl = ast_create(NODE_VAR_DECL);
opt_decl->var_decl.name = xstrdup("__opt");
@@ -1192,6 +1293,10 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
ASTNode *memb_next = ast_create(NODE_EXPR_MEMBER);
ASTNode *it_ref = ast_create(NODE_EXPR_VAR);
it_ref->var_ref.name = xstrdup("__it");
+ if (iter_type_ptr)
+ {
+ it_ref->resolved_type = xstrdup(iter_type_ptr);
+ }
memb_next->member.target = it_ref;
memb_next->member.field = xstrdup("next");
call_next->call.callee = memb_next;
@@ -1204,15 +1309,22 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
ASTNode *memb_is_none = ast_create(NODE_EXPR_MEMBER);
ASTNode *opt_ref1 = ast_create(NODE_EXPR_VAR);
opt_ref1->var_ref.name = xstrdup("__opt");
+ if (option_type_ptr)
+ {
+ opt_ref1->resolved_type = xstrdup(option_type_ptr);
+ }
memb_is_none->member.target = opt_ref1;
memb_is_none->member.field = xstrdup("is_none");
call_is_none->call.callee = memb_is_none;
+ call_is_none->call.args = NULL;
+ call_is_none->call.arg_count = 0;
- ASTNode *break_stmt = ast_create(NODE_BREAK);
-
+ // if (__opt.is_none()) break;
ASTNode *if_break = ast_create(NODE_IF);
if_break->if_stmt.condition = call_is_none;
+ ASTNode *break_stmt = ast_create(NODE_BREAK);
if_break->if_stmt.then_body = break_stmt;
+ if_break->if_stmt.else_body = NULL;
APPEND_STMT(if_break);
// var <user_var> = __opt.unwrap();
@@ -1225,25 +1337,28 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
ASTNode *memb_unwrap = ast_create(NODE_EXPR_MEMBER);
ASTNode *opt_ref2 = ast_create(NODE_EXPR_VAR);
opt_ref2->var_ref.name = xstrdup("__opt");
+ if (option_type_ptr)
+ {
+ opt_ref2->resolved_type = xstrdup(option_type_ptr);
+ }
memb_unwrap->member.target = opt_ref2;
memb_unwrap->member.field = xstrdup("unwrap");
call_unwrap->call.callee = memb_unwrap;
+ call_unwrap->call.args = NULL;
+ call_unwrap->call.arg_count = 0;
user_var_decl->var_decl.init_expr = call_unwrap;
APPEND_STMT(user_var_decl);
- // User Body
+ // User body statements
enter_scope(ctx);
add_symbol(ctx, var_name, NULL, NULL);
- ASTNode *user_body_node;
- if (lexer_peek(l).type == TOK_LBRACE)
- {
- user_body_node = parse_block(ctx, l);
- }
- else
+ // Body block
+ ASTNode *stmt = parse_statement(ctx, l);
+ ASTNode *user_body_node = stmt;
+ if (stmt && stmt->type != NODE_BLOCK)
{
- ASTNode *stmt = parse_statement(ctx, l);
ASTNode *blk = ast_create(NODE_BLOCK);
blk->block.statements = stmt;
user_body_node = blk;
@@ -1256,10 +1371,21 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
loop_body->block.statements = stmts_head;
while_loop->while_stmt.body = loop_body;
- // Wrap entire thing in a block to scope _it
+ // Wrap entire thing in a block to scope __it (and __zc_arr_slice if present)
ASTNode *outer_block = ast_create(NODE_BLOCK);
- it_decl->next = while_loop;
- outer_block->block.statements = it_decl;
+ if (slice_decl)
+ {
+ // Chain: slice_decl -> it_decl -> while_loop
+ slice_decl->next = it_decl;
+ it_decl->next = while_loop;
+ outer_block->block.statements = slice_decl;
+ }
+ else
+ {
+ // Chain: it_decl -> while_loop
+ it_decl->next = while_loop;
+ outer_block->block.statements = it_decl;
+ }
return outer_block;
}