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
+28 -2
View File
@@ -870,7 +870,7 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
return make_result({ "stmt": "Continue" }, pos + 1)
}
// for loop
// for loop (range or list iteration)
if k == "For" {
let p = pos + 1
let item_name = tok_value(tokens, p)
@@ -880,8 +880,34 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
state_set("__no_block_expr", "1")
let r = parse_expr(tokens, p)
state_set("__no_block_expr", prev_no_block)
let list_expr = r["node"]
let start_expr = r["node"]
let p = r["pos"]
// Check for range operator: .. (exclusive) or ..= (inclusive)
let range_k = tok_kind(tokens, p)
if range_k == "DotDot" {
// exclusive range: for i in start..end
let p = p + 1
let r2 = parse_expr(tokens, p)
let end_expr = r2["node"]
let p = r2["pos"]
let r3 = parse_block(tokens, p)
let body = r3["stmts"]
let p = r3["pos"]
return make_result({ "stmt": "ForRange", "var": item_name, "start": start_expr, "end": end_expr, "inclusive": false, "body": body }, p)
}
if range_k == "DotDotEq" {
// inclusive range: for i in start..=end
let p = p + 1
let r2 = parse_expr(tokens, p)
let end_expr = r2["node"]
let p = r2["pos"]
let r3 = parse_block(tokens, p)
let body = r3["stmts"]
let p = r3["pos"]
return make_result({ "stmt": "ForRange", "var": item_name, "start": start_expr, "end": end_expr, "inclusive": true, "body": body }, p)
}
// No range operator: regular for-in (list iteration)
let list_expr = start_expr
let r2 = parse_block(tokens, p)
let body = r2["stmts"]
let p = r2["pos"]