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,
|
for_each: ForEach,
|
||||||
@"switch": Switch,
|
@"switch": Switch,
|
||||||
block: *LexicalBlock,
|
block: *LexicalBlock,
|
||||||
|
break_statement,
|
||||||
|
continue_statement,
|
||||||
},
|
},
|
||||||
line: u32,
|
line: u32,
|
||||||
column: u32,
|
column: u32,
|
||||||
@ -1062,6 +1064,7 @@ pub const Value = struct {
|
|||||||
.unary => false,
|
.unary => false,
|
||||||
.array_expression => false,
|
.array_expression => false,
|
||||||
.string_literal => true,
|
.string_literal => true,
|
||||||
|
.dereference => false,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1254,6 +1257,8 @@ pub const Module = struct {
|
|||||||
current_function: ?*Global = null,
|
current_function: ?*Global = null,
|
||||||
current_macro_declaration: ?*Macro = null,
|
current_macro_declaration: ?*Macro = null,
|
||||||
current_macro_instantiation: ?*Value = null,
|
current_macro_instantiation: ?*Value = null,
|
||||||
|
exit_block: ?*llvm.BasicBlock = null,
|
||||||
|
continue_block: ?*llvm.BasicBlock = null,
|
||||||
inline_at_debug_location: ?*llvm.DI.Location = null,
|
inline_at_debug_location: ?*llvm.DI.Location = null,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
@ -1884,6 +1889,8 @@ pub const Module = struct {
|
|||||||
@"for",
|
@"for",
|
||||||
@"while",
|
@"while",
|
||||||
@"switch",
|
@"switch",
|
||||||
|
@"break",
|
||||||
|
@"continue",
|
||||||
};
|
};
|
||||||
|
|
||||||
const rules = blk: {
|
const rules = blk: {
|
||||||
@ -2464,8 +2471,18 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
'\'' => blk: {
|
'\'' => blk: {
|
||||||
module.offset += 1;
|
module.offset += 1;
|
||||||
const ch = module.content[module.offset];
|
const ch_after_quote = module.content[module.offset];
|
||||||
module.offset += 1;
|
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('\'');
|
module.expect_character('\'');
|
||||||
|
|
||||||
break :blk .{
|
break :blk .{
|
||||||
@ -2916,6 +2933,8 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
.@"break" => break :blk .break_statement,
|
||||||
|
.@"continue" => break :blk .continue_statement,
|
||||||
} else {
|
} else {
|
||||||
module.offset -= statement_start_identifier.len;
|
module.offset -= statement_start_identifier.len;
|
||||||
|
|
||||||
@ -8484,28 +8503,54 @@ pub const Module = struct {
|
|||||||
_ = module.llvm.builder.create_branch(loop_entry_block);
|
_ = module.llvm.builder.create_branch(loop_entry_block);
|
||||||
module.llvm.builder.position_at_end(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 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);
|
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.llvm.builder.position_at_end(loop_body_block);
|
||||||
|
|
||||||
module.analyze_block(while_loop.block);
|
module.analyze_block(while_loop.block);
|
||||||
|
|
||||||
if (module.llvm.builder.get_insert_block() != null) {
|
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()) {
|
if (loop_body_block.to_value().use_empty()) {
|
||||||
@trap();
|
@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_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 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);
|
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);
|
const loop_exit_block = module.llvm.context.create_basic_block("foreach.exit", llvm_function);
|
||||||
|
module.exit_block = loop_exit_block;
|
||||||
|
|
||||||
|
|
||||||
switch (for_loop.kind) {
|
switch (for_loop.kind) {
|
||||||
.slice => {
|
.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,
|
arena: &Arena,
|
||||||
base_type_allocation: &Type,
|
base_type_allocation: &Type,
|
||||||
void_value: &Value,
|
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
|
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;
|
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
|
compile = fn (arena: &Arena, options: CompileOptions) void
|
||||||
{
|
{
|
||||||
>signs: [2]u1 = [0, 1];
|
>signs: [2]u1 = [0, 1];
|
||||||
@ -729,7 +788,14 @@ compile = fn (arena: &Arena, options: CompileOptions) void
|
|||||||
.arena = arena,
|
.arena = arena,
|
||||||
.base_type_allocation = base_type_allocation,
|
.base_type_allocation = base_type_allocation,
|
||||||
.void_value = void_value,
|
.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
|
compile_file = fn (arena: &Arena, compile_options: CompileFile) void
|
||||||
|
@ -330,4 +330,5 @@ const names = &[_][]const u8{
|
|||||||
"basic_union",
|
"basic_union",
|
||||||
"constant_global_reference",
|
"constant_global_reference",
|
||||||
"generic_pointer_macro",
|
"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