Implement wrapping arithmetic
This commit is contained in:
parent
04a1682f57
commit
343b909829
@ -3805,10 +3805,16 @@ pub const Instruction = union(enum) {
|
|||||||
|
|
||||||
const Id = enum {
|
const Id = enum {
|
||||||
add,
|
add,
|
||||||
|
wrapping_add,
|
||||||
|
saturated_add,
|
||||||
|
sub,
|
||||||
|
wrapping_sub,
|
||||||
|
saturated_sub,
|
||||||
|
mul,
|
||||||
|
wrapping_mul,
|
||||||
|
saturated_mul,
|
||||||
div,
|
div,
|
||||||
mod,
|
mod,
|
||||||
mul,
|
|
||||||
sub,
|
|
||||||
bit_and,
|
bit_and,
|
||||||
bit_or,
|
bit_or,
|
||||||
bit_xor,
|
bit_xor,
|
||||||
@ -4380,8 +4386,14 @@ pub const IntrinsicId = enum {
|
|||||||
|
|
||||||
pub const ArithmeticLogicIntegerInstruction = enum {
|
pub const ArithmeticLogicIntegerInstruction = enum {
|
||||||
add,
|
add,
|
||||||
|
wrapping_add,
|
||||||
|
saturated_add,
|
||||||
sub,
|
sub,
|
||||||
|
wrapping_sub,
|
||||||
|
saturated_sub,
|
||||||
mul,
|
mul,
|
||||||
|
wrapping_mul,
|
||||||
|
saturated_mul,
|
||||||
div,
|
div,
|
||||||
mod,
|
mod,
|
||||||
bit_and,
|
bit_and,
|
||||||
@ -6728,7 +6740,7 @@ pub const Builder = struct {
|
|||||||
fn resolveAssignment(builder: *Builder, unit: *Unit, context: *const Context, node_index: Node.Index) !V {
|
fn resolveAssignment(builder: *Builder, unit: *Unit, context: *const Context, node_index: Node.Index) !V {
|
||||||
const node = unit.getNode(node_index);
|
const node = unit.getNode(node_index);
|
||||||
switch (node.id) {
|
switch (node.id) {
|
||||||
.assign, .add_assign, .sub_assign, .div_assign => {
|
.assign, .add_assign, .sub_assign, .div_assign, .or_assign => {
|
||||||
if (unit.getNode(node.left).id == .discard) {
|
if (unit.getNode(node.left).id == .discard) {
|
||||||
_ = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, node.right, .right);
|
_ = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, node.right, .right);
|
||||||
return .{
|
return .{
|
||||||
@ -6778,6 +6790,7 @@ pub const Builder = struct {
|
|||||||
.add_assign => .add,
|
.add_assign => .add,
|
||||||
.sub_assign => .sub,
|
.sub_assign => .sub,
|
||||||
.div_assign => .div,
|
.div_assign => .div,
|
||||||
|
.or_assign => .bit_or,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -9992,13 +10005,22 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.add, .sub, .mul, .div, .mod, .bit_and, .bit_or, .bit_xor, .shift_left, .shift_right, .bool_and, .bool_or => block: {
|
.add, .wrapping_add, .saturated_add,
|
||||||
|
.sub, .wrapping_sub, .saturated_sub,
|
||||||
|
.mul, .wrapping_mul, .saturated_mul,
|
||||||
|
.div, .mod, .bit_and, .bit_or, .bit_xor, .shift_left, .shift_right, .bool_and, .bool_or => block: {
|
||||||
const left_node_index = node.left;
|
const left_node_index = node.left;
|
||||||
const right_node_index = node.right;
|
const right_node_index = node.right;
|
||||||
const binary_operation_id: ArithmeticLogicIntegerInstruction = switch (node.id) {
|
const binary_operation_id: ArithmeticLogicIntegerInstruction = switch (node.id) {
|
||||||
.add => .add,
|
.add => .add,
|
||||||
|
.wrapping_add => .wrapping_add,
|
||||||
|
.saturated_add => .saturated_add,
|
||||||
.sub => .sub,
|
.sub => .sub,
|
||||||
|
.wrapping_sub => .wrapping_sub,
|
||||||
|
.saturated_sub => .saturated_sub,
|
||||||
.mul => .mul,
|
.mul => .mul,
|
||||||
|
.wrapping_mul => .wrapping_mul,
|
||||||
|
.saturated_mul => .saturated_mul,
|
||||||
.div => .div,
|
.div => .div,
|
||||||
.mod => .mod,
|
.mod => .mod,
|
||||||
.bit_and => .bit_and,
|
.bit_and => .bit_and,
|
||||||
@ -10026,11 +10048,17 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
.type => switch (binary_operation_id) {
|
.type => switch (binary_operation_id) {
|
||||||
.add,
|
.add,
|
||||||
|
.wrapping_add,
|
||||||
|
.saturated_add,
|
||||||
.sub,
|
.sub,
|
||||||
|
.wrapping_sub,
|
||||||
|
.saturated_sub,
|
||||||
.bit_and,
|
.bit_and,
|
||||||
.bit_xor,
|
.bit_xor,
|
||||||
.bit_or,
|
.bit_or,
|
||||||
.mul,
|
.mul,
|
||||||
|
.wrapping_mul,
|
||||||
|
.saturated_mul,
|
||||||
.div,
|
.div,
|
||||||
.mod,
|
.mod,
|
||||||
.shift_left,
|
.shift_left,
|
||||||
@ -10070,6 +10098,7 @@ pub const Builder = struct {
|
|||||||
.bit_xor => left ^ right,
|
.bit_xor => left ^ right,
|
||||||
.shift_left => left << @as(u6, @intCast(right)),
|
.shift_left => left << @as(u6, @intCast(right)),
|
||||||
.shift_right => left >> @as(u6, @intCast(right)),
|
.shift_right => left >> @as(u6, @intCast(right)),
|
||||||
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
break :block switch (type_expect) {
|
break :block switch (type_expect) {
|
||||||
@ -10141,8 +10170,14 @@ pub const Builder = struct {
|
|||||||
.bit_xor,
|
.bit_xor,
|
||||||
.shift_right,
|
.shift_right,
|
||||||
.add,
|
.add,
|
||||||
|
.wrapping_add,
|
||||||
|
.saturated_add,
|
||||||
.sub,
|
.sub,
|
||||||
|
.wrapping_sub,
|
||||||
|
.saturated_sub,
|
||||||
.mul,
|
.mul,
|
||||||
|
.wrapping_mul,
|
||||||
|
.saturated_mul,
|
||||||
.div,
|
.div,
|
||||||
.mod,
|
.mod,
|
||||||
=> left_value.type,
|
=> left_value.type,
|
||||||
@ -10157,10 +10192,16 @@ pub const Builder = struct {
|
|||||||
.materialized_int => b: {
|
.materialized_int => b: {
|
||||||
const id: Instruction.IntegerBinaryOperation.Id = switch (binary_operation_id) {
|
const id: Instruction.IntegerBinaryOperation.Id = switch (binary_operation_id) {
|
||||||
.add => .add,
|
.add => .add,
|
||||||
|
.wrapping_add => .wrapping_add,
|
||||||
|
.saturated_add => .saturated_add,
|
||||||
|
.sub => .sub,
|
||||||
|
.wrapping_sub => .wrapping_sub,
|
||||||
|
.saturated_sub => .saturated_sub,
|
||||||
|
.mul => .mul,
|
||||||
|
.wrapping_mul => .wrapping_mul,
|
||||||
|
.saturated_mul => .saturated_mul,
|
||||||
.div => .div,
|
.div => .div,
|
||||||
.mod => .mod,
|
.mod => .mod,
|
||||||
.mul => .mul,
|
|
||||||
.sub => .sub,
|
|
||||||
.bit_and => .bit_and,
|
.bit_and => .bit_and,
|
||||||
.bit_or => .bit_or,
|
.bit_or => .bit_or,
|
||||||
.bit_xor => .bit_xor,
|
.bit_xor => .bit_xor,
|
||||||
@ -13776,7 +13817,7 @@ pub const Builder = struct {
|
|||||||
try builder.insertDebugCheckPoint(unit, context, statement_node.token);
|
try builder.insertDebugCheckPoint(unit, context, statement_node.token);
|
||||||
|
|
||||||
switch (statement_node.id) {
|
switch (statement_node.id) {
|
||||||
.assign, .add_assign, .sub_assign, .div_assign => {
|
.assign, .add_assign, .sub_assign, .div_assign, .or_assign => {
|
||||||
_ = try builder.resolveAssignment(unit, context, statement_node_index);
|
_ = try builder.resolveAssignment(unit, context, statement_node_index);
|
||||||
},
|
},
|
||||||
.if_else => {
|
.if_else => {
|
||||||
@ -17349,8 +17390,14 @@ pub const Token = struct {
|
|||||||
// Binary
|
// Binary
|
||||||
operator_assign,
|
operator_assign,
|
||||||
operator_add,
|
operator_add,
|
||||||
|
operator_saturated_add,
|
||||||
|
operator_wrapping_add,
|
||||||
operator_minus,
|
operator_minus,
|
||||||
|
operator_saturated_sub,
|
||||||
|
operator_wrapping_sub,
|
||||||
operator_asterisk,
|
operator_asterisk,
|
||||||
|
operator_saturated_mul,
|
||||||
|
operator_wrapping_mul,
|
||||||
operator_div,
|
operator_div,
|
||||||
operator_mod,
|
operator_mod,
|
||||||
operator_bar,
|
operator_bar,
|
||||||
@ -17359,8 +17406,14 @@ pub const Token = struct {
|
|||||||
operator_shift_left,
|
operator_shift_left,
|
||||||
operator_shift_right,
|
operator_shift_right,
|
||||||
operator_add_assign,
|
operator_add_assign,
|
||||||
|
operator_wrapping_add_assign,
|
||||||
|
operator_saturated_add_assign,
|
||||||
operator_sub_assign,
|
operator_sub_assign,
|
||||||
|
operator_wrapping_sub_assign,
|
||||||
|
operator_saturated_sub_assign,
|
||||||
operator_mul_assign,
|
operator_mul_assign,
|
||||||
|
operator_wrapping_mul_assign,
|
||||||
|
operator_saturated_mul_assign,
|
||||||
operator_div_assign,
|
operator_div_assign,
|
||||||
operator_mod_assign,
|
operator_mod_assign,
|
||||||
operator_or_assign,
|
operator_or_assign,
|
||||||
|
@ -2762,14 +2762,20 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
const left = try llvm.emitRightValue(unit, context, binary_operation.left);
|
const left = try llvm.emitRightValue(unit, context, binary_operation.left);
|
||||||
const right = try llvm.emitRightValue(unit, context, binary_operation.right);
|
const right = try llvm.emitRightValue(unit, context, binary_operation.right);
|
||||||
assert(left.getType() == right.getType());
|
assert(left.getType() == right.getType());
|
||||||
const no_signed_wrapping = binary_operation.signedness == .signed;
|
const no_signed_wrapping = binary_operation.signedness == .signed or switch (binary_operation.id) {
|
||||||
const no_unsigned_wrapping = binary_operation.signedness == .unsigned;
|
.wrapping_add, .wrapping_sub, .wrapping_mul => false,
|
||||||
|
else => true,
|
||||||
|
};
|
||||||
|
const no_unsigned_wrapping = binary_operation.signedness == .unsigned or switch (binary_operation.id) {
|
||||||
|
.wrapping_add, .wrapping_sub, .wrapping_mul => false,
|
||||||
|
else => true,
|
||||||
|
};
|
||||||
const name = @tagName(binary_operation.id);
|
const name = @tagName(binary_operation.id);
|
||||||
const is_exact = false;
|
const is_exact = false;
|
||||||
const instruction = switch (binary_operation.id) {
|
const instruction = switch (binary_operation.id) {
|
||||||
.add => llvm.builder.createAdd(left, right, name.ptr, name.len, no_unsigned_wrapping, no_signed_wrapping) orelse return LLVM.Value.Instruction.Error.add,
|
.add, .wrapping_add => llvm.builder.createAdd(left, right, name.ptr, name.len, no_unsigned_wrapping, no_signed_wrapping) orelse return LLVM.Value.Instruction.Error.add,
|
||||||
.mul => llvm.builder.createMultiply(left, right, name.ptr, name.len, no_unsigned_wrapping, no_signed_wrapping) orelse return LLVM.Value.Instruction.Error.multiply,
|
.sub, .wrapping_sub => llvm.builder.createSub(left, right, name.ptr, name.len, no_unsigned_wrapping, no_signed_wrapping) orelse return LLVM.Value.Instruction.Error.add,
|
||||||
.sub => llvm.builder.createSub(left, right, name.ptr, name.len, no_unsigned_wrapping, no_signed_wrapping) orelse return LLVM.Value.Instruction.Error.add,
|
.mul, .wrapping_mul => llvm.builder.createMultiply(left, right, name.ptr, name.len, no_unsigned_wrapping, no_signed_wrapping) orelse return LLVM.Value.Instruction.Error.multiply,
|
||||||
.div => switch (binary_operation.signedness) {
|
.div => switch (binary_operation.signedness) {
|
||||||
.unsigned => llvm.builder.createUDiv(left, right, name.ptr, name.len, is_exact) orelse unreachable,
|
.unsigned => llvm.builder.createUDiv(left, right, name.ptr, name.len, is_exact) orelse unreachable,
|
||||||
.signed => llvm.builder.createSDiv(left, right, name.ptr, name.len, is_exact) orelse unreachable,
|
.signed => llvm.builder.createSDiv(left, right, name.ptr, name.len, is_exact) orelse unreachable,
|
||||||
@ -2786,7 +2792,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.unsigned => llvm.builder.createLogicalShiftRight(left, right, name.ptr, name.len, is_exact) orelse unreachable,
|
.unsigned => llvm.builder.createLogicalShiftRight(left, right, name.ptr, name.len, is_exact) orelse unreachable,
|
||||||
.signed => llvm.builder.createArithmeticShiftRight(left, right, name.ptr, name.len, is_exact) orelse unreachable,
|
.signed => llvm.builder.createArithmeticShiftRight(left, right, name.ptr, name.len, is_exact) orelse unreachable,
|
||||||
},
|
},
|
||||||
//else => |t| @panic(@tagName(t)),
|
else => unreachable,
|
||||||
};
|
};
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, instruction);
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, instruction);
|
||||||
},
|
},
|
||||||
|
@ -313,6 +313,26 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
|||||||
index += 1;
|
index += 1;
|
||||||
break :b .operator_add_assign;
|
break :b .operator_add_assign;
|
||||||
},
|
},
|
||||||
|
'|' => b: {
|
||||||
|
index += 1;
|
||||||
|
break :b switch (text[index]) {
|
||||||
|
'=' => assign: {
|
||||||
|
index += 1;
|
||||||
|
break :assign .operator_saturated_add_assign;
|
||||||
|
},
|
||||||
|
else => .operator_saturated_add,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'%' => b: {
|
||||||
|
index += 1;
|
||||||
|
break :b switch (text[index]) {
|
||||||
|
'=' => assign: {
|
||||||
|
index += 1;
|
||||||
|
break :assign .operator_wrapping_add_assign;
|
||||||
|
},
|
||||||
|
else => .operator_wrapping_add,
|
||||||
|
};
|
||||||
|
},
|
||||||
else => .operator_add,
|
else => .operator_add,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -325,6 +345,26 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
|||||||
index += 1;
|
index += 1;
|
||||||
break :b .operator_sub_assign;
|
break :b .operator_sub_assign;
|
||||||
},
|
},
|
||||||
|
'|' => b: {
|
||||||
|
index += 1;
|
||||||
|
break :b switch (text[index]) {
|
||||||
|
'=' => assign: {
|
||||||
|
index += 1;
|
||||||
|
break :assign .operator_saturated_add_assign;
|
||||||
|
},
|
||||||
|
else => .operator_saturated_sub,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'%' => b: {
|
||||||
|
index += 1;
|
||||||
|
break :b switch (text[index]) {
|
||||||
|
'=' => assign: {
|
||||||
|
index += 1;
|
||||||
|
break :assign .operator_wrapping_sub_assign;
|
||||||
|
},
|
||||||
|
else => .operator_wrapping_sub,
|
||||||
|
};
|
||||||
|
},
|
||||||
else => .operator_minus,
|
else => .operator_minus,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -337,6 +377,26 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
|||||||
index += 1;
|
index += 1;
|
||||||
break :b .operator_mul_assign;
|
break :b .operator_mul_assign;
|
||||||
},
|
},
|
||||||
|
'|' => b: {
|
||||||
|
index += 1;
|
||||||
|
break :b switch (text[index]) {
|
||||||
|
'=' => assign: {
|
||||||
|
index += 1;
|
||||||
|
break :assign .operator_saturated_mul_assign;
|
||||||
|
},
|
||||||
|
else => .operator_saturated_mul,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'%' => b: {
|
||||||
|
index += 1;
|
||||||
|
break :b switch (text[index]) {
|
||||||
|
'=' => assign: {
|
||||||
|
index += 1;
|
||||||
|
break :assign .operator_wrapping_mul_assign;
|
||||||
|
},
|
||||||
|
else => .operator_wrapping_mul,
|
||||||
|
};
|
||||||
|
},
|
||||||
else => .operator_asterisk,
|
else => .operator_asterisk,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -206,6 +206,13 @@ pub const Node = struct {
|
|||||||
slice_metadata,
|
slice_metadata,
|
||||||
orelse_expression,
|
orelse_expression,
|
||||||
type,
|
type,
|
||||||
|
or_assign,
|
||||||
|
wrapping_add,
|
||||||
|
saturated_add,
|
||||||
|
wrapping_sub,
|
||||||
|
saturated_sub,
|
||||||
|
wrapping_mul,
|
||||||
|
saturated_mul,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -871,6 +878,7 @@ const Analyzer = struct {
|
|||||||
.operator_mul_assign => .mul_assign,
|
.operator_mul_assign => .mul_assign,
|
||||||
.operator_div_assign => .div_assign,
|
.operator_div_assign => .div_assign,
|
||||||
.operator_mod_assign => .mod_assign,
|
.operator_mod_assign => .mod_assign,
|
||||||
|
.operator_or_assign => .or_assign,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
analyzer.consumeToken();
|
analyzer.consumeToken();
|
||||||
@ -1052,8 +1060,14 @@ const Analyzer = struct {
|
|||||||
compare_less_equal,
|
compare_less_equal,
|
||||||
compare_greater_equal,
|
compare_greater_equal,
|
||||||
add,
|
add,
|
||||||
|
wrapping_add,
|
||||||
|
saturated_add,
|
||||||
sub,
|
sub,
|
||||||
|
wrapping_sub,
|
||||||
|
saturated_sub,
|
||||||
mul,
|
mul,
|
||||||
|
wrapping_mul,
|
||||||
|
saturated_mul,
|
||||||
div,
|
div,
|
||||||
mod,
|
mod,
|
||||||
bit_and,
|
bit_and,
|
||||||
@ -1075,8 +1089,14 @@ const Analyzer = struct {
|
|||||||
.compare_less_equal = 30,
|
.compare_less_equal = 30,
|
||||||
.compare_greater_equal = 30,
|
.compare_greater_equal = 30,
|
||||||
.add = 60,
|
.add = 60,
|
||||||
|
.wrapping_add = 60,
|
||||||
|
.saturated_add = 60,
|
||||||
.sub = 60,
|
.sub = 60,
|
||||||
|
.wrapping_sub = 60,
|
||||||
|
.saturated_sub = 60,
|
||||||
.mul = 70,
|
.mul = 70,
|
||||||
|
.wrapping_mul = 70,
|
||||||
|
.saturated_mul = 70,
|
||||||
.div = 70,
|
.div = 70,
|
||||||
.mod = 70,
|
.mod = 70,
|
||||||
.bit_and = 40,
|
.bit_and = 40,
|
||||||
@ -1098,13 +1118,19 @@ const Analyzer = struct {
|
|||||||
.compare_less_equal = .none,
|
.compare_less_equal = .none,
|
||||||
.compare_greater_equal = .none,
|
.compare_greater_equal = .none,
|
||||||
.add = .left,
|
.add = .left,
|
||||||
|
.wrapping_add = .left,
|
||||||
|
.saturated_add = .left,
|
||||||
.sub = .left,
|
.sub = .left,
|
||||||
|
.wrapping_sub = .left,
|
||||||
|
.saturated_sub = .left,
|
||||||
.bit_and = .left,
|
.bit_and = .left,
|
||||||
.bit_xor = .left,
|
.bit_xor = .left,
|
||||||
.bit_or = .left,
|
.bit_or = .left,
|
||||||
.bool_and = .left,
|
.bool_and = .left,
|
||||||
.bool_or = .left,
|
.bool_or = .left,
|
||||||
.mul = .left,
|
.mul = .left,
|
||||||
|
.wrapping_mul = .left,
|
||||||
|
.saturated_mul = .left,
|
||||||
.div = .left,
|
.div = .left,
|
||||||
.mod = .left,
|
.mod = .left,
|
||||||
.shift_left = .left,
|
.shift_left = .left,
|
||||||
@ -1121,13 +1147,19 @@ const Analyzer = struct {
|
|||||||
.compare_greater_equal = .compare_greater_equal,
|
.compare_greater_equal = .compare_greater_equal,
|
||||||
.compare_less_equal = .compare_less_equal,
|
.compare_less_equal = .compare_less_equal,
|
||||||
.add = .add,
|
.add = .add,
|
||||||
|
.wrapping_add = .wrapping_add,
|
||||||
|
.saturated_add = .saturated_add,
|
||||||
.sub = .sub,
|
.sub = .sub,
|
||||||
|
.wrapping_sub = .wrapping_sub,
|
||||||
|
.saturated_sub = .saturated_sub,
|
||||||
.bit_and = .bit_and,
|
.bit_and = .bit_and,
|
||||||
.bit_xor = .bit_xor,
|
.bit_xor = .bit_xor,
|
||||||
.bit_or = .bit_or,
|
.bit_or = .bit_or,
|
||||||
.bool_and = .bool_and,
|
.bool_and = .bool_and,
|
||||||
.bool_or = .bool_or,
|
.bool_or = .bool_or,
|
||||||
.mul = .mul,
|
.mul = .mul,
|
||||||
|
.wrapping_mul = .wrapping_mul,
|
||||||
|
.saturated_mul = .saturated_mul,
|
||||||
.div = .div,
|
.div = .div,
|
||||||
.mod = .mod,
|
.mod = .mod,
|
||||||
.shift_left = .shift_left,
|
.shift_left = .shift_left,
|
||||||
@ -1162,6 +1194,7 @@ const Analyzer = struct {
|
|||||||
.operator_mul_assign,
|
.operator_mul_assign,
|
||||||
.operator_div_assign,
|
.operator_div_assign,
|
||||||
.operator_mod_assign,
|
.operator_mod_assign,
|
||||||
|
.operator_or_assign,
|
||||||
.operator_dot,
|
.operator_dot,
|
||||||
.operator_double_dot,
|
.operator_double_dot,
|
||||||
.operator_triple_dot,
|
.operator_triple_dot,
|
||||||
@ -1183,8 +1216,14 @@ const Analyzer = struct {
|
|||||||
.operator_compare_less_equal => .compare_less_equal,
|
.operator_compare_less_equal => .compare_less_equal,
|
||||||
.operator_compare_greater_equal => .compare_greater_equal,
|
.operator_compare_greater_equal => .compare_greater_equal,
|
||||||
.operator_add => .add,
|
.operator_add => .add,
|
||||||
|
.operator_wrapping_add => .wrapping_add,
|
||||||
|
.operator_saturated_add => .saturated_add,
|
||||||
.operator_minus => .sub,
|
.operator_minus => .sub,
|
||||||
|
.operator_wrapping_sub => .wrapping_sub,
|
||||||
|
.operator_saturated_sub => .saturated_sub,
|
||||||
.operator_asterisk => .mul,
|
.operator_asterisk => .mul,
|
||||||
|
.operator_wrapping_mul => .wrapping_mul,
|
||||||
|
.operator_saturated_mul => .saturated_mul,
|
||||||
.operator_div => .div,
|
.operator_div => .div,
|
||||||
.operator_mod => .mod,
|
.operator_mod => .mod,
|
||||||
.operator_ampersand => .bit_and,
|
.operator_ampersand => .bit_and,
|
||||||
|
58
src/main.nat
58
src/main.nat
@ -6,6 +6,39 @@ const print = std.print;
|
|||||||
const print_usize = std.print_usize;
|
const print_usize = std.print_usize;
|
||||||
const exit = std.os.exit;
|
const exit = std.os.exit;
|
||||||
|
|
||||||
|
const lex = fn (arena: &Arena, bytes: []const u8) *!void {
|
||||||
|
if (bytes.length >= 0xffffffff) {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
const length: u32 = #cast(bytes.length);
|
||||||
|
|
||||||
|
const max_initial_keyword_len: u32 = 8;
|
||||||
|
|
||||||
|
//var index: u32 = 0;
|
||||||
|
//while (index + 64 < length) {
|
||||||
|
// var i = index;
|
||||||
|
// const top = index + max_initial_keyword_len + 1;
|
||||||
|
// var space: u32 = 0;
|
||||||
|
// while (i < top) {
|
||||||
|
// const is_space = bytes[i] == ' ';
|
||||||
|
// space |= #cast(
|
||||||
|
// i += 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (space == 0) {
|
||||||
|
// unreachable;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileStartToken = enum{
|
||||||
|
"comptime",
|
||||||
|
"test",
|
||||||
|
"const",
|
||||||
|
"var",
|
||||||
|
};
|
||||||
|
|
||||||
const ArgumentProcessingError = error{
|
const ArgumentProcessingError = error{
|
||||||
no_arguments,
|
no_arguments,
|
||||||
};
|
};
|
||||||
@ -58,31 +91,6 @@ const FixedKeyword = enum{
|
|||||||
"continue",
|
"continue",
|
||||||
};
|
};
|
||||||
|
|
||||||
const FileStartToken = enum{
|
|
||||||
"comptime",
|
|
||||||
"test",
|
|
||||||
"const",
|
|
||||||
"var",
|
|
||||||
};
|
|
||||||
|
|
||||||
const lex = fn (arena: &Arena, bytes: []const u8) *!void {
|
|
||||||
if (bytes.length >= 0xffffffff) {
|
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
const length: u32 = #cast(bytes.length);
|
|
||||||
var i: u32 = 0;
|
|
||||||
|
|
||||||
//var index: u32 = 0;
|
|
||||||
//while (index + 64 < length) {
|
|
||||||
// var i = index;
|
|
||||||
// const top = index + 64;
|
|
||||||
// while (i < top) {
|
|
||||||
// i += 1;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
const get_argument = fn (real_argument: []const u8, wanted_argument: []const u8, command_arguments: []const [&:0]const u8, i_ptr: &usize) ?[]const u8 {
|
const get_argument = fn (real_argument: []const u8, wanted_argument: []const u8, command_arguments: []const [&:0]const u8, i_ptr: &usize) ?[]const u8 {
|
||||||
const i = i_ptr.@;
|
const i = i_ptr.@;
|
||||||
|
|
||||||
|
12
test/standalone/wrapping_arithmetic/main.nat
Normal file
12
test/standalone/wrapping_arithmetic/main.nat
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const std = #import("std");
|
||||||
|
const expect = std.testing.expect;
|
||||||
|
const main = fn () *!void {
|
||||||
|
var a: u8 = 255;
|
||||||
|
var b: u8 = 1;
|
||||||
|
const result = a +% b;
|
||||||
|
try expect(result == 0);
|
||||||
|
var c: u16 = 0;
|
||||||
|
var d: u16 = 1;
|
||||||
|
const sub_result = c -% d;
|
||||||
|
try expect(sub_result == 65535);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user