Implement basic tests and error unions
This commit is contained in:
parent
3a78cfe11d
commit
e9e5165345
File diff suppressed because it is too large
Load Diff
@ -1180,7 +1180,13 @@ pub const LLVM = struct {
|
|||||||
for (sema_function_prototype.argument_types) |argument_type_index| {
|
for (sema_function_prototype.argument_types) |argument_type_index| {
|
||||||
switch (unit.types.get(argument_type_index).*) {
|
switch (unit.types.get(argument_type_index).*) {
|
||||||
// TODO: ABI
|
// TODO: ABI
|
||||||
.integer, .pointer, .@"enum", .@"struct", .slice, .bool, => try parameter_types.append(context.allocator, try llvm.getType(unit, context, argument_type_index)),
|
.integer,
|
||||||
|
.pointer,
|
||||||
|
.@"enum",
|
||||||
|
.@"struct",
|
||||||
|
.slice,
|
||||||
|
.bool,
|
||||||
|
=> try parameter_types.append(context.allocator, try llvm.getType(unit, context, argument_type_index)),
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
// arg_types.appendAssumeCapacity(llvm_argument_type);
|
// arg_types.appendAssumeCapacity(llvm_argument_type);
|
||||||
@ -1262,6 +1268,39 @@ pub const LLVM = struct {
|
|||||||
const array_type = LLVM.Type.Array.get(element_type, array.count + @intFromBool(extra_element)) orelse return Type.Error.array;
|
const array_type = LLVM.Type.Array.get(element_type, array.count + @intFromBool(extra_element)) orelse return Type.Error.array;
|
||||||
break :blk array_type.toType();
|
break :blk array_type.toType();
|
||||||
},
|
},
|
||||||
|
.error_union => |error_union| {
|
||||||
|
const error_type = try llvm.getType(unit, context, error_union.@"error");
|
||||||
|
const payload_type = try llvm.getType(unit, context, error_union.type);
|
||||||
|
const payload_type_size = unit.types.get(error_union.type).getBitSize(unit);
|
||||||
|
|
||||||
|
switch (payload_type_size) {
|
||||||
|
0 => {
|
||||||
|
const integer_type = llvm.context.getIntegerType(31) orelse unreachable;
|
||||||
|
const boolean_type = try llvm.getType(unit, context, .bool);
|
||||||
|
const types = [2]*LLVM.Type{ integer_type.toType(), boolean_type };
|
||||||
|
const is_packed = false;
|
||||||
|
const struct_type = llvm.context.getStructType(&types, types.len, is_packed) orelse return Type.Error.@"struct";
|
||||||
|
return struct_type.toType();
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
_ = error_type;
|
||||||
|
_ = payload_type;
|
||||||
|
unreachable;
|
||||||
|
},
|
||||||
|
.error_set => |error_set_index| b: {
|
||||||
|
const error_set = unit.error_sets.get(error_set_index);
|
||||||
|
if (error_set.values.items.len > 0) {
|
||||||
|
unreachable;
|
||||||
|
} else {
|
||||||
|
const integer_type = llvm.context.getIntegerType(32) orelse unreachable;
|
||||||
|
break :b integer_type.toType();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.@"error" => b: {
|
||||||
|
const integer_type = llvm.context.getIntegerType(31) orelse unreachable;
|
||||||
|
break :b integer_type.toType();
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1327,7 +1366,13 @@ pub const LLVM = struct {
|
|||||||
|
|
||||||
break :b name.items;
|
break :b name.items;
|
||||||
} else {
|
} else {
|
||||||
unreachable;
|
if (unit.type_declarations.get(sema_type_index)) |type_declaration| {
|
||||||
|
_ = type_declaration; // autofix
|
||||||
|
unreachable;
|
||||||
|
} else {
|
||||||
|
// TODO: fix
|
||||||
|
break :b "anon_struct";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO: termination
|
// TODO: termination
|
||||||
@ -2031,7 +2076,7 @@ pub const LLVM = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emitComptimeRightValue(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, ct: Compilation.V.Comptime, type_index: Compilation.Type.Index) !*LLVM.Value.Constant {
|
fn emitComptimeRightValue(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, ct: Compilation.V.Comptime, type_index: Compilation.Type.Index) anyerror!*LLVM.Value.Constant {
|
||||||
switch (ct) {
|
switch (ct) {
|
||||||
.constant_int => |integer| {
|
.constant_int => |integer| {
|
||||||
const integer_type = unit.types.get(type_index);
|
const integer_type = unit.types.get(type_index);
|
||||||
@ -2083,21 +2128,7 @@ pub const LLVM = struct {
|
|||||||
const constant_int = llvm.context.getConstantInt(backing_integer_type.bit_count, value, signed) orelse unreachable;
|
const constant_int = llvm.context.getConstantInt(backing_integer_type.bit_count, value, signed) orelse unreachable;
|
||||||
return constant_int.toConstant();
|
return constant_int.toConstant();
|
||||||
},
|
},
|
||||||
.constant_struct => |constant_struct_index| {
|
.constant_struct => |constant_struct_index| return try llvm.getConstantStruct(unit, context, constant_struct_index),
|
||||||
const constant_struct = unit.constant_structs.get(constant_struct_index);
|
|
||||||
var field_values = try ArrayList(*LLVM.Value.Constant).initCapacity(context.allocator, constant_struct.fields.len);
|
|
||||||
const sema_struct_type = unit.structs.get(unit.types.get(constant_struct.type).@"struct");
|
|
||||||
for (constant_struct.fields, sema_struct_type.fields.items) |field_value, field_index| {
|
|
||||||
const field = unit.struct_fields.get(field_index);
|
|
||||||
const constant = try llvm.emitComptimeRightValue(unit, context, field_value, field.type);
|
|
||||||
field_values.appendAssumeCapacity(constant);
|
|
||||||
}
|
|
||||||
|
|
||||||
const llvm_type = try llvm.getType(unit, context, constant_struct.type);
|
|
||||||
const struct_type = llvm_type.toStruct() orelse unreachable;
|
|
||||||
const const_struct = struct_type.getConstant(field_values.items.ptr, field_values.items.len) orelse unreachable;
|
|
||||||
return const_struct;
|
|
||||||
},
|
|
||||||
.undefined => {
|
.undefined => {
|
||||||
const undefined_type = try llvm.getType(unit, context, type_index);
|
const undefined_type = try llvm.getType(unit, context, type_index);
|
||||||
const poison = undefined_type.getPoison() orelse unreachable;
|
const poison = undefined_type.getPoison() orelse unreachable;
|
||||||
@ -2130,6 +2161,13 @@ pub const LLVM = struct {
|
|||||||
const constant_null_pointer = pointer_type.getNull();
|
const constant_null_pointer = pointer_type.getNull();
|
||||||
return constant_null_pointer.toConstant();
|
return constant_null_pointer.toConstant();
|
||||||
},
|
},
|
||||||
|
.error_value => |error_field_index| {
|
||||||
|
const error_field = unit.error_fields.get(error_field_index);
|
||||||
|
const signed = false;
|
||||||
|
const bit_count = 31;
|
||||||
|
const constant_int = llvm.context.getConstantInt(bit_count, error_field.value, signed) orelse unreachable;
|
||||||
|
return constant_int.toConstant();
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2192,9 +2230,10 @@ pub const LLVM = struct {
|
|||||||
const const_slice = unit.constant_slices.get(constant_slice_index);
|
const const_slice = unit.constant_slices.get(constant_slice_index);
|
||||||
const const_slice_type = try llvm.getType(unit, context, const_slice.type);
|
const const_slice_type = try llvm.getType(unit, context, const_slice.type);
|
||||||
const slice_struct_type = const_slice_type.toStruct() orelse unreachable;
|
const slice_struct_type = const_slice_type.toStruct() orelse unreachable;
|
||||||
const ptr = llvm.global_variable_map.get(const_slice.ptr).?;
|
const ptr = llvm.global_variable_map.get(const_slice.array).?;
|
||||||
const signed = false;
|
const signed = false;
|
||||||
const len = llvm.context.getConstantInt(@bitSizeOf(usize), const_slice.len, signed) orelse unreachable;
|
assert(const_slice.start == 0);
|
||||||
|
const len = llvm.context.getConstantInt(@bitSizeOf(usize), const_slice.end, signed) orelse unreachable;
|
||||||
const slice_fields = [2]*LLVM.Value.Constant{
|
const slice_fields = [2]*LLVM.Value.Constant{
|
||||||
ptr.toConstant(),
|
ptr.toConstant(),
|
||||||
len.toConstant(),
|
len.toConstant(),
|
||||||
@ -2223,6 +2262,7 @@ pub const LLVM = struct {
|
|||||||
break :b constant_int.toConstant();
|
break :b constant_int.toConstant();
|
||||||
},
|
},
|
||||||
.constant_slice => |constant_slice_index| try llvm.getConstantSlice(unit, context, constant_slice_index),
|
.constant_slice => |constant_slice_index| try llvm.getConstantSlice(unit, context, constant_slice_index),
|
||||||
|
.constant_struct => |constant_struct_index| try llvm.getConstantStruct(unit, context, constant_struct_index),
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
list.appendAssumeCapacity(value);
|
list.appendAssumeCapacity(value);
|
||||||
@ -2232,6 +2272,22 @@ pub const LLVM = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn getConstantStruct(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, constant_struct_index: Compilation.V.Comptime.ConstantStruct.Index) !*LLVM.Value.Constant {
|
||||||
|
const constant_struct = unit.constant_structs.get(constant_struct_index);
|
||||||
|
var field_values = try ArrayList(*LLVM.Value.Constant).initCapacity(context.allocator, constant_struct.fields.len);
|
||||||
|
const sema_struct_type = unit.structs.get(unit.types.get(constant_struct.type).@"struct");
|
||||||
|
for (constant_struct.fields, sema_struct_type.fields.items) |field_value, field_index| {
|
||||||
|
const field = unit.struct_fields.get(field_index);
|
||||||
|
const constant = try llvm.emitComptimeRightValue(unit, context, field_value, field.type);
|
||||||
|
field_values.appendAssumeCapacity(constant);
|
||||||
|
}
|
||||||
|
|
||||||
|
const llvm_type = try llvm.getType(unit, context, constant_struct.type);
|
||||||
|
const struct_type = llvm_type.toStruct() orelse unreachable;
|
||||||
|
const const_struct = struct_type.getConstant(field_values.items.ptr, field_values.items.len) orelse unreachable;
|
||||||
|
return const_struct;
|
||||||
|
}
|
||||||
|
|
||||||
fn callIntrinsic(llvm: *LLVM, intrinsic_name: []const u8, intrinsic_parameter_types: []const *LLVM.Type, intrinsic_arguments: []const *LLVM.Value) !*LLVM.Value {
|
fn callIntrinsic(llvm: *LLVM, intrinsic_name: []const u8, intrinsic_parameter_types: []const *LLVM.Type, intrinsic_arguments: []const *LLVM.Value) !*LLVM.Value {
|
||||||
const intrinsic_id = LLVM.lookupIntrinsic(intrinsic_name.ptr, intrinsic_name.len);
|
const intrinsic_id = LLVM.lookupIntrinsic(intrinsic_name.ptr, intrinsic_name.len);
|
||||||
assert(intrinsic_id != .none);
|
assert(intrinsic_id != .none);
|
||||||
@ -2354,7 +2410,6 @@ pub const LLVM = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getCallingConvention(calling_convention: Compilation.Function.CallingConvention) LLVM.Value.Constant.Function.CallingConvention {
|
fn getCallingConvention(calling_convention: Compilation.Function.CallingConvention) LLVM.Value.Constant.Function.CallingConvention {
|
||||||
@ -2508,6 +2563,8 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
const entry_block_node = try llvm.createBasicBlock(context, function_definition.basic_blocks.items[0], "fn_entry");
|
const entry_block_node = try llvm.createBasicBlock(context, function_definition.basic_blocks.items[0], "fn_entry");
|
||||||
block_command_list.append(entry_block_node);
|
block_command_list.append(entry_block_node);
|
||||||
|
|
||||||
|
var phis = AutoArrayHashMap(Compilation.Instruction.Index, *LLVM.Value.Instruction.PhiNode){};
|
||||||
|
|
||||||
while (block_command_list.len != 0) {
|
while (block_command_list.len != 0) {
|
||||||
const block_node = block_command_list.first orelse unreachable;
|
const block_node = block_command_list.first orelse unreachable;
|
||||||
const basic_block_index = block_node.data;
|
const basic_block_index = block_node.data;
|
||||||
@ -2625,14 +2682,8 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
switch (unit.types.get(stack_slot.type).*) {
|
switch (unit.types.get(stack_slot.type).*) {
|
||||||
.void, .noreturn, .type => unreachable,
|
.void, .noreturn, .type => unreachable,
|
||||||
.comptime_int => unreachable,
|
.comptime_int => unreachable,
|
||||||
.bool => {},
|
|
||||||
.@"struct" => {},
|
|
||||||
.@"enum" => {},
|
|
||||||
.function => unreachable,
|
.function => unreachable,
|
||||||
.integer => {},
|
else => {},
|
||||||
.pointer => {},
|
|
||||||
.slice => {},
|
|
||||||
.array => {},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const declaration_type = try llvm.getType(unit, context, stack_slot.type);
|
const declaration_type = try llvm.getType(unit, context, stack_slot.type);
|
||||||
@ -2769,7 +2820,6 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
for (call.arguments, arguments) |argument_value, *argument| {
|
for (call.arguments, arguments) |argument_value, *argument| {
|
||||||
argument.* = try llvm.emitRightValue(unit, context, argument_value);
|
argument.* = try llvm.emitRightValue(unit, context, argument_value);
|
||||||
}
|
}
|
||||||
@ -2883,15 +2933,8 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
switch (unit.types.get(argument_type_index).*) {
|
switch (unit.types.get(argument_type_index).*) {
|
||||||
.void, .noreturn, .type => unreachable,
|
.void, .noreturn, .type => unreachable,
|
||||||
.comptime_int => unreachable,
|
.comptime_int => unreachable,
|
||||||
.bool => {},
|
|
||||||
// .bool => unreachable,
|
|
||||||
.@"struct" => {},
|
|
||||||
.@"enum" => {},
|
|
||||||
.function => unreachable,
|
.function => unreachable,
|
||||||
.integer => {},
|
else => {},
|
||||||
.pointer => {},
|
|
||||||
.slice => {},
|
|
||||||
.array => {},
|
|
||||||
}
|
}
|
||||||
const argument_type = argument.toValue().getType();
|
const argument_type = argument.toValue().getType();
|
||||||
const alloca_array_size: ?*LLVM.Value = null;
|
const alloca_array_size: ?*LLVM.Value = null;
|
||||||
@ -3047,6 +3090,8 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
const not_taken_node = try llvm.createBasicBlock(context, branch.not_taken, "not_taken_block");
|
const not_taken_node = try llvm.createBasicBlock(context, branch.not_taken, "not_taken_block");
|
||||||
block_command_list.insertAfter(block_node, taken_node);
|
block_command_list.insertAfter(block_node, taken_node);
|
||||||
block_command_list.insertAfter(taken_node, not_taken_node);
|
block_command_list.insertAfter(taken_node, not_taken_node);
|
||||||
|
// block_command_list.append(taken_node);
|
||||||
|
// block_command_list.append(taken_node);
|
||||||
|
|
||||||
// TODO: make this fast
|
// TODO: make this fast
|
||||||
const taken_block = llvm.llvm_block_map.get(taken_node.data).?;
|
const taken_block = llvm.llvm_block_map.get(taken_node.data).?;
|
||||||
@ -3064,11 +3109,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
const phi_name = "phi";
|
const phi_name = "phi";
|
||||||
const phi_node = llvm.builder.createPhi(phi_type, reserved_value_count, phi_name, phi_name.len) orelse unreachable;
|
const phi_node = llvm.builder.createPhi(phi_type, reserved_value_count, phi_name, phi_name.len) orelse unreachable;
|
||||||
|
|
||||||
for (phi.values.items, phi.basic_blocks.items) |sema_value, sema_block| {
|
try phis.putNoClobber(context.allocator, instruction_index, phi_node);
|
||||||
const value = llvm.llvm_value_map.get(sema_value) orelse try llvm.emitRightValue(unit, context, sema_value);
|
|
||||||
const value_basic_block = llvm.llvm_block_map.get(sema_block).?;
|
|
||||||
phi_node.addIncoming(value, value_basic_block);
|
|
||||||
}
|
|
||||||
|
|
||||||
try llvm.llvm_instruction_map.putNoClobber(context.allocator, instruction_index, phi_node.toValue());
|
try llvm.llvm_instruction_map.putNoClobber(context.allocator, instruction_index, phi_node.toValue());
|
||||||
},
|
},
|
||||||
@ -3106,6 +3147,16 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
_ = block_command_list.popFirst();
|
_ = block_command_list.popFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (phis.keys(), phis.values()) |instruction_index, phi| {
|
||||||
|
const instruction = unit.instructions.get(instruction_index);
|
||||||
|
const sema_phi = instruction.phi;
|
||||||
|
for (sema_phi.values.items, sema_phi.basic_blocks.items) |sema_value, sema_block| {
|
||||||
|
const value_basic_block = llvm.llvm_block_map.get(sema_block).?;
|
||||||
|
const value = llvm.llvm_value_map.get(sema_value) orelse try llvm.emitRightValue(unit, context, sema_value);
|
||||||
|
phi.addIncoming(value, value_basic_block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!builder.isCurrentBlockTerminated()) {
|
if (!builder.isCurrentBlockTerminated()) {
|
||||||
var message_len: usize = 0;
|
var message_len: usize = 0;
|
||||||
const function_str = llvm.function.toString(&message_len);
|
const function_str = llvm.function.toString(&message_len);
|
||||||
@ -3228,7 +3279,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
try arguments.append(context.allocator, "-lSystem");
|
try arguments.append(context.allocator, "-lSystem");
|
||||||
},
|
},
|
||||||
.linux => {
|
.linux => {
|
||||||
try arguments.appendSlice(context.allocator, &.{"--entry", "_start"});
|
try arguments.appendSlice(context.allocator, &.{ "--entry", "_start" });
|
||||||
try arguments.append(context.allocator, "-m");
|
try arguments.append(context.allocator, "-m");
|
||||||
try arguments.append(context.allocator, switch (unit.descriptor.target.cpu.arch) {
|
try arguments.append(context.allocator, switch (unit.descriptor.target.cpu.arch) {
|
||||||
.x86_64 => "elf_x86_64",
|
.x86_64 => "elf_x86_64",
|
||||||
@ -3238,8 +3289,8 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
if (unit.descriptor.link_libc) {
|
if (unit.descriptor.link_libc) {
|
||||||
try arguments.append(context.allocator, "/usr/lib/crt1.o");
|
try arguments.append(context.allocator, "/usr/lib/crt1.o");
|
||||||
try arguments.append(context.allocator, "/usr/lib/crti.o");
|
try arguments.append(context.allocator, "/usr/lib/crti.o");
|
||||||
try arguments.appendSlice(context.allocator, &.{"-L", "/usr/lib"});
|
try arguments.appendSlice(context.allocator, &.{ "-L", "/usr/lib" });
|
||||||
try arguments.appendSlice(context.allocator, &.{"-dynamic-linker", "/lib64/ld-linux-x86-64.so.2"});
|
try arguments.appendSlice(context.allocator, &.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||||
try arguments.append(context.allocator, "--as-needed");
|
try arguments.append(context.allocator, "--as-needed");
|
||||||
try arguments.append(context.allocator, "-lm");
|
try arguments.append(context.allocator, "-lm");
|
||||||
try arguments.append(context.allocator, "-lpthread");
|
try arguments.append(context.allocator, "-lpthread");
|
||||||
|
@ -100,7 +100,7 @@ pub fn getIndexForType(comptime T: type, comptime E: type) type {
|
|||||||
const EnumField = std.builtin.Type.EnumField;
|
const EnumField = std.builtin.Type.EnumField;
|
||||||
comptime var fields: []const EnumField = &.{};
|
comptime var fields: []const EnumField = &.{};
|
||||||
// comptime var enum_value: comptime_int = 0;
|
// comptime var enum_value: comptime_int = 0;
|
||||||
fields = fields ++ @typeInfo(E).Enum.fields;
|
fields = fields ++ @typeInfo(E).Enum.fields;
|
||||||
|
|
||||||
// for (names) |name| {
|
// for (names) |name| {
|
||||||
// fields = fields ++ [1]EnumField{.{
|
// fields = fields ++ [1]EnumField{.{
|
||||||
@ -137,32 +137,31 @@ pub fn getIndexForType(comptime T: type, comptime E: type) type {
|
|||||||
return @enumFromInt(value);
|
return @enumFromInt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addInt(this: Index, value: IndexType) Index{
|
pub fn addInt(this: Index, value: IndexType) Index {
|
||||||
const this_int = @intFromEnum(this);
|
const this_int = @intFromEnum(this);
|
||||||
return @enumFromInt(this_int + value);
|
return @enumFromInt(this_int + value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subInt(this: Index, value: IndexType) IndexType{
|
pub fn subInt(this: Index, value: IndexType) IndexType {
|
||||||
const this_int = @intFromEnum(this);
|
const this_int = @intFromEnum(this);
|
||||||
return this_int - value;
|
return this_int - value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(a: Index, b: Index) Index{
|
pub fn add(a: Index, b: Index) Index {
|
||||||
return @enumFromInt(@intFromEnum(a) + @intFromEnum(b));
|
return @enumFromInt(@intFromEnum(a) + @intFromEnum(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub(a: Index, b: Index) IndexType{
|
pub fn sub(a: Index, b: Index) IndexType {
|
||||||
return @intFromEnum(a) - @intFromEnum(b);
|
return @intFromEnum(a) - @intFromEnum(b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ListType = enum{
|
pub const ListType = enum {
|
||||||
index,
|
index,
|
||||||
pointer,
|
pointer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
pub fn enumFromString(comptime E: type, string: []const u8) ?E {
|
pub fn enumFromString(comptime E: type, string: []const u8) ?E {
|
||||||
return inline for (@typeInfo(E).Enum.fields) |enum_field| {
|
return inline for (@typeInfo(E).Enum.fields) |enum_field| {
|
||||||
if (std.mem.eql(u8, string, enum_field.name)) {
|
if (std.mem.eql(u8, string, enum_field.name)) {
|
||||||
|
@ -15,7 +15,6 @@ const logln = Compilation.logln;
|
|||||||
const Token = Compilation.Token;
|
const Token = Compilation.Token;
|
||||||
const fs = @import("../fs.zig");
|
const fs = @import("../fs.zig");
|
||||||
|
|
||||||
|
|
||||||
// Needed information
|
// Needed information
|
||||||
// Token: u8
|
// Token: u8
|
||||||
// line: u32
|
// line: u32
|
||||||
@ -76,7 +75,7 @@ pub fn analyze(allocator: Allocator, text: []const u8, token_buffer: *Token.Buff
|
|||||||
|
|
||||||
try token_buffer.tokens.ensureUnusedCapacity(allocator, text.len / 4);
|
try token_buffer.tokens.ensureUnusedCapacity(allocator, text.len / 4);
|
||||||
|
|
||||||
logln(.lexer, .end, "START LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{Token.unwrap(lexer.offset), lexer.line_offset});
|
logln(.lexer, .end, "START LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{ Token.unwrap(lexer.offset), lexer.line_offset });
|
||||||
|
|
||||||
while (index < len) {
|
while (index < len) {
|
||||||
const start_index = index;
|
const start_index = index;
|
||||||
@ -229,7 +228,7 @@ pub fn analyze(allocator: Allocator, text: []const u8, token_buffer: *Token.Buff
|
|||||||
index += 1;
|
index += 1;
|
||||||
break :blk .operator_compare_less_equal;
|
break :blk .operator_compare_less_equal;
|
||||||
},
|
},
|
||||||
else =>break :blk .operator_compare_less,
|
else => break :blk .operator_compare_less,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'>' => blk: {
|
'>' => blk: {
|
||||||
@ -249,7 +248,7 @@ pub fn analyze(allocator: Allocator, text: []const u8, token_buffer: *Token.Buff
|
|||||||
index += 1;
|
index += 1;
|
||||||
break :blk .operator_compare_greater_equal;
|
break :blk .operator_compare_greater_equal;
|
||||||
},
|
},
|
||||||
else =>break :blk .operator_compare_greater,
|
else => break :blk .operator_compare_greater,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
';' => blk: {
|
';' => blk: {
|
||||||
@ -281,7 +280,6 @@ pub fn analyze(allocator: Allocator, text: []const u8, token_buffer: *Token.Buff
|
|||||||
},
|
},
|
||||||
else => break :blk .operator_bang,
|
else => break :blk .operator_bang,
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
'=' => blk: {
|
'=' => blk: {
|
||||||
index += 1;
|
index += 1;
|
||||||
@ -421,10 +419,10 @@ pub fn analyze(allocator: Allocator, text: []const u8, token_buffer: *Token.Buff
|
|||||||
});
|
});
|
||||||
const line_offset = token_buffer.line_offsets.items[line_index];
|
const line_offset = token_buffer.line_offsets.items[line_index];
|
||||||
const column = start_index - line_offset;
|
const column = start_index - line_offset;
|
||||||
logln(.lexer, .new_token, "T at line {}, column {}, byte offset {}, with length {} -line offset: {}- ({s})", .{line_index, column, start_index, token_length, line_offset, @tagName(token_id)});
|
logln(.lexer, .new_token, "T at line {}, column {}, byte offset {}, with length {} -line offset: {}- ({s})", .{ line_index, column, start_index, token_length, line_offset, @tagName(token_id) });
|
||||||
}
|
}
|
||||||
|
|
||||||
logln(.lexer, .end, "END LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{Token.unwrap(lexer.offset), lexer.line_offset});
|
logln(.lexer, .end, "END LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{ Token.unwrap(lexer.offset), lexer.line_offset });
|
||||||
|
|
||||||
lexer.count = Token.sub(token_buffer.getOffset(), lexer.offset);
|
lexer.count = Token.sub(token_buffer.getOffset(), lexer.offset);
|
||||||
lexer.line_count = token_buffer.getLineOffset() - lexer.line_offset;
|
lexer.line_count = token_buffer.getLineOffset() - lexer.line_offset;
|
||||||
|
@ -65,7 +65,7 @@ pub const Node = struct {
|
|||||||
token: Token.Index,
|
token: Token.Index,
|
||||||
id: Id,
|
id: Id,
|
||||||
|
|
||||||
pub const List = BlockList(@This(), enum{});
|
pub const List = BlockList(@This(), enum {});
|
||||||
pub usingnamespace List.Index;
|
pub usingnamespace List.Index;
|
||||||
|
|
||||||
pub const Range = struct {
|
pub const Range = struct {
|
||||||
@ -187,6 +187,9 @@ pub const Node = struct {
|
|||||||
test_declaration,
|
test_declaration,
|
||||||
all_errors,
|
all_errors,
|
||||||
error_union,
|
error_union,
|
||||||
|
catch_expression,
|
||||||
|
try_expression,
|
||||||
|
error_type,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -307,7 +310,9 @@ const Analyzer = struct {
|
|||||||
if (equal(u8, identifier_name, enum_field.name)) {
|
if (equal(u8, identifier_name, enum_field.name)) {
|
||||||
const attribute = @field(Compilation.Debug.Declaration.Global.Attribute, enum_field.name);
|
const attribute = @field(Compilation.Debug.Declaration.Global.Attribute, enum_field.name);
|
||||||
const attribute_node = switch (attribute) {
|
const attribute_node = switch (attribute) {
|
||||||
.@"export", .@"extern", => try analyzer.addNode(.{
|
.@"export",
|
||||||
|
.@"extern",
|
||||||
|
=> try analyzer.addNode(.{
|
||||||
.id = @field(Node.Id, "symbol_attribute_" ++ @tagName(attribute)),
|
.id = @field(Node.Id, "symbol_attribute_" ++ @tagName(attribute)),
|
||||||
.token = identifier,
|
.token = identifier,
|
||||||
.left = .null,
|
.left = .null,
|
||||||
@ -393,7 +398,8 @@ const Analyzer = struct {
|
|||||||
if (equal(u8, identifier_name, enum_field.name)) {
|
if (equal(u8, identifier_name, enum_field.name)) {
|
||||||
const attribute = @field(Compilation.Function.Attribute, enum_field.name);
|
const attribute = @field(Compilation.Function.Attribute, enum_field.name);
|
||||||
const attribute_node = switch (attribute) {
|
const attribute_node = switch (attribute) {
|
||||||
.naked, => try analyzer.addNode(.{
|
.naked,
|
||||||
|
=> try analyzer.addNode(.{
|
||||||
.id = @field(Node.Id, "function_attribute_" ++ @tagName(attribute)),
|
.id = @field(Node.Id, "function_attribute_" ++ @tagName(attribute)),
|
||||||
.token = identifier,
|
.token = identifier,
|
||||||
.left = .null,
|
.left = .null,
|
||||||
@ -420,7 +426,7 @@ const Analyzer = struct {
|
|||||||
.id = .function_prototype,
|
.id = .function_prototype,
|
||||||
.token = token,
|
.token = token,
|
||||||
.left = arguments,
|
.left = arguments,
|
||||||
.right = try analyzer.nodeList( attribute_and_return_type_node_list),
|
.right = try analyzer.nodeList(attribute_and_return_type_node_list),
|
||||||
});
|
});
|
||||||
|
|
||||||
return function_prototype;
|
return function_prototype;
|
||||||
@ -473,16 +479,17 @@ const Analyzer = struct {
|
|||||||
const first_statement_token = analyzer.peekToken();
|
const first_statement_token = analyzer.peekToken();
|
||||||
logln(.parser, .block, "First statement token: {s}", .{@tagName(first_statement_token)});
|
logln(.parser, .block, "First statement token: {s}", .{@tagName(first_statement_token)});
|
||||||
const statement_index = switch (first_statement_token) {
|
const statement_index = switch (first_statement_token) {
|
||||||
.identifier => switch (analyzer.peekTokenAhead(1)) {
|
else => try analyzer.assignExpressionStatement(),
|
||||||
.operator_colon => {
|
// .identifier => switch (analyzer.peekTokenAhead(1)) {
|
||||||
unreachable;
|
// .operator_colon => {
|
||||||
},
|
// unreachable;
|
||||||
else => try analyzer.assignExpressionStatement(),
|
// },
|
||||||
},
|
// else => try analyzer.assignExpressionStatement(),
|
||||||
.fixed_keyword_unreachable,
|
// },
|
||||||
.fixed_keyword_return,
|
// .fixed_keyword_unreachable,
|
||||||
.discard,
|
// .fixed_keyword_return,
|
||||||
=> try analyzer.assignExpressionStatement(),
|
// .discard,
|
||||||
|
// => try analyzer.assignExpressionStatement(),
|
||||||
|
|
||||||
.fixed_keyword_while => try analyzer.whileExpression(),
|
.fixed_keyword_while => try analyzer.whileExpression(),
|
||||||
.fixed_keyword_switch => try analyzer.switchExpression(),
|
.fixed_keyword_switch => try analyzer.switchExpression(),
|
||||||
@ -491,17 +498,12 @@ const Analyzer = struct {
|
|||||||
.fixed_keyword_const,
|
.fixed_keyword_const,
|
||||||
.fixed_keyword_var,
|
.fixed_keyword_var,
|
||||||
=> try analyzer.symbolDeclaration(),
|
=> try analyzer.symbolDeclaration(),
|
||||||
.fixed_keyword_break => b: {
|
// .intrinsic => blk: {
|
||||||
const node_index = try analyzer.breakExpression();
|
// const intrinsic = try analyzer.compilerIntrinsic();
|
||||||
_ = try analyzer.expectToken(.operator_semicolon);
|
// _ = try analyzer.expectToken(.operator_semicolon);
|
||||||
break :b node_index;
|
// break :blk intrinsic;
|
||||||
},
|
// },
|
||||||
.intrinsic => blk: {
|
// else => |t| @panic(@tagName(t)),
|
||||||
const intrinsic = try analyzer.compilerIntrinsic();
|
|
||||||
_ = try analyzer.expectToken(.operator_semicolon);
|
|
||||||
break :blk intrinsic;
|
|
||||||
},
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const node = analyzer.nodes.get(statement_index);
|
const node = analyzer.nodes.get(statement_index);
|
||||||
@ -783,7 +785,7 @@ const Analyzer = struct {
|
|||||||
const left = try analyzer.expression();
|
const left = try analyzer.expression();
|
||||||
const expression_token = analyzer.token_i;
|
const expression_token = analyzer.token_i;
|
||||||
const expression_id: Node.Id = switch (analyzer.peekToken()) {
|
const expression_id: Node.Id = switch (analyzer.peekToken()) {
|
||||||
.operator_semicolon, .operator_comma => return left,
|
.operator_semicolon, .operator_comma, .operator_right_brace, .identifier => return left,
|
||||||
.operator_assign => .assign,
|
.operator_assign => .assign,
|
||||||
.operator_add_assign => .add_assign,
|
.operator_add_assign => .add_assign,
|
||||||
.operator_sub_assign => .sub_assign,
|
.operator_sub_assign => .sub_assign,
|
||||||
@ -951,6 +953,7 @@ const Analyzer = struct {
|
|||||||
bit_or,
|
bit_or,
|
||||||
shift_left,
|
shift_left,
|
||||||
shift_right,
|
shift_right,
|
||||||
|
@"catch",
|
||||||
};
|
};
|
||||||
|
|
||||||
const operator_precedence = std.EnumArray(PrecedenceOperator, i32).init(.{
|
const operator_precedence = std.EnumArray(PrecedenceOperator, i32).init(.{
|
||||||
@ -970,6 +973,7 @@ const Analyzer = struct {
|
|||||||
.bit_or = 40,
|
.bit_or = 40,
|
||||||
.shift_left = 50,
|
.shift_left = 50,
|
||||||
.shift_right = 50,
|
.shift_right = 50,
|
||||||
|
.@"catch" = 40,
|
||||||
});
|
});
|
||||||
|
|
||||||
const operator_associativity = std.EnumArray(PrecedenceOperator, Associativity).init(.{
|
const operator_associativity = std.EnumArray(PrecedenceOperator, Associativity).init(.{
|
||||||
@ -989,6 +993,7 @@ const Analyzer = struct {
|
|||||||
.mod = .left,
|
.mod = .left,
|
||||||
.shift_left = .left,
|
.shift_left = .left,
|
||||||
.shift_right = .left,
|
.shift_right = .left,
|
||||||
|
.@"catch" = .left,
|
||||||
});
|
});
|
||||||
|
|
||||||
const operator_node_id = std.EnumArray(PrecedenceOperator, Node.Id).init(.{
|
const operator_node_id = std.EnumArray(PrecedenceOperator, Node.Id).init(.{
|
||||||
@ -1008,6 +1013,7 @@ const Analyzer = struct {
|
|||||||
.mod = .mod,
|
.mod = .mod,
|
||||||
.shift_left = .shift_left,
|
.shift_left = .shift_left,
|
||||||
.shift_right = .shift_right,
|
.shift_right = .shift_right,
|
||||||
|
.@"catch" = .catch_expression,
|
||||||
});
|
});
|
||||||
|
|
||||||
fn expressionPrecedence(analyzer: *Analyzer, minimum_precedence: i32) !Node.Index {
|
fn expressionPrecedence(analyzer: *Analyzer, minimum_precedence: i32) !Node.Index {
|
||||||
@ -1062,6 +1068,7 @@ const Analyzer = struct {
|
|||||||
.operator_xor => .bit_xor,
|
.operator_xor => .bit_xor,
|
||||||
.operator_shift_left => .shift_left,
|
.operator_shift_left => .shift_left,
|
||||||
.operator_shift_right => .shift_right,
|
.operator_shift_right => .shift_right,
|
||||||
|
.fixed_keyword_catch => .@"catch",
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1114,6 +1121,7 @@ const Analyzer = struct {
|
|||||||
},
|
},
|
||||||
.operator_bang => .boolean_not,
|
.operator_bang => .boolean_not,
|
||||||
.operator_minus => .negation,
|
.operator_minus => .negation,
|
||||||
|
.fixed_keyword_try => .try_expression,
|
||||||
// .tilde => |t| @panic(@tagName(t)),
|
// .tilde => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1155,6 +1163,9 @@ const Analyzer = struct {
|
|||||||
.discard,
|
.discard,
|
||||||
.fixed_keyword_undefined,
|
.fixed_keyword_undefined,
|
||||||
.operator_left_bracket,
|
.operator_left_bracket,
|
||||||
|
.fixed_keyword_const,
|
||||||
|
.fixed_keyword_var,
|
||||||
|
.fixed_keyword_error,
|
||||||
=> try analyzer.curlySuffixExpression(),
|
=> try analyzer.curlySuffixExpression(),
|
||||||
.fixed_keyword_fn => try analyzer.function(),
|
.fixed_keyword_fn => try analyzer.function(),
|
||||||
.fixed_keyword_return => try analyzer.addNode(.{
|
.fixed_keyword_return => try analyzer.addNode(.{
|
||||||
@ -1167,6 +1178,7 @@ const Analyzer = struct {
|
|||||||
.left = try analyzer.expression(),
|
.left = try analyzer.expression(),
|
||||||
.right = Node.Index.null,
|
.right = Node.Index.null,
|
||||||
}),
|
}),
|
||||||
|
.fixed_keyword_break => try analyzer.breakExpression(),
|
||||||
// todo:?
|
// todo:?
|
||||||
.operator_left_brace => try analyzer.block(),
|
.operator_left_brace => try analyzer.block(),
|
||||||
.fixed_keyword_if => try analyzer.ifExpression(),
|
.fixed_keyword_if => try analyzer.ifExpression(),
|
||||||
@ -1384,34 +1396,40 @@ const Analyzer = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn errorUnionExpression(analyzer: *Analyzer) !Node.Index {
|
fn errorUnionExpression(analyzer: *Analyzer) !Node.Index {
|
||||||
if (analyzer.peekToken() == .operator_bang) {
|
const initial = analyzer.token_i;
|
||||||
const error_union_token = try analyzer.expectToken(.operator_bang);
|
if (analyzer.peekToken() == .operator_asterisk and analyzer.peekTokenAhead(1) == .operator_bang) {
|
||||||
if (analyzer.peekToken() == .operator_asterisk) {
|
const asterisk = try analyzer.expectToken(.operator_asterisk);
|
||||||
analyzer.consumeToken();
|
analyzer.consumeToken();
|
||||||
// All errors
|
const type_node = try analyzer.suffixExpression();
|
||||||
const all_errors_node = try analyzer.addNode(.{
|
|
||||||
.id = .all_errors,
|
|
||||||
.token = error_union_token,
|
|
||||||
.left = .null,
|
|
||||||
.right = .null,
|
|
||||||
});
|
|
||||||
const type_node = try analyzer.suffixExpression();
|
|
||||||
|
|
||||||
const error_union = try analyzer.addNode(.{
|
const all_errors_node = try analyzer.addNode(.{
|
||||||
.id = .error_union,
|
.id = .all_errors,
|
||||||
.token = error_union_token,
|
.token = asterisk,
|
||||||
.left = all_errors_node,
|
.left = .null,
|
||||||
.right = type_node,
|
.right = .null,
|
||||||
});
|
});
|
||||||
return error_union;
|
|
||||||
} else {
|
const error_union = try analyzer.addNode(.{
|
||||||
unreachable;
|
.id = .error_union,
|
||||||
}
|
.token = asterisk,
|
||||||
|
// All errors
|
||||||
|
.left = all_errors_node,
|
||||||
|
.right = type_node,
|
||||||
|
});
|
||||||
|
return error_union;
|
||||||
} else {
|
} else {
|
||||||
const suffix_expression = try analyzer.suffixExpression();
|
const suffix_expression = try analyzer.suffixExpression();
|
||||||
|
|
||||||
return switch (analyzer.peekToken()) {
|
return switch (analyzer.peekToken()) {
|
||||||
.operator_bang => unreachable,
|
.operator_bang => try analyzer.addNode(.{
|
||||||
|
.id = .error_union,
|
||||||
|
.token = blk: {
|
||||||
|
analyzer.consumeToken();
|
||||||
|
break :blk initial;
|
||||||
|
},
|
||||||
|
.left = suffix_expression,
|
||||||
|
.right = try analyzer.typeExpression(),
|
||||||
|
}),
|
||||||
else => suffix_expression,
|
else => suffix_expression,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1598,8 +1616,9 @@ const Analyzer = struct {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processContainerType(analyzer: *Analyzer, maybe_token_id: ?Token.Id) !Node.Index{
|
fn processContainerType(analyzer: *Analyzer, maybe_token_id: ?Token.Id) !Node.Index {
|
||||||
const token_i = if (maybe_token_id) |tid| try analyzer.expectToken(tid) else analyzer.token_i;
|
const token_i = if (maybe_token_id) |tid| try analyzer.expectToken(tid) else analyzer.token_i;
|
||||||
|
assert(Token.unwrap(analyzer.token_i) < analyzer.token_buffer.tokens.len);
|
||||||
const token_id = maybe_token_id orelse .fixed_keyword_struct;
|
const token_id = maybe_token_id orelse .fixed_keyword_struct;
|
||||||
const container_type: Compilation.ContainerType = switch (token_id) {
|
const container_type: Compilation.ContainerType = switch (token_id) {
|
||||||
.fixed_keyword_struct => .@"struct",
|
.fixed_keyword_struct => .@"struct",
|
||||||
@ -1608,8 +1627,8 @@ const Analyzer = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const node_id: Node.Id = switch (token_id) {
|
const node_id: Node.Id = switch (token_id) {
|
||||||
.fixed_keyword_struct => .@"struct_type",
|
.fixed_keyword_struct => .struct_type,
|
||||||
.fixed_keyword_enum => .@"enum_type",
|
.fixed_keyword_enum => .enum_type,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1710,7 +1729,7 @@ const Analyzer = struct {
|
|||||||
const member_node = analyzer.nodes.get(member_node_index);
|
const member_node = analyzer.nodes.get(member_node_index);
|
||||||
if (member_node.id == .identifier) {
|
if (member_node.id == .identifier) {
|
||||||
const token_offset = analyzer.getTokenOffset(member_node.token);
|
const token_offset = analyzer.getTokenOffset(member_node.token);
|
||||||
std.debug.print("Node index #{} (list index {}):\n```\n{s}\n```\n", .{Node.unwrap(member_node_index), index, analyzer.source_file[token_offset..]});
|
std.debug.print("Node index #{} (list index {}):\n```\n{s}\n```\n", .{ Node.unwrap(member_node_index), index, analyzer.source_file[token_offset..] });
|
||||||
// std.debug.print("ID: {s}\n", .{analyzer.bytes(member_node.token)});
|
// std.debug.print("ID: {s}\n", .{analyzer.bytes(member_node.token)});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
@ -1726,7 +1745,16 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
fn testDeclaration(analyzer: *Analyzer) !Node.Index {
|
fn testDeclaration(analyzer: *Analyzer) !Node.Index {
|
||||||
const test_token = try analyzer.expectToken(.fixed_keyword_test);
|
const test_token = try analyzer.expectToken(.fixed_keyword_test);
|
||||||
const name_node: Node.Index = if (analyzer.peekToken() == .string_literal) try analyzer.identifierNode() else .null;
|
const name_node: Node.Index = if (analyzer.peekToken() == .string_literal) try analyzer.addNode(.{
|
||||||
|
.id = .string_literal,
|
||||||
|
.token = b: {
|
||||||
|
const index = analyzer.token_i;
|
||||||
|
analyzer.consumeToken();
|
||||||
|
break :b index;
|
||||||
|
},
|
||||||
|
.left = .null,
|
||||||
|
.right = .null,
|
||||||
|
}) else .null;
|
||||||
const test_block = try analyzer.block();
|
const test_block = try analyzer.block();
|
||||||
return try analyzer.addNode(.{
|
return try analyzer.addNode(.{
|
||||||
.token = test_token,
|
.token = test_token,
|
||||||
@ -1861,6 +1889,33 @@ const Analyzer = struct {
|
|||||||
_ = try analyzer.expectToken(.operator_right_parenthesis);
|
_ = try analyzer.expectToken(.operator_right_parenthesis);
|
||||||
break :blk expr;
|
break :blk expr;
|
||||||
},
|
},
|
||||||
|
.fixed_keyword_error => blk: {
|
||||||
|
analyzer.consumeToken();
|
||||||
|
if (analyzer.peekToken() == .operator_left_brace) {
|
||||||
|
analyzer.consumeToken();
|
||||||
|
var list = ArrayList(Node.Index){};
|
||||||
|
|
||||||
|
while (analyzer.peekToken() != .operator_right_brace) {
|
||||||
|
const identifier = try analyzer.identifierNode();
|
||||||
|
try list.append(analyzer.allocator, identifier);
|
||||||
|
const comma = try analyzer.expectToken(.operator_comma);
|
||||||
|
_ = comma; // autofix
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzer.consumeToken();
|
||||||
|
|
||||||
|
break :blk try analyzer.addNode(.{
|
||||||
|
.id = .error_type,
|
||||||
|
.token = token_i,
|
||||||
|
.left = try analyzer.nodeList(list),
|
||||||
|
.right = .null,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const t = analyzer.peekToken();
|
||||||
|
_ = t; // autofix
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => |t| switch (t) {
|
else => |t| switch (t) {
|
||||||
.identifier => std.debug.panic("{s}: {s}", .{ @tagName(t), analyzer.bytes(token_i) }),
|
.identifier => std.debug.panic("{s}: {s}", .{ @tagName(t), analyzer.bytes(token_i) }),
|
||||||
else => @panic(@tagName(t)),
|
else => @panic(@tagName(t)),
|
||||||
@ -2031,7 +2086,6 @@ const Analyzer = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Here it is assumed that left brace is consumed
|
// Here it is assumed that left brace is consumed
|
||||||
pub fn analyze(allocator: Allocator, lexer_result: lexer.Result, source_file: []const u8, token_buffer: *Token.Buffer, node_list: *Node.List, node_lists: *ArrayList(ArrayList(Node.Index))) !Result {
|
pub fn analyze(allocator: Allocator, lexer_result: lexer.Result, source_file: []const u8, token_buffer: *Token.Buffer, node_list: *Node.List, node_lists: *ArrayList(ArrayList(Node.Index))) !Result {
|
||||||
const start = std.time.Instant.now() catch unreachable;
|
const start = std.time.Instant.now() catch unreachable;
|
||||||
@ -2065,5 +2119,3 @@ const Associativity = enum {
|
|||||||
none,
|
none,
|
||||||
left,
|
left,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,5 +30,5 @@ const panic = fn (reason: PanicReason) noreturn{
|
|||||||
|
|
||||||
const TestFunction = struct{
|
const TestFunction = struct{
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
function: &const fn () !*void,
|
function: &const fn () *!void,
|
||||||
};
|
};
|
||||||
|
@ -31,8 +31,8 @@ const start :: export = fn (argc_argv_address: usize) noreturn {
|
|||||||
argument_address_iterator += #size(usize) * (argument_count + 1);
|
argument_address_iterator += #size(usize) * (argument_count + 1);
|
||||||
environment_values = #cast(argument_address_iterator);
|
environment_values = #cast(argument_address_iterator);
|
||||||
const env = environment_values;
|
const env = environment_values;
|
||||||
const result = #import("main").main();
|
#import("root").main() catch std.os.exit(1);
|
||||||
std.os.exit(exit_code = result);
|
std.os.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const main :: export = fn (argc: s32, argv: [&]const [&:0]const u8, env: [&:null]const ?[&:null]const u8) s32 {
|
const main :: export = fn (argc: s32, argv: [&]const [&:0]const u8, env: [&:null]const ?[&:null]const u8) s32 {
|
||||||
@ -40,5 +40,6 @@ const main :: export = fn (argc: s32, argv: [&]const [&:0]const u8, env: [&:null
|
|||||||
argument_count = argc_u;
|
argument_count = argc_u;
|
||||||
argument_values = argv;
|
argument_values = argv;
|
||||||
environment_values = env;
|
environment_values = env;
|
||||||
return #import("main").main();
|
#import("root").main() catch return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
6
lib/test_runner.nat
Normal file
6
lib/test_runner.nat
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const builtin = #import("builtin");
|
||||||
|
const main = fn () *!void {
|
||||||
|
for (builtin.test_functions) |test_function| {
|
||||||
|
try test_function.function();
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
const main = fn () s32 {
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -2,7 +2,11 @@ const std = #import("std");
|
|||||||
const assert = std.assert;
|
const assert = std.assert;
|
||||||
const Executable = std.build.Executable;
|
const Executable = std.build.Executable;
|
||||||
|
|
||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const executable = Executable{
|
const executable = Executable{
|
||||||
.target = .{
|
.target = .{
|
||||||
.cpu = .x86_64,
|
.cpu = .x86_64,
|
||||||
@ -10,13 +14,12 @@ const main = fn () s32 {
|
|||||||
.abi = .gnu,
|
.abi = .gnu,
|
||||||
},
|
},
|
||||||
.main_source_path = "src/main.nat",
|
.main_source_path = "src/main.nat",
|
||||||
.name = "first",
|
.name = "first_build",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (executable.compile()) {
|
if (executable.compile()) {
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes = "Executable failed to compile!\n");
|
std.print(bytes = "Executable failed to compile!\n");
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
2
test/build/first_build/src/main.nat
Normal file
2
test/build/first_build/src/main.nat
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
const main = fn () *!void {
|
||||||
|
}
|
@ -2,7 +2,11 @@ const std = #import("std");
|
|||||||
const assert = std.assert;
|
const assert = std.assert;
|
||||||
const Executable = std.build.Executable;
|
const Executable = std.build.Executable;
|
||||||
|
|
||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const executable = Executable{
|
const executable = Executable{
|
||||||
.target = .{
|
.target = .{
|
||||||
.cpu = .x86_64,
|
.cpu = .x86_64,
|
||||||
@ -15,9 +19,8 @@ const main = fn () s32 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (executable.compile()) {
|
if (executable.compile()) {
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes = "Executable failed to compile!\n");
|
std.print(bytes = "Executable failed to compile!\n");
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
const main = fn () s32 {
|
const main = fn () *!void {
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
const a: s32 = 1;
|
const a: s32 = 1;
|
||||||
const b: s32 = 2;
|
const b: s32 = 2;
|
||||||
const c: s32 = a + b;
|
const c: s32 = a + b;
|
||||||
const d: s32 = 3;
|
const d: s32 = 3;
|
||||||
const e: s32 = d - c;
|
const e: s32 = d - c;
|
||||||
return e;
|
if (e != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
const main = fn() Error!void {
|
||||||
var a: s32 = 5;
|
var a: s32 = 5;
|
||||||
var b: s32 = 4;
|
var b: s32 = 4;
|
||||||
var result = a & b;
|
var result = a & b;
|
||||||
return result - b;
|
if (result - b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const ch = 'a';
|
const ch = 'a';
|
||||||
var buffer: [1]u8 = undefined;
|
var buffer: [1]u8 = undefined;
|
||||||
var ptr: &[1]u8 = buffer.&;
|
var ptr: &[1]u8 = buffer.&;
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
ptr[index] = ch;
|
ptr[index] = ch;
|
||||||
const sub: u8 = ptr[index] - ch;
|
const sub: u8 = ptr[index] - ch;
|
||||||
const result: u32 = sub;
|
if (sub != 0) {
|
||||||
return #cast(result);
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
var buffer: [2]u8 = undefined;
|
var buffer: [2]u8 = undefined;
|
||||||
const expected = 'a';
|
const expected = 'a';
|
||||||
const index: usize = 1;
|
const index: usize = 1;
|
||||||
@ -6,7 +10,9 @@ const main = fn () s32 {
|
|||||||
const ch = buffer[index];
|
const ch = buffer[index];
|
||||||
const sub = expected - ch;
|
const sub = expected - ch;
|
||||||
const result: u32 = sub;
|
const result: u32 = sub;
|
||||||
return #cast(result);
|
if (result != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo = fn (buffer: &[2]u8, index: usize, ch: u8) void {
|
const foo = fn (buffer: &[2]u8, index: usize, ch: u8) void {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const ch = 'a';
|
const ch = 'a';
|
||||||
var buffer: [1]u8 = undefined;
|
var buffer: [1]u8 = undefined;
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
buffer[index] = ch;
|
buffer[index] = ch;
|
||||||
const sub: u8 = buffer[index] - ch;
|
if (buffer[index] - ch != 0) {
|
||||||
const result: u32 = sub;
|
return Error.unexpected_result;
|
||||||
return #cast(result);
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
const assert = std.assert;
|
const assert = std.assert;
|
||||||
|
|
||||||
const main = fn() s32 {
|
const main = fn() *!void {
|
||||||
assert(true);
|
assert(true);
|
||||||
var a: s32 = 1;
|
var a: s32 = 1;
|
||||||
const is_not_one = a != 1;
|
const is_not_one = a != 1;
|
||||||
assert(!is_not_one);
|
assert(!is_not_one);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ const BitStruct = struct(u8) {
|
|||||||
d: u5,
|
d: u5,
|
||||||
};
|
};
|
||||||
|
|
||||||
const main = fn () s32 {
|
const main = fn () *!void {
|
||||||
var bs = BitStruct{
|
var bs = BitStruct{
|
||||||
.a = false,
|
.a = false,
|
||||||
.b = true,
|
.b = true,
|
||||||
@ -26,5 +26,4 @@ const main = fn () s32 {
|
|||||||
};
|
};
|
||||||
const bitcast_const_bs: u8 = #cast(const_bs);
|
const bitcast_const_bs: u8 = #cast(const_bs);
|
||||||
assert(bitcast_const_bs == 5);
|
assert(bitcast_const_bs == 5);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ const transform = fn (a: A) B {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const main = fn () s32 {
|
const main = fn () *!void {
|
||||||
var a = A{
|
var a = A{
|
||||||
.a = 3,
|
.a = 3,
|
||||||
.b = 8,
|
.b = 8,
|
||||||
@ -26,6 +26,4 @@ const main = fn () s32 {
|
|||||||
const b = transform(a);
|
const b = transform(a);
|
||||||
assert(a.a == b.a);
|
assert(a.a == b.a);
|
||||||
assert(a.b == b.b);
|
assert(a.b == b.b);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
const main = fn() Error!void {
|
||||||
var i: s32 = 0;
|
var i: s32 = 0;
|
||||||
const j: s32 = 5;
|
const j: s32 = 5;
|
||||||
for (0..10) |_| {
|
for (0..10) |_| {
|
||||||
@ -8,5 +11,7 @@ const main = fn() s32 {
|
|||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i - j;
|
if (i - j != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
if (true) {
|
if (true) {
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
const main = fn() Error!void {
|
||||||
const dividend: s32 = 30;
|
const dividend: s32 = 30;
|
||||||
const divisor: s32 = 6;
|
const divisor: s32 = 6;
|
||||||
const div: s32 = dividend / divisor;
|
const div: s32 = dividend / divisor;
|
||||||
const n: s32 = 5;
|
const n: s32 = 5;
|
||||||
|
|
||||||
return n - div;
|
if (n - div != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const a = foo(5);
|
const a = foo(5);
|
||||||
if (a != 123) {
|
if (a != 123) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
const b = foo(5);
|
const b = foo(5);
|
||||||
if (b != 123) {
|
if (b != 123) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a - b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
return a - b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo = fn (arg: s32) s32 {
|
const foo = fn (arg: s32) s32 {
|
||||||
|
@ -1,3 +1 @@
|
|||||||
const main = fn() s32 {
|
const main = fn() *!void { }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
var counter: s32 = 0;
|
var counter: s32 = 0;
|
||||||
const loop = 10;
|
const loop = 10;
|
||||||
|
|
||||||
@ -6,5 +10,7 @@ const main = fn() s32 {
|
|||||||
counter += 1;
|
counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return loop - counter;
|
if (loop - counter != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,17 @@ const print_values = fn(slice: []const u8) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const a = [_]u8{1, 1, 4, 5, 6};
|
const a = [_]u8{1, 1, 4, 5, 6};
|
||||||
const b = [_]u8{1, 4, 6};
|
const b = [_]u8{1, 4, 6};
|
||||||
const expected_result: usize = a.len + b.len;
|
const expected_result: usize = a.len + b.len;
|
||||||
const result = count_slice_byte_count(slices = .{a.&, b.&}.&);
|
const result = count_slice_byte_count(slices = .{a.&, b.&}.&);
|
||||||
print_values(slice = a.&);
|
print_values(slice = a.&);
|
||||||
const main_result: u32 = #cast(expected_result - result);
|
if (expected_result - result != 0) {
|
||||||
return #cast(main_result);
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
|
|
||||||
const main = fn() s32 {
|
const main = fn() Error!void {
|
||||||
if (std.os.duplicate_process()) |pid| {
|
if (std.os.duplicate_process()) |pid| {
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
std.print(bytes = "Hello from child\n");
|
std.print(bytes = "Hello from child\n");
|
||||||
std.os.exit(exit_code = 0);
|
std.os.exit(exit_code = 0);
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes = "Hello from parent\n");
|
std.print(bytes = "Hello from parent\n");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes = "Unable to create child process\n");
|
std.print(bytes = "Unable to create child process\n");
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
|
|
||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
if (std.os.duplicate_process()) |pid| {
|
if (std.os.duplicate_process()) |pid| {
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
std.print(bytes = "Hello from child\n");
|
std.print(bytes = "Hello from child\n");
|
||||||
const argv = [_:null] ?[&:0]const u8{"/usr/bin/ls"};
|
const argv = [_:null] ?[&:0]const u8{"/usr/bin/ls"};
|
||||||
_ = std.os.execute(path = "/usr/bin/ls", argv = argv.&, env = std.start.environment_values);
|
_ = std.os.execute(path = "/usr/bin/ls", argv = argv.&, env = std.start.environment_values);
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes = "Hello from parent\n");
|
std.print(bytes = "Hello from parent\n");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes = "Unable to create child process\n");
|
std.print(bytes = "Unable to create child process\n");
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,14 @@ const foo = fn () s32 {
|
|||||||
return expected_number;
|
return expected_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
var function_pointer = foo.&;
|
var function_pointer = foo.&;
|
||||||
const result = function_pointer();
|
const result = function_pointer();
|
||||||
return result - expected_number;
|
if (result - expected_number != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,17 @@ const Struct = struct{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
var s = Struct{
|
var s = Struct{
|
||||||
.a = expected_number,
|
.a = expected_number,
|
||||||
.handler = Struct.handler_function.&,
|
.handler = Struct.handler_function.&,
|
||||||
};
|
};
|
||||||
|
|
||||||
return s.handler(s.&) - expected_number;
|
if (s.handler(s.&) - expected_number != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
|
|
||||||
const main = fn() s32 {
|
const main = fn() *!void {
|
||||||
std.print(bytes = "Hello world!\n");
|
std.print(bytes = "Hello world!\n");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
const main = fn () Error!void {
|
||||||
const a = foo(5);
|
const a = foo(5);
|
||||||
if (a != 6) {
|
if (a != 6) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
const b = foo(5);
|
const b = foo(5);
|
||||||
if (b != 6) {
|
if (b != 6) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
|
if (a - b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
return a - b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo = fn (arg: s32) s32 {
|
const foo = fn (arg: s32) s32 {
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
const a = foo(5);
|
const a = foo(5);
|
||||||
if (a != 12412) {
|
if (a != 12412) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
const b = foo(5);
|
const b = foo(5);
|
||||||
if (b != 12412) {
|
if (b != 12412) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a - b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
return a - b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo = fn(arg: s32) s32 {
|
const foo = fn(arg: s32) s32 {
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
const a: s32 = 5;
|
unexpected_result,
|
||||||
const b: s32 = 4;
|
};
|
||||||
return a * b - a * b;
|
const main = fn() Error!void {
|
||||||
|
var a: s32 = 5;
|
||||||
|
var b: s32 = 4;
|
||||||
|
if (a * b - a * b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
var i: s32 = 0;
|
var i: s32 = 0;
|
||||||
while (i < 10) {
|
while (i < 10) {
|
||||||
i += 1;
|
i += 1;
|
||||||
@ -7,5 +11,7 @@ const main = fn() s32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return i - 5;
|
if (i - 5 != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const a = foo(5142);
|
const a = foo(5142);
|
||||||
if (a != 2501) {
|
if (a != 2501) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
const b = foo(5142);
|
const b = foo(5142);
|
||||||
if (b != 2501) {
|
if (b != 2501) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
|
if (a - b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
return #cast(a - b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo = fn (arg: u32) u32 {
|
const foo = fn (arg: u32) u32 {
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
const main = fn () Error!void {
|
||||||
const a = foo(5142);
|
const a = foo(5142);
|
||||||
const b = foo(5142);
|
const b = foo(5142);
|
||||||
return #cast(a - b);
|
if (a - b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo = fn (arg: u32) u32 {
|
const foo = fn (arg: u32) u32 {
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
const main = fn () s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const a = foo(5);
|
const a = foo(5);
|
||||||
const b = foo(5);
|
const b = foo(5);
|
||||||
return a - b;
|
if (a - b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo = fn (arg: s32) s32 {
|
const foo = fn (arg: s32) s32 {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
const assert = std.assert;
|
const assert = std.assert;
|
||||||
const main = fn() s32 {
|
const main = fn() *!void {
|
||||||
var foo = [2:null] ?[&:0]const u8 {"Hi", "Ho"};
|
var foo = [2:null] ?[&:0]const u8 {"Hi", "Ho"};
|
||||||
assert(foo[2] == null);
|
assert(foo[2] == null);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
const foo = fn(slice: []u8) ?[]u8 {
|
const foo = fn(slice: []u8) ?[]u8 {
|
||||||
return slice[0..1];
|
return slice[0..1];
|
||||||
}
|
}
|
||||||
const main = fn() s32 {
|
const main = fn() *!void {
|
||||||
_ = foo(slice = .{ 0, 1, 2, 3 }.&);
|
_ = foo(slice = .{ 0, 1, 2, 3 }.&);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
const a: u32 = 0xffff;
|
const a: u32 = 0xffff;
|
||||||
const b: u32 = 0xffff0000;
|
const b: u32 = 0xffff0000;
|
||||||
const c: u32 = 0xffffffff;
|
const c: u32 = 0xffffffff;
|
||||||
const result = c - (a | b);
|
const result = c - (a | b);
|
||||||
return #cast(result);
|
if (result != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
const print = std.print;
|
const print = std.print;
|
||||||
|
|
||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
var buffer: [std.os.max_path_byte_count:0]u8 = undefined;
|
var buffer: [std.os.max_path_byte_count:0]u8 = undefined;
|
||||||
if (std.os.current_executable_path(buffer = buffer.&)) |bytes| {
|
if (std.os.current_executable_path(buffer = buffer.&)) |bytes| {
|
||||||
print(bytes);
|
print(bytes);
|
||||||
print(bytes = "\n");
|
print(bytes = "\n");
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
print(bytes = "Failed\n");
|
return Error.unexpected_result;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
var x: u32 = 1;
|
var x: u32 = 1;
|
||||||
x = x << 5;
|
x = x << 5;
|
||||||
x = x >> 5;
|
x = x >> 5;
|
||||||
const b: u32 = 1;
|
const b: u32 = 1;
|
||||||
return #cast(x - b);
|
if (x - b != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
var false_boolean: bool = false;
|
var false_boolean: bool = false;
|
||||||
if (false_boolean) {
|
if (false_boolean) {
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
const std = #import("std");
|
const Error = error{
|
||||||
const assert = std.assert;
|
unexpected_result,
|
||||||
const main = fn () s32 {
|
};
|
||||||
assert(#size(usize) == 8);
|
|
||||||
return 0;
|
const main = fn () Error!void {
|
||||||
|
if (#size(usize) != 8) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
const main = fn () s32{
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void{
|
||||||
const a: [4]u8 = .{1, 2, 3, 4};
|
const a: [4]u8 = .{1, 2, 3, 4};
|
||||||
const b: []const []const u8 = .{a.&}.&;
|
const b: []const []const u8 = .{a.&}.&;
|
||||||
|
|
||||||
@ -10,5 +14,7 @@ const main = fn () s32{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return #cast(sum - 10);
|
if (sum - 10 != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
const main = fn () s32{
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn () Error!void {
|
||||||
const a: [4]u8 = .{1, 2, 3, 4};
|
const a: [4]u8 = .{1, 2, 3, 4};
|
||||||
const b: []const []const u8 = .{a.&}.&;
|
const b: []const []const u8 = .{a.&}.&;
|
||||||
const c: u8 = b[0][0] - 1;
|
const c: u8 = b[0][0] - 1;
|
||||||
const d: u32 = c;
|
if (c != 0) {
|
||||||
return #cast(c);
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
const main = fn () s32 {
|
const main = fn () *!void {
|
||||||
_ = foo();
|
_ = foo();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo = fn () []u8 {
|
const foo = fn () []u8 {
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
const assert = std.assert;
|
const assert = std.assert;
|
||||||
|
|
||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
var buffer: [65]u8 = undefined;
|
var buffer: [65]u8 = undefined;
|
||||||
const slice = foo(5, buffer.&);
|
const slice = foo(5, buffer.&);
|
||||||
assert(slice.len + 5 == buffer.len);
|
assert(slice.len + 5 == buffer.len);
|
||||||
const result: u32 = #cast(slice.len + 5 - buffer.len);
|
const result: u32 = #cast(slice.len + 5 - buffer.len);
|
||||||
return #cast(result);
|
if (result != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const foo = fn(n: usize, buffer: &[65]u8) []u8 {
|
const foo = fn(n: usize, buffer: &[65]u8) []u8 {
|
||||||
return buffer[n..];
|
return buffer[n..];
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
const main = fn() Error!void {
|
||||||
var a : s32 = 0;
|
var a : s32 = 0;
|
||||||
return a;
|
if (a != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
|
|
||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
const size = 0x1000;
|
const size = 0x1000;
|
||||||
|
|
||||||
if (std.page_allocator.allocate(size, alignment = 12)) |result| {
|
if (std.page_allocator.allocate(size, alignment = 12)) |result| {
|
||||||
@ -8,13 +12,12 @@ const main = fn() s32 {
|
|||||||
std.print(bytes = "Allocation succeeded. Freeing...\n");
|
std.print(bytes = "Allocation succeeded. Freeing...\n");
|
||||||
if (std.page_allocator.free(bytes_ptr = result.ptr, bytes_len = result.len)) {
|
if (std.page_allocator.free(bytes_ptr = result.ptr, bytes_len = result.len)) {
|
||||||
std.print(bytes = "Memory freed successfully\n");
|
std.print(bytes = "Memory freed successfully\n");
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes = "Memory freed with errors\n");
|
std.print(bytes = "Memory freed with errors\n");
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes = "Allocation failed!\n");
|
std.print(bytes = "Allocation failed!\n");
|
||||||
return 1;
|
return Error.unexpected_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
const main = fn() s32 {
|
const Error = error{
|
||||||
|
unexpected_result,
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = fn() Error!void {
|
||||||
var a: s32 = 561;
|
var a: s32 = 561;
|
||||||
var b: s32 = 124;
|
var b: s32 = 124;
|
||||||
var c: s32 = a ^ b;
|
var c: s32 = a ^ b;
|
||||||
var d: s32 = a ^ b;
|
var d: s32 = a ^ b;
|
||||||
return c ^ d;
|
if (c ^ d != 0) {
|
||||||
|
return Error.unexpected_result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
const assert = std.assert;
|
const assert = std.assert;
|
||||||
const main = fn () s32 {
|
const main = fn () *!void {
|
||||||
var a = [2:0]u8 {1, 2};
|
var a = [2:0]u8 {1, 2};
|
||||||
assert(a[2] == 0);
|
assert(a[2] == 0);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
2
test/tests/first_test/main.nat
Normal file
2
test/tests/first_test/main.nat
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
test "First test" {
|
||||||
|
}
|
@ -1,2 +0,0 @@
|
|||||||
test {
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user