for each wip
This commit is contained in:
parent
8bef7f8bd0
commit
d20dbd02a8
@ -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();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
30
tests/for_each.bbb
Normal file
30
tests/for_each.bbb
Normal file
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user