Constant add

This commit is contained in:
David Gonzalez Martin 2025-02-21 11:24:42 -06:00
parent c4d25ca393
commit 892360a084
2 changed files with 120 additions and 56 deletions

View File

@ -144,53 +144,71 @@ const Converter = struct {
} }
} }
fn parse_integer(noalias converter: *Converter, expected_type: *llvm.Type) *llvm.Value { fn parse_decimal(noalias converter: *Converter) u64 {
var value: u64 = 0;
while (true) {
const ch = converter.content[converter.offset];
if (!is_decimal_ch(ch)) {
break;
}
converter.offset += 1;
value = lib.parse.accumulate_decimal(value, ch);
}
return value;
}
fn parse_integer(noalias converter: *Converter, expected_type: *llvm.Type, signed: bool) *llvm.Value {
const start = converter.offset; const start = converter.offset;
const integer_start_ch = converter.content[start]; const integer_start_ch = converter.content[start];
assert(!is_space(integer_start_ch)); assert(!is_space(integer_start_ch));
assert(is_decimal_ch(integer_start_ch)); assert(is_decimal_ch(integer_start_ch));
const integer_type = expected_type.to_integer(); const integer_type = expected_type.to_integer();
const sign_extend = false; const sign_extend = signed;
var value: u64 = 0;
switch (integer_start_ch) {
'0' => {
converter.offset += 1;
switch (converter.content[converter.offset]) {
'x' => {
// TODO: parse hexadecimal
converter.report_error();
},
'o' => {
// TODO: parse octal
converter.report_error();
},
'b' => {
// TODO: parse binary
converter.report_error();
},
'0'...'9' => {
converter.report_error();
},
// Zero literal
else => {},
}
},
'1'...'9' => {
while (true) {
const ch = converter.content[converter.offset];
if (!is_decimal_ch(ch)) {
break;
}
const value: u64 = switch (signed) {
true => switch (integer_start_ch) {
'0' => blk: {
converter.offset += 1; converter.offset += 1;
value = lib.parse.accumulate_decimal(value, ch);
} switch (converter.content[converter.offset]) {
'x', 'o', 'b', '0'...'9' => converter.report_error(),
else => break :blk 0,
}
},
'1'...'9' => @bitCast(-@as(i64, @intCast(converter.parse_decimal()))),
else => unreachable,
}, },
else => unreachable, false => switch (integer_start_ch) {
} '0' => blk: {
converter.offset += 1;
switch (converter.content[converter.offset]) {
'x' => {
// TODO: parse hexadecimal
converter.report_error();
},
'o' => {
// TODO: parse octal
converter.report_error();
},
'b' => {
// TODO: parse binary
converter.report_error();
},
'0'...'9' => {
converter.report_error();
},
// Zero literal
else => break :blk 0,
}
},
'1'...'9' => converter.parse_decimal(),
else => unreachable,
},
};
const integer_value = integer_type.get_constant(value, @intFromBool(sign_extend)); const integer_value = integer_type.get_constant(value, @intFromBool(sign_extend));
return integer_value.to_value(); return integer_value.to_value();
@ -251,6 +269,7 @@ const Converter = struct {
const ExpressionState = enum { const ExpressionState = enum {
none, none,
sub, sub,
add,
}; };
fn parse_value(noalias converter: *Converter, noalias thread: *llvm.Thread, expected_type: *llvm.Type) *llvm.Value { fn parse_value(noalias converter: *Converter, noalias thread: *llvm.Thread, expected_type: *llvm.Type) *llvm.Value {
@ -267,14 +286,14 @@ const Converter = struct {
converter.skip_space(); converter.skip_space();
switch (value_state) { const left = previous_value;
.none => previous_value = current_value, const right = current_value;
.sub => {
const left = previous_value; previous_value = switch (value_state) {
const right = current_value; .none => current_value,
previous_value = thread.builder.create_sub(left, right); .sub => thread.builder.create_sub(left, right),
}, .add => thread.builder.create_add(left, right),
} };
const ch = converter.content[converter.offset]; const ch = converter.content[converter.offset];
value_state = switch (ch) { value_state = switch (ch) {
@ -283,6 +302,10 @@ const Converter = struct {
converter.offset += 1; converter.offset += 1;
break :blk .sub; break :blk .sub;
}, },
'+' => blk: {
converter.offset += 1;
break :blk .add;
},
else => os.abort(), else => os.abort(),
}; };
@ -292,19 +315,51 @@ const Converter = struct {
return value; return value;
} }
const Prefix = enum {
none,
negative,
};
fn parse_single_value(noalias converter: *Converter, expected_type: *llvm.Type) *llvm.Value { fn parse_single_value(noalias converter: *Converter, expected_type: *llvm.Type) *llvm.Value {
converter.skip_space(); converter.skip_space();
const start = converter.offset; const prefix_offset = converter.offset;
const value_start_ch = converter.content[start]; const prefix_ch = converter.content[prefix_offset];
if (is_identifier_start_ch(value_start_ch)) { var is_signed = false;
converter.report_error(); const prefix: Prefix = switch (prefix_ch) {
} else if (is_decimal_ch(value_start_ch)) { 'a'...'z', 'A'...'Z', '_', '0'...'9' => .none,
const value = converter.parse_integer(expected_type); '-' => blk: {
return value; converter.offset += 1;
} else {
converter.report_error(); // TODO: should we skip space here?
} converter.skip_space();
is_signed = true;
break :blk .negative;
},
else => os.abort(),
};
_ = prefix;
const value_offset = converter.offset;
const value_start_ch = converter.content[value_offset];
const value = switch (value_start_ch) {
'a'...'z', 'A'...'Z', '_' => os.abort(),
'0'...'9' => converter.parse_integer(expected_type, is_signed),
else => os.abort(),
};
return value;
// if (is_identifier_start_ch(value_start_ch)) {
// converter.report_error();
// } else if (is_decimal_ch(value_start_ch)) {
// const value = converter.parse_integer(expected_type);
// return value;
// } else if ({
// switch (value_start_ch) {
//
// }
// converter.report_error();
// }
} }
}; };
@ -631,6 +686,10 @@ test "minimal" {
try invoke("minimal"); try invoke("minimal");
} }
test "constant add" {
try invoke("constant_add");
}
test "constant sub" { test "constant sub" {
try invoke("constant_sub"); try invoke("constant_sub");
} }

5
tests/constant_add.bbb Normal file
View File

@ -0,0 +1,5 @@
[export] main = fn [cc(c)] () s32
{
return -1 + 1;
}