More if
This commit is contained in:
parent
381ea47e39
commit
1e5020fed1
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
.zig-cache/
|
||||||
zig-cache/
|
zig-cache/
|
||||||
zig-out/
|
zig-out/
|
||||||
nat/
|
nat/
|
||||||
|
@ -745,6 +745,7 @@ const Parser = struct{
|
|||||||
logical_shift_right_assign,
|
logical_shift_right_assign,
|
||||||
|
|
||||||
compare_equal,
|
compare_equal,
|
||||||
|
compare_not_equal,
|
||||||
compare_unsigned_greater,
|
compare_unsigned_greater,
|
||||||
compare_unsigned_greater_equal,
|
compare_unsigned_greater_equal,
|
||||||
compare_signed_greater,
|
compare_signed_greater,
|
||||||
@ -782,10 +783,10 @@ const Parser = struct{
|
|||||||
.none => {
|
.none => {
|
||||||
previous_value = current_value;
|
previous_value = current_value;
|
||||||
},
|
},
|
||||||
.compare_equal, .compare_unsigned_greater, .compare_unsigned_greater_equal, .compare_signed_greater, .compare_signed_greater_equal, .compare_unsigned_less, .compare_unsigned_less_equal, .compare_signed_less, .compare_signed_less_equal => {
|
.compare_equal, .compare_not_equal, .compare_unsigned_greater, .compare_unsigned_greater_equal, .compare_signed_greater, .compare_signed_greater_equal, .compare_unsigned_less, .compare_unsigned_less_equal, .compare_signed_less, .compare_signed_less_equal => {
|
||||||
switch (current_operation) {
|
switch (current_operation) {
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
inline .compare_equal, .compare_unsigned_greater, .compare_unsigned_greater_equal, .compare_signed_greater, .compare_signed_greater_equal, .compare_unsigned_less, .compare_unsigned_less_equal, .compare_signed_less, .compare_signed_less_equal => |co| {
|
inline .compare_equal, .compare_not_equal, .compare_unsigned_greater, .compare_unsigned_greater_equal, .compare_signed_greater, .compare_signed_greater_equal, .compare_unsigned_less, .compare_unsigned_less_equal, .compare_signed_less, .compare_signed_less_equal => |co| {
|
||||||
const string = @tagName(co)["compare_".len..];
|
const string = @tagName(co)["compare_".len..];
|
||||||
const comparison = @field(IntegerCompare.Id, string);
|
const comparison = @field(IntegerCompare.Id, string);
|
||||||
const compare = thread.integer_compares.append(.{
|
const compare = thread.integer_compares.append(.{
|
||||||
@ -862,6 +863,20 @@ const Parser = struct{
|
|||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
},
|
},
|
||||||
|
'!' => {
|
||||||
|
current_operation = undefined;
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
switch (src[parser.i]) {
|
||||||
|
'=' => {
|
||||||
|
current_operation = .compare_not_equal;
|
||||||
|
parser.i += 1;
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
},
|
||||||
'+' => {
|
'+' => {
|
||||||
current_operation = .add;
|
current_operation = .add;
|
||||||
parser.i += 1;
|
parser.i += 1;
|
||||||
@ -1047,7 +1062,11 @@ const Parser = struct{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_if_expression(parser: *Parser, analyzer: *Analyzer, thread: *Thread, file: *File) void {
|
const IfResult = struct {
|
||||||
|
terminated: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn parse_if_expression(parser: *Parser, analyzer: *Analyzer, thread: *Thread, file: *File) IfResult {
|
||||||
const src = file.source_code;
|
const src = file.source_code;
|
||||||
parser.i += 2;
|
parser.i += 2;
|
||||||
|
|
||||||
@ -1134,30 +1153,35 @@ const Parser = struct{
|
|||||||
analyzer.current_basic_block = branch.taken;
|
analyzer.current_basic_block = branch.taken;
|
||||||
_ = branch.taken.predecessors.append(original_block);
|
_ = branch.taken.predecessors.append(original_block);
|
||||||
|
|
||||||
|
var if_terminated = false;
|
||||||
|
var else_terminated = false;
|
||||||
switch (src[parser.i]) {
|
switch (src[parser.i]) {
|
||||||
brace_open => {
|
brace_open => {
|
||||||
analyze_local_block(thread, analyzer, parser, file);
|
const if_block = analyze_local_block(thread, analyzer, parser, file);
|
||||||
|
if_terminated = if_block.terminated;
|
||||||
},
|
},
|
||||||
else => @panic((src.ptr + parser.i)[0..1]),
|
else => @panic((src.ptr + parser.i)[0..1]),
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
if (src[parser.i] == 'e') {
|
if (src[parser.i] == 'e' and byte_equal(src[parser.i..][0.."else".len], "else")) {
|
||||||
if (byte_equal(src[parser.i..][0.."else".len], "else")) {
|
// TODO: create not taken block
|
||||||
parser.i += "else".len;
|
parser.i += "else".len;
|
||||||
_ = branch.taken.predecessors.append(original_block);
|
_ = branch.not_taken.predecessors.append(original_block);
|
||||||
analyzer.current_basic_block = branch.not_taken;
|
analyzer.current_basic_block = branch.not_taken;
|
||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
switch (src[parser.i]) {
|
switch (src[parser.i]) {
|
||||||
brace_open => {
|
brace_open => {
|
||||||
analyze_local_block(thread, analyzer, parser, file);
|
const else_block = analyze_local_block(thread, analyzer, parser, file);
|
||||||
|
else_terminated = else_block.terminated;
|
||||||
},
|
},
|
||||||
'i' => {
|
'i' => {
|
||||||
if (src[parser.i + 1] == 'f') {
|
if (src[parser.i + 1] == 'f') {
|
||||||
parser.parse_if_expression(analyzer, thread, file);
|
const else_if = parser.parse_if_expression(analyzer, thread, file);
|
||||||
|
else_terminated = else_if.terminated;
|
||||||
} else {
|
} else {
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
@ -1165,11 +1189,13 @@ const Parser = struct{
|
|||||||
else => @panic((src.ptr + parser.i)[0..1]),
|
else => @panic((src.ptr + parser.i)[0..1]),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable;
|
_ = branch.not_taken.predecessors.append(original_block);
|
||||||
}
|
analyzer.current_basic_block = branch.not_taken;
|
||||||
} else {
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.terminated = if_terminated and else_terminated,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3342,7 +3368,11 @@ fn build_return(thread: *Thread, analyzer: *Analyzer, return_value: *Value) void
|
|||||||
analyzer.current_basic_block.is_terminated = true;
|
analyzer.current_basic_block.is_terminated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser, file: *File) void {
|
const LocalBlockResult = struct{
|
||||||
|
terminated: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser, file: *File) LocalBlockResult {
|
||||||
const src = file.source_code;
|
const src = file.source_code;
|
||||||
const function = analyzer.current_function;
|
const function = analyzer.current_function;
|
||||||
const block_start = parser.i;
|
const block_start = parser.i;
|
||||||
@ -3359,6 +3389,7 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
});
|
});
|
||||||
analyzer.current_scope = &local_block.scope;
|
analyzer.current_scope = &local_block.scope;
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
var terminated = false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
@ -3448,6 +3479,7 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
} else {
|
} else {
|
||||||
build_return(thread, analyzer, return_value);
|
build_return(thread, analyzer, return_value);
|
||||||
}
|
}
|
||||||
|
terminated = true;
|
||||||
} else {
|
} else {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -3567,7 +3599,8 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
},
|
},
|
||||||
'i' => {
|
'i' => {
|
||||||
if (src[parser.i + 1] == 'f') {
|
if (src[parser.i + 1] == 'f') {
|
||||||
parser.parse_if_expression(analyzer, thread, file);
|
const if_block = parser.parse_if_expression(analyzer, thread, file);
|
||||||
|
terminated = terminated or if_block.terminated;
|
||||||
} else {
|
} else {
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
@ -3579,6 +3612,10 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
parser.expect_character(src, brace_close);
|
parser.expect_character(src, brace_close);
|
||||||
|
|
||||||
|
return LocalBlockResult{
|
||||||
|
.terminated = terminated,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3897,7 +3934,8 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
|||||||
_ = analyzer.current_basic_block.instructions.append(&store.instruction);
|
_ = analyzer.current_basic_block.instructions.append(&store.instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze_local_block(thread, &analyzer, &parser, file);
|
const result = analyze_local_block(thread, &analyzer, &parser, file);
|
||||||
|
_ = result;
|
||||||
|
|
||||||
const current_basic_block = analyzer.current_basic_block;
|
const current_basic_block = analyzer.current_basic_block;
|
||||||
if (analyzer.return_phi) |return_phi| {
|
if (analyzer.return_phi) |return_phi| {
|
||||||
|
19
retest/standalone/more_if/main.nat
Normal file
19
retest/standalone/more_if/main.nat
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
fn foo(arg: s32) s32 {
|
||||||
|
if (arg > 1) {
|
||||||
|
return 6;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn[cc(.c)] main[export]() s32 {
|
||||||
|
>a = foo(5);
|
||||||
|
>b = foo(5);
|
||||||
|
if (a - 6 != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (b - 6 != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return a - b;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user