for arr: (it) {}

This commit is contained in:
agra
2026-02-16 00:55:03 +02:00
parent 3e1e764753
commit fb60818424
7 changed files with 88 additions and 56 deletions

View File

@@ -296,6 +296,7 @@ pub const CodeGen = struct {
const NamedValue = struct {
ptr: c.LLVMValueRef, // alloca pointer
ty: Type, // sx type
is_const: bool = false,
};
/// Unified value lookup result — avoids sequential hash lookups at hot paths.
@@ -2881,6 +2882,8 @@ pub const CodeGen = struct {
return self.emitErrorFmt("undefined variable '{s}'", .{name});
const entry = lookup.asNamedValue() orelse
return self.emitErrorFmt("cannot assign to constant '{s}'", .{name});
if (entry.is_const)
return self.emitErrorFmt("cannot assign to '{s}'", .{name});
// Meta type reassignment: x = Vec4, x = f64, x = test
if (entry.ty == .meta_type and asgn.op == .assign) {
@@ -6345,15 +6348,17 @@ pub const CodeGen = struct {
const elem_llvm_ty = self.typeToLLVM(elem_ty);
// Allocate it_index (s64) and it (element type)
const idx_alloca = self.buildEntryBlockAlloca(i64_type, "it_index");
// Allocate index variable
const idx_alloca = self.buildEntryBlockAlloca(i64_type, "for_idx");
_ = c.LLVMBuildStore(self.builder, c.LLVMConstInt(i64_type, 0, 0), idx_alloca);
const it_alloca = self.buildEntryBlockAlloca(elem_llvm_ty, "it");
// Push scope and bind it, it_index
// Push scope and bind index if requested
try self.pushScope();
try self.named_values.put("it", .{ .ptr = it_alloca, .ty = elem_ty });
try self.named_values.put("it_index", .{ .ptr = idx_alloca, .ty = Type.s(64) });
if (for_expr.index_name) |idx_name| {
if (!std.mem.eql(u8, idx_name, "_")) {
try self.named_values.put(idx_name, .{ .ptr = idx_alloca, .ty = Type.s(64), .is_const = true });
}
}
// Create basic blocks
const cond_bb = self.appendBB("for.cond");
@@ -6363,29 +6368,32 @@ pub const CodeGen = struct {
self.br(cond_bb);
// Condition: it_index < len
// Condition: index < len
self.positionAt(cond_bb);
const cur_idx = c.LLVMBuildLoad2(self.builder, i64_type, idx_alloca, "cur_idx");
const cond_val = self.icmp(c.LLVMIntSLT, cur_idx, len_val, "for_cond");
self.condBr(cond_val, body_bb, after_bb);
// Body: load it = iterable[it_index], then execute body
// Body: compute element GEP, bind capture, execute body
self.positionAt(body_bb);
const body_idx = c.LLVMBuildLoad2(self.builder, i64_type, idx_alloca, "body_idx");
if (is_slice) {
// Slice: GEP through data pointer
const gep = self.gepPointerElement(elem_llvm_ty, iter_ptr, body_idx, "for_elem");
const elem_val = c.LLVMBuildLoad2(self.builder, elem_llvm_ty, gep, "it_val");
_ = c.LLVMBuildStore(self.builder, elem_val, it_alloca);
} else {
// Array: GEP with [0, idx]
const elem_gep = if (is_slice)
self.gepPointerElement(elem_llvm_ty, iter_ptr, body_idx, "for_elem")
else blk: {
const arr_llvm_ty = self.typeToLLVM(iter_ty);
const zero = c.LLVMConstInt(i64_type, 0, 0);
var indices = [_]c.LLVMValueRef{ zero, body_idx };
const gep = c.LLVMBuildGEP2(self.builder, arr_llvm_ty, iter_ptr, &indices, 2, "for_elem");
const elem_val = c.LLVMBuildLoad2(self.builder, elem_llvm_ty, gep, "it_val");
_ = c.LLVMBuildStore(self.builder, elem_val, it_alloca);
break :blk c.LLVMBuildGEP2(self.builder, arr_llvm_ty, iter_ptr, &indices, 2, "for_elem");
};
if (!std.mem.eql(u8, for_expr.capture_name, "_")) {
// Alias mode: capture points directly to element in array/slice
try self.named_values.put(for_expr.capture_name, .{
.ptr = elem_gep,
.ty = elem_ty,
.is_const = true,
});
}
// Save and set loop context for break/continue
@@ -6405,7 +6413,7 @@ pub const CodeGen = struct {
self.br(incr_bb);
}
// Increment it_index, then branch back to condition
// Increment index, then branch back to condition
self.positionAt(incr_bb);
const inc_idx = c.LLVMBuildLoad2(self.builder, i64_type, idx_alloca, "inc_idx");
const next_idx = c.LLVMBuildAdd(self.builder, inc_idx, c.LLVMConstInt(i64_type, 1, 0), "next_idx");