Loop break and continue
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 2m46s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 2m44s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 2m50s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 4m21s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 2m47s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 2m58s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 2m37s
CI / ci (Debug, ubuntu-latest) (push) Successful in 4m21s
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 2m46s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 2m44s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 2m50s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 4m21s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 2m47s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 2m58s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 2m37s
CI / ci (Debug, ubuntu-latest) (push) Successful in 4m21s
This commit is contained in:
parent
88c187de46
commit
1b0a5c4636
@ -788,6 +788,8 @@ pub const Statement = struct {
|
||||
for_each: ForEach,
|
||||
@"switch": Switch,
|
||||
block: *LexicalBlock,
|
||||
break_statement,
|
||||
continue_statement,
|
||||
},
|
||||
line: u32,
|
||||
column: u32,
|
||||
@ -1062,6 +1064,7 @@ pub const Value = struct {
|
||||
.unary => false,
|
||||
.array_expression => false,
|
||||
.string_literal => true,
|
||||
.dereference => false,
|
||||
else => @trap(),
|
||||
};
|
||||
}
|
||||
@ -1254,6 +1257,8 @@ pub const Module = struct {
|
||||
current_function: ?*Global = null,
|
||||
current_macro_declaration: ?*Macro = null,
|
||||
current_macro_instantiation: ?*Value = null,
|
||||
exit_block: ?*llvm.BasicBlock = null,
|
||||
continue_block: ?*llvm.BasicBlock = null,
|
||||
inline_at_debug_location: ?*llvm.DI.Location = null,
|
||||
name: []const u8,
|
||||
path: []const u8,
|
||||
@ -1884,6 +1889,8 @@ pub const Module = struct {
|
||||
@"for",
|
||||
@"while",
|
||||
@"switch",
|
||||
@"break",
|
||||
@"continue",
|
||||
};
|
||||
|
||||
const rules = blk: {
|
||||
@ -2464,8 +2471,18 @@ pub const Module = struct {
|
||||
},
|
||||
'\'' => blk: {
|
||||
module.offset += 1;
|
||||
const ch = module.content[module.offset];
|
||||
module.offset += 1;
|
||||
const ch_after_quote = module.content[module.offset];
|
||||
const ch: u8 = switch (ch_after_quote) {
|
||||
'\\' => switch (module.content[module.offset + 1]) {
|
||||
'n' => '\n',
|
||||
'r' => '\r',
|
||||
't' => '\t',
|
||||
else => @trap(),
|
||||
},
|
||||
else => ch_after_quote,
|
||||
};
|
||||
module.offset += @as(u64, @intFromBool(ch_after_quote == '\\')) + 1;
|
||||
|
||||
module.expect_character('\'');
|
||||
|
||||
break :blk .{
|
||||
@ -2916,6 +2933,8 @@ pub const Module = struct {
|
||||
},
|
||||
};
|
||||
},
|
||||
.@"break" => break :blk .break_statement,
|
||||
.@"continue" => break :blk .continue_statement,
|
||||
} else {
|
||||
module.offset -= statement_start_identifier.len;
|
||||
|
||||
@ -8484,27 +8503,53 @@ pub const Module = struct {
|
||||
_ = module.llvm.builder.create_branch(loop_entry_block);
|
||||
module.llvm.builder.position_at_end(loop_entry_block);
|
||||
|
||||
module.analyze(while_loop.condition, .{}, .abi);
|
||||
|
||||
const boolean_type = module.integer_type(1, false);
|
||||
const condition_value = switch (while_loop.condition.type == boolean_type) {
|
||||
true => while_loop.condition.llvm.?,
|
||||
false => switch (while_loop.condition.type.?.bb) {
|
||||
.integer => module.llvm.builder.create_integer_compare(.ne, while_loop.condition.llvm.?, while_loop.condition.type.?.llvm.abi.?.to_integer().get_constant(0, @intFromBool(false)).to_value()),
|
||||
else => @trap(),
|
||||
},
|
||||
};
|
||||
|
||||
const loop_body_block = module.llvm.context.create_basic_block("while.body", llvm_function);
|
||||
|
||||
const previous_continue_block = module.continue_block;
|
||||
defer module.continue_block = previous_continue_block;
|
||||
const loop_continue_block = module.llvm.context.create_basic_block("while.continue", llvm_function);
|
||||
module.continue_block = loop_continue_block;
|
||||
|
||||
const previous_exit_block = module.exit_block;
|
||||
defer module.exit_block = previous_exit_block;
|
||||
const loop_end_block = module.llvm.context.create_basic_block("while.end", llvm_function);
|
||||
_ = module.llvm.builder.create_conditional_branch(condition_value, loop_body_block, loop_end_block);
|
||||
module.exit_block = loop_end_block;
|
||||
|
||||
if (while_loop.condition.is_constant()) {
|
||||
switch (while_loop.condition.bb) {
|
||||
.constant_integer => |constant_integer| {
|
||||
if (constant_integer.value == 0) {
|
||||
module.report_error();
|
||||
}
|
||||
},
|
||||
else => @trap(),
|
||||
}
|
||||
_ = module.llvm.builder.create_branch(loop_body_block);
|
||||
} else {
|
||||
module.analyze(while_loop.condition, .{}, .abi);
|
||||
|
||||
const boolean_type = module.integer_type(1, false);
|
||||
const condition_value = switch (while_loop.condition.type == boolean_type) {
|
||||
true => while_loop.condition.llvm.?,
|
||||
false => switch (while_loop.condition.type.?.bb) {
|
||||
.integer => module.llvm.builder.create_integer_compare(.ne, while_loop.condition.llvm.?, while_loop.condition.type.?.llvm.abi.?.to_integer().get_constant(0, @intFromBool(false)).to_value()),
|
||||
else => @trap(),
|
||||
},
|
||||
};
|
||||
|
||||
_ = module.llvm.builder.create_conditional_branch(condition_value, loop_body_block, loop_end_block);
|
||||
}
|
||||
|
||||
module.llvm.builder.position_at_end(loop_body_block);
|
||||
|
||||
module.analyze_block(while_loop.block);
|
||||
|
||||
if (module.llvm.builder.get_insert_block() != null) {
|
||||
_ = module.llvm.builder.create_branch(loop_entry_block);
|
||||
}
|
||||
_ = module.llvm.builder.create_branch(loop_continue_block);
|
||||
}
|
||||
|
||||
module.llvm.builder.position_at_end(loop_continue_block);
|
||||
_ = module.llvm.builder.create_branch(loop_entry_block);
|
||||
|
||||
if (loop_body_block.to_value().use_empty()) {
|
||||
@trap();
|
||||
@ -8589,8 +8634,17 @@ pub const Module = struct {
|
||||
|
||||
const loop_entry_block = module.llvm.context.create_basic_block("foreach.entry", llvm_function);
|
||||
const loop_body_block = module.llvm.context.create_basic_block("foreach.body", llvm_function);
|
||||
|
||||
const previous_continue_block = module.continue_block;
|
||||
defer module.continue_block = previous_continue_block;
|
||||
const loop_continue_block = module.llvm.context.create_basic_block("foreach.continue", llvm_function);
|
||||
module.continue_block = loop_continue_block;
|
||||
|
||||
const previous_exit_block = module.exit_block;
|
||||
defer module.exit_block = previous_exit_block;
|
||||
const loop_exit_block = module.llvm.context.create_basic_block("foreach.exit", llvm_function);
|
||||
module.exit_block = loop_exit_block;
|
||||
|
||||
|
||||
switch (for_loop.kind) {
|
||||
.slice => {
|
||||
@ -8787,6 +8841,16 @@ pub const Module = struct {
|
||||
},
|
||||
}
|
||||
},
|
||||
.break_statement => {
|
||||
const exit_block = module.exit_block orelse module.report_error();
|
||||
_ = module.llvm.builder.create_branch(exit_block);
|
||||
module.llvm.builder.clear_insertion_position();
|
||||
},
|
||||
.continue_statement => {
|
||||
const continue_block = module.continue_block orelse module.report_error();
|
||||
_ = module.llvm.builder.create_branch(continue_block);
|
||||
module.llvm.builder.clear_insertion_position();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -630,6 +630,11 @@ Module = struct
|
||||
arena: &Arena,
|
||||
base_type_allocation: &Type,
|
||||
void_value: &Value,
|
||||
// Parser data
|
||||
content: []u8,
|
||||
offset: u64,
|
||||
line_offset: u64,
|
||||
line_character_offset: u64,
|
||||
}
|
||||
|
||||
module_integer_type = fn (module: &Module, integer: TypeInteger) &Type
|
||||
@ -650,6 +655,60 @@ module_noreturn_type = fn (module: &Module) &Type
|
||||
return module_void_type(module) + 1;
|
||||
}
|
||||
|
||||
is_space = fn (ch: u8) u1
|
||||
{
|
||||
return ch == ' ' or ch == '\n' or ch == '\t' or ch == '\r';
|
||||
}
|
||||
|
||||
module_skip_space = fn (module: &Module) void
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
>iteration_offset = module.offset;
|
||||
|
||||
while (module.offset < module.content.length and? is_space(module.content[module.offset]))
|
||||
{
|
||||
module.line_offset += #extend(module.content[module.offset] == '\n');
|
||||
module.line_character_offset = #select(module.content[module.offset] == '\n', module.offset, module.line_character_offset);
|
||||
module.offset += 1;
|
||||
}
|
||||
|
||||
if (module.offset + 1 < module.content.length)
|
||||
{
|
||||
>i = module.offset;
|
||||
>is_comment = module.content[i] == '/' and module.content[i + 1] == '/';
|
||||
|
||||
if (is_comment)
|
||||
{
|
||||
while (module.offset < module.content.length and? module.content[module.offset] != '\n')
|
||||
{
|
||||
module.offset += 1;
|
||||
}
|
||||
|
||||
if (module.offset < module.content.length)
|
||||
{
|
||||
module.line_offset += 1;
|
||||
module.line_character_offset = module.offset;
|
||||
module.offset += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (module.offset - iteration_offset == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module_parse = fn (module: &Module) void
|
||||
{
|
||||
}
|
||||
|
||||
module_emit = fn (module: &Module) void
|
||||
{
|
||||
}
|
||||
|
||||
compile = fn (arena: &Arena, options: CompileOptions) void
|
||||
{
|
||||
>signs: [2]u1 = [0, 1];
|
||||
@ -729,7 +788,14 @@ compile = fn (arena: &Arena, options: CompileOptions) void
|
||||
.arena = arena,
|
||||
.base_type_allocation = base_type_allocation,
|
||||
.void_value = void_value,
|
||||
.content = options.content,
|
||||
.offset = 0,
|
||||
.line_offset = 0,
|
||||
.line_character_offset = 0,
|
||||
};
|
||||
|
||||
module_parse(&module);
|
||||
module_emit(&module);
|
||||
}
|
||||
|
||||
compile_file = fn (arena: &Arena, compile_options: CompileFile) void
|
||||
|
@ -330,4 +330,5 @@ const names = &[_][]const u8{
|
||||
"basic_union",
|
||||
"constant_global_reference",
|
||||
"generic_pointer_macro",
|
||||
"break_continue",
|
||||
};
|
||||
|
31
tests/break_continue.bbb
Normal file
31
tests/break_continue.bbb
Normal file
@ -0,0 +1,31 @@
|
||||
[export] main = fn [cc(c)] () s32
|
||||
{
|
||||
>a: s32 = 0;
|
||||
|
||||
while (a < 10)
|
||||
{
|
||||
if (a == 3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
a += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
>b: s32 = 2;
|
||||
for (i: 0..10)
|
||||
{
|
||||
if (b == 2)
|
||||
{
|
||||
b += 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return a - b;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user