From d20dbd02a8a746bcaedb0610facaed66963cb8c6 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Fri, 18 Apr 2025 19:18:18 -0600 Subject: [PATCH] for each wip --- src/bootstrap.zig | 99 +++++++++++++++++++++++++++++++++++++++++++++- tests/for_each.bbb | 30 ++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 tests/for_each.bbb diff --git a/src/bootstrap.zig b/src/bootstrap.zig index 0383876..77f91ff 100644 --- a/src/bootstrap.zig +++ b/src/bootstrap.zig @@ -616,12 +616,20 @@ pub const Statement = struct { expression: *Value, @"if": If, @"while": While, + for_each: ForEach, @"switch": Switch, block: *LexicalBlock, }, line: u32, column: u32, + const ForEach = struct { + left_values: []const []const u8, + right_values: []const *Value, + predicate: *Statement, + scope: Scope, + }; + const Assignment = struct { left: *Value, right: *Value, @@ -980,6 +988,7 @@ pub const Scope = struct { global, function, local, + for_each, }; }; @@ -1639,6 +1648,7 @@ pub const Module = struct { @"return", @"if", // TODO: make `unreachable` a statement start keyword? + @"for", @"while", @"switch", }; @@ -2286,7 +2296,7 @@ pub const Module = struct { return result.?; } - fn parse_statement(module: *Module, function: *Global, block: *LexicalBlock) *Statement { + fn parse_statement(module: *Module, function: *Global, scope: *Scope) *Statement { const statement_line = module.get_line(); const statement_column = module.get_column(); @@ -2404,6 +2414,86 @@ pub const Module = struct { }, }; }, + .@"for" => { + module.skip_space(); + + module.expect_character(left_parenthesis); + module.skip_space(); + + var name_buffer: [64][]const u8 = undefined; + var left_value_count: u64 = 0; + + while (true) { + module.skip_space(); + + const is_left = switch (module.content[module.offset]) { + '&' => true, + else => false, + }; + module.offset += @intFromBool(is_left); + + if (is_identifier_start_ch(module.content[module.offset])) { + const identifier = module.parse_identifier(); + name_buffer[left_value_count] = identifier; + left_value_count += 1; + } else { + @trap(); + } + + module.skip_space(); + + if (!module.consume_character_if_match(',')) { + module.expect_character(':'); + break; + } + } + + module.skip_space(); + + var right_value_buffer: [64]*Value = undefined; + var right_value_count: u64 = 0; + while (true) { + module.skip_space(); + + const identifier = module.parse_value(function, .{}); + right_value_buffer[right_value_count] = identifier; + right_value_count += 1; + + module.skip_space(); + + if (!module.consume_character_if_match(',')) { + module.expect_character(right_parenthesis); + break; + } + } + + module.skip_space(); + + if (left_value_count != right_value_count) { + module.report_error(); + } + + const left_values = module.arena.allocate([]const u8, left_value_count); + @memcpy(left_values, name_buffer[0..left_value_count]); + const right_values = module.arena.allocate(*Value, right_value_count); + @memcpy(right_values, right_value_buffer[0..right_value_count]); + + const predicate = module.parse_statement(function, block); + + break :blk .{ + .for_each = .{ + .left_values = left_values, + .right_values = right_values, + .predicate = predicate, + .scope = .{ + .line = statement_line, + .column = statement_column, + .kind = .for_each, + .parent = &block.scope, + }, + }, + }; + }, .@"switch" => { module.skip_space(); module.expect_character(left_parenthesis); @@ -2732,6 +2822,9 @@ pub const Module = struct { } assert(scope.parent != null); }, + .for_each => { + @trap(); + }, } } else { module.report_error(); @@ -7102,6 +7195,10 @@ pub const Module = struct { } }, .block => |child_block| module.analyze_block(function, child_block), + .for_each => |for_loop| { + _ = for_loop; + @trap(); + }, } } diff --git a/tests/for_each.bbb b/tests/for_each.bbb new file mode 100644 index 0000000..2318847 --- /dev/null +++ b/tests/for_each.bbb @@ -0,0 +1,30 @@ +require = fn (ok: u1) void +{ + if (!ok) #trap(); +} + +[export] main = fn [cc(c)] () s32 +{ + >array: [_]u32 = [5, 3, 2]; + >counter: u32 = 0; + for (e : array) + { + counter += e; + } + + require(counter == 10); + + //for (&e : array) + //{ + // e.& += 1; + //} + + //>new_counter: u32 = 0; + //for (e : array) + //{ + // new_counter += e; + //} + //require(counter + array.length); + + return 0; +}