add for-range loops to El (for i in 0..n)

Adds `for i in start..end` (exclusive) and `for i in start..=end`
(inclusive) range loop syntax. Existing `for item in list` iteration
is preserved; the parser branches on DotDot/DotDotEq presence after
the start expression. Lexer adds DotDot and DotDotEq tokens with
longer-match-first priority. Codegen emits a C `for` loop with the
loop variable scoped to the statement; inclusive uses `<=`, exclusive `<`.
This commit is contained in:
Will Anderson
2026-05-03 15:44:58 -05:00
parent 49a8a1c24b
commit f271f9d9d8
3 changed files with 68 additions and 4 deletions
+22
View File
@@ -1141,6 +1141,28 @@ fn cg_stmt(stmt: Map<String, Any>, indent: String, declared: [String]) -> [Strin
return declared
}
if kind == "ForRange" {
let var_name: String = stmt["var"]
let start_expr = stmt["start"]
let end_expr = stmt["end"]
let inclusive: Bool = stmt["inclusive"]
let body = stmt["body"]
let start_c: String = cg_expr(start_expr)
let end_c: String = cg_expr(end_expr)
// Loop variable introduced as a C local scoped to the for statement.
// Body gets its own declared clone so let-bindings don't leak out.
let body_decl = native_list_clone(declared)
let body_decl = native_list_append(body_decl, var_name)
if inclusive {
emit_line(indent + "for (el_val_t " + var_name + " = " + start_c + "; " + var_name + " <= " + end_c + "; " + var_name + "++) {")
} else {
emit_line(indent + "for (el_val_t " + var_name + " = " + start_c + "; " + var_name + " < " + end_c + "; " + var_name + "++) {")
}
cg_stmts(body, indent + " ", body_decl)
emit_line(indent + "}")
return declared
}
if kind == "FnDef" { return declared }
if kind == "TypeDef" { return declared }
if kind == "EnumDef" { return declared }