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| {
|
||||
switch (unit.types.get(argument_type_index).*) {
|
||||
// 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)),
|
||||
}
|
||||
// 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;
|
||||
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)),
|
||||
};
|
||||
|
||||
@ -1327,7 +1366,13 @@ pub const LLVM = struct {
|
||||
|
||||
break :b name.items;
|
||||
} else {
|
||||
if (unit.type_declarations.get(sema_type_index)) |type_declaration| {
|
||||
_ = type_declaration; // autofix
|
||||
unreachable;
|
||||
} else {
|
||||
// TODO: fix
|
||||
break :b "anon_struct";
|
||||
}
|
||||
}
|
||||
},
|
||||
// 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) {
|
||||
.constant_int => |integer| {
|
||||
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;
|
||||
return constant_int.toConstant();
|
||||
},
|
||||
.constant_struct => |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;
|
||||
},
|
||||
.constant_struct => |constant_struct_index| return try llvm.getConstantStruct(unit, context, constant_struct_index),
|
||||
.undefined => {
|
||||
const undefined_type = try llvm.getType(unit, context, type_index);
|
||||
const poison = undefined_type.getPoison() orelse unreachable;
|
||||
@ -2130,6 +2161,13 @@ pub const LLVM = struct {
|
||||
const constant_null_pointer = pointer_type.getNull();
|
||||
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)),
|
||||
}
|
||||
}
|
||||
@ -2192,9 +2230,10 @@ pub const LLVM = struct {
|
||||
const const_slice = unit.constant_slices.get(constant_slice_index);
|
||||
const const_slice_type = try llvm.getType(unit, context, const_slice.type);
|
||||
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 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{
|
||||
ptr.toConstant(),
|
||||
len.toConstant(),
|
||||
@ -2223,6 +2262,7 @@ pub const LLVM = struct {
|
||||
break :b constant_int.toConstant();
|
||||
},
|
||||
.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)),
|
||||
};
|
||||
list.appendAssumeCapacity(value);
|
||||
@ -2232,6 +2272,22 @@ pub const LLVM = struct {
|
||||
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 {
|
||||
const intrinsic_id = LLVM.lookupIntrinsic(intrinsic_name.ptr, intrinsic_name.len);
|
||||
assert(intrinsic_id != .none);
|
||||
@ -2354,7 +2410,6 @@ pub const LLVM = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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");
|
||||
block_command_list.append(entry_block_node);
|
||||
|
||||
var phis = AutoArrayHashMap(Compilation.Instruction.Index, *LLVM.Value.Instruction.PhiNode){};
|
||||
|
||||
while (block_command_list.len != 0) {
|
||||
const block_node = block_command_list.first orelse unreachable;
|
||||
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).*) {
|
||||
.void, .noreturn, .type => unreachable,
|
||||
.comptime_int => unreachable,
|
||||
.bool => {},
|
||||
.@"struct" => {},
|
||||
.@"enum" => {},
|
||||
.function => unreachable,
|
||||
.integer => {},
|
||||
.pointer => {},
|
||||
.slice => {},
|
||||
.array => {},
|
||||
else => {},
|
||||
}
|
||||
|
||||
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)),
|
||||
};
|
||||
|
||||
|
||||
for (call.arguments, arguments) |argument_value, *argument| {
|
||||
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).*) {
|
||||
.void, .noreturn, .type => unreachable,
|
||||
.comptime_int => unreachable,
|
||||
.bool => {},
|
||||
// .bool => unreachable,
|
||||
.@"struct" => {},
|
||||
.@"enum" => {},
|
||||
.function => unreachable,
|
||||
.integer => {},
|
||||
.pointer => {},
|
||||
.slice => {},
|
||||
.array => {},
|
||||
else => {},
|
||||
}
|
||||
const argument_type = argument.toValue().getType();
|
||||
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");
|
||||
block_command_list.insertAfter(block_node, 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
|
||||
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_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| {
|
||||
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 phis.putNoClobber(context.allocator, instruction_index, phi_node);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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()) {
|
||||
var message_len: usize = 0;
|
||||
const function_str = llvm.function.toString(&message_len);
|
||||
|
@ -162,7 +162,6 @@ pub const ListType = enum{
|
||||
pointer,
|
||||
};
|
||||
|
||||
|
||||
pub fn enumFromString(comptime E: type, string: []const u8) ?E {
|
||||
return inline for (@typeInfo(E).Enum.fields) |enum_field| {
|
||||
if (std.mem.eql(u8, string, enum_field.name)) {
|
||||
|
@ -15,7 +15,6 @@ const logln = Compilation.logln;
|
||||
const Token = Compilation.Token;
|
||||
const fs = @import("../fs.zig");
|
||||
|
||||
|
||||
// Needed information
|
||||
// Token: u8
|
||||
// line: u32
|
||||
@ -281,7 +280,6 @@ pub fn analyze(allocator: Allocator, text: []const u8, token_buffer: *Token.Buff
|
||||
},
|
||||
else => break :blk .operator_bang,
|
||||
}
|
||||
|
||||
},
|
||||
'=' => blk: {
|
||||
index += 1;
|
||||
|
@ -187,6 +187,9 @@ pub const Node = struct {
|
||||
test_declaration,
|
||||
all_errors,
|
||||
error_union,
|
||||
catch_expression,
|
||||
try_expression,
|
||||
error_type,
|
||||
};
|
||||
};
|
||||
|
||||
@ -307,7 +310,9 @@ const Analyzer = struct {
|
||||
if (equal(u8, identifier_name, enum_field.name)) {
|
||||
const attribute = @field(Compilation.Debug.Declaration.Global.Attribute, enum_field.name);
|
||||
const attribute_node = switch (attribute) {
|
||||
.@"export", .@"extern", => try analyzer.addNode(.{
|
||||
.@"export",
|
||||
.@"extern",
|
||||
=> try analyzer.addNode(.{
|
||||
.id = @field(Node.Id, "symbol_attribute_" ++ @tagName(attribute)),
|
||||
.token = identifier,
|
||||
.left = .null,
|
||||
@ -393,7 +398,8 @@ const Analyzer = struct {
|
||||
if (equal(u8, identifier_name, enum_field.name)) {
|
||||
const attribute = @field(Compilation.Function.Attribute, enum_field.name);
|
||||
const attribute_node = switch (attribute) {
|
||||
.naked, => try analyzer.addNode(.{
|
||||
.naked,
|
||||
=> try analyzer.addNode(.{
|
||||
.id = @field(Node.Id, "function_attribute_" ++ @tagName(attribute)),
|
||||
.token = identifier,
|
||||
.left = .null,
|
||||
@ -473,16 +479,17 @@ const Analyzer = struct {
|
||||
const first_statement_token = analyzer.peekToken();
|
||||
logln(.parser, .block, "First statement token: {s}", .{@tagName(first_statement_token)});
|
||||
const statement_index = switch (first_statement_token) {
|
||||
.identifier => switch (analyzer.peekTokenAhead(1)) {
|
||||
.operator_colon => {
|
||||
unreachable;
|
||||
},
|
||||
else => try analyzer.assignExpressionStatement(),
|
||||
},
|
||||
.fixed_keyword_unreachable,
|
||||
.fixed_keyword_return,
|
||||
.discard,
|
||||
=> try analyzer.assignExpressionStatement(),
|
||||
// .identifier => switch (analyzer.peekTokenAhead(1)) {
|
||||
// .operator_colon => {
|
||||
// unreachable;
|
||||
// },
|
||||
// else => try analyzer.assignExpressionStatement(),
|
||||
// },
|
||||
// .fixed_keyword_unreachable,
|
||||
// .fixed_keyword_return,
|
||||
// .discard,
|
||||
// => try analyzer.assignExpressionStatement(),
|
||||
|
||||
.fixed_keyword_while => try analyzer.whileExpression(),
|
||||
.fixed_keyword_switch => try analyzer.switchExpression(),
|
||||
@ -491,17 +498,12 @@ const Analyzer = struct {
|
||||
.fixed_keyword_const,
|
||||
.fixed_keyword_var,
|
||||
=> try analyzer.symbolDeclaration(),
|
||||
.fixed_keyword_break => b: {
|
||||
const node_index = try analyzer.breakExpression();
|
||||
_ = try analyzer.expectToken(.operator_semicolon);
|
||||
break :b node_index;
|
||||
},
|
||||
.intrinsic => blk: {
|
||||
const intrinsic = try analyzer.compilerIntrinsic();
|
||||
_ = try analyzer.expectToken(.operator_semicolon);
|
||||
break :blk intrinsic;
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
// .intrinsic => blk: {
|
||||
// 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);
|
||||
@ -783,7 +785,7 @@ const Analyzer = struct {
|
||||
const left = try analyzer.expression();
|
||||
const expression_token = analyzer.token_i;
|
||||
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_add_assign => .add_assign,
|
||||
.operator_sub_assign => .sub_assign,
|
||||
@ -951,6 +953,7 @@ const Analyzer = struct {
|
||||
bit_or,
|
||||
shift_left,
|
||||
shift_right,
|
||||
@"catch",
|
||||
};
|
||||
|
||||
const operator_precedence = std.EnumArray(PrecedenceOperator, i32).init(.{
|
||||
@ -970,6 +973,7 @@ const Analyzer = struct {
|
||||
.bit_or = 40,
|
||||
.shift_left = 50,
|
||||
.shift_right = 50,
|
||||
.@"catch" = 40,
|
||||
});
|
||||
|
||||
const operator_associativity = std.EnumArray(PrecedenceOperator, Associativity).init(.{
|
||||
@ -989,6 +993,7 @@ const Analyzer = struct {
|
||||
.mod = .left,
|
||||
.shift_left = .left,
|
||||
.shift_right = .left,
|
||||
.@"catch" = .left,
|
||||
});
|
||||
|
||||
const operator_node_id = std.EnumArray(PrecedenceOperator, Node.Id).init(.{
|
||||
@ -1008,6 +1013,7 @@ const Analyzer = struct {
|
||||
.mod = .mod,
|
||||
.shift_left = .shift_left,
|
||||
.shift_right = .shift_right,
|
||||
.@"catch" = .catch_expression,
|
||||
});
|
||||
|
||||
fn expressionPrecedence(analyzer: *Analyzer, minimum_precedence: i32) !Node.Index {
|
||||
@ -1062,6 +1068,7 @@ const Analyzer = struct {
|
||||
.operator_xor => .bit_xor,
|
||||
.operator_shift_left => .shift_left,
|
||||
.operator_shift_right => .shift_right,
|
||||
.fixed_keyword_catch => .@"catch",
|
||||
else => |t| @panic(@tagName(t)),
|
||||
};
|
||||
|
||||
@ -1114,6 +1121,7 @@ const Analyzer = struct {
|
||||
},
|
||||
.operator_bang => .boolean_not,
|
||||
.operator_minus => .negation,
|
||||
.fixed_keyword_try => .try_expression,
|
||||
// .tilde => |t| @panic(@tagName(t)),
|
||||
};
|
||||
|
||||
@ -1155,6 +1163,9 @@ const Analyzer = struct {
|
||||
.discard,
|
||||
.fixed_keyword_undefined,
|
||||
.operator_left_bracket,
|
||||
.fixed_keyword_const,
|
||||
.fixed_keyword_var,
|
||||
.fixed_keyword_error,
|
||||
=> try analyzer.curlySuffixExpression(),
|
||||
.fixed_keyword_fn => try analyzer.function(),
|
||||
.fixed_keyword_return => try analyzer.addNode(.{
|
||||
@ -1167,6 +1178,7 @@ const Analyzer = struct {
|
||||
.left = try analyzer.expression(),
|
||||
.right = Node.Index.null,
|
||||
}),
|
||||
.fixed_keyword_break => try analyzer.breakExpression(),
|
||||
// todo:?
|
||||
.operator_left_brace => try analyzer.block(),
|
||||
.fixed_keyword_if => try analyzer.ifExpression(),
|
||||
@ -1384,34 +1396,40 @@ const Analyzer = struct {
|
||||
}
|
||||
|
||||
fn errorUnionExpression(analyzer: *Analyzer) !Node.Index {
|
||||
if (analyzer.peekToken() == .operator_bang) {
|
||||
const error_union_token = try analyzer.expectToken(.operator_bang);
|
||||
if (analyzer.peekToken() == .operator_asterisk) {
|
||||
const initial = analyzer.token_i;
|
||||
if (analyzer.peekToken() == .operator_asterisk and analyzer.peekTokenAhead(1) == .operator_bang) {
|
||||
const asterisk = try analyzer.expectToken(.operator_asterisk);
|
||||
analyzer.consumeToken();
|
||||
// All errors
|
||||
const type_node = try analyzer.suffixExpression();
|
||||
|
||||
const all_errors_node = try analyzer.addNode(.{
|
||||
.id = .all_errors,
|
||||
.token = error_union_token,
|
||||
.token = asterisk,
|
||||
.left = .null,
|
||||
.right = .null,
|
||||
});
|
||||
const type_node = try analyzer.suffixExpression();
|
||||
|
||||
const error_union = try analyzer.addNode(.{
|
||||
.id = .error_union,
|
||||
.token = error_union_token,
|
||||
.token = asterisk,
|
||||
// All errors
|
||||
.left = all_errors_node,
|
||||
.right = type_node,
|
||||
});
|
||||
return error_union;
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
} else {
|
||||
const suffix_expression = try analyzer.suffixExpression();
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
@ -1600,6 +1618,7 @@ const Analyzer = struct {
|
||||
|
||||
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;
|
||||
assert(Token.unwrap(analyzer.token_i) < analyzer.token_buffer.tokens.len);
|
||||
const token_id = maybe_token_id orelse .fixed_keyword_struct;
|
||||
const container_type: Compilation.ContainerType = switch (token_id) {
|
||||
.fixed_keyword_struct => .@"struct",
|
||||
@ -1608,8 +1627,8 @@ const Analyzer = struct {
|
||||
};
|
||||
|
||||
const node_id: Node.Id = switch (token_id) {
|
||||
.fixed_keyword_struct => .@"struct_type",
|
||||
.fixed_keyword_enum => .@"enum_type",
|
||||
.fixed_keyword_struct => .struct_type,
|
||||
.fixed_keyword_enum => .enum_type,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
@ -1726,7 +1745,16 @@ const Analyzer = struct {
|
||||
|
||||
fn testDeclaration(analyzer: *Analyzer) !Node.Index {
|
||||
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();
|
||||
return try analyzer.addNode(.{
|
||||
.token = test_token,
|
||||
@ -1861,6 +1889,33 @@ const Analyzer = struct {
|
||||
_ = try analyzer.expectToken(.operator_right_parenthesis);
|
||||
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) {
|
||||
.identifier => std.debug.panic("{s}: {s}", .{ @tagName(t), analyzer.bytes(token_i) }),
|
||||
else => @panic(@tagName(t)),
|
||||
@ -2031,7 +2086,6 @@ const Analyzer = struct {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 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 {
|
||||
const start = std.time.Instant.now() catch unreachable;
|
||||
@ -2065,5 +2119,3 @@ const Associativity = enum {
|
||||
none,
|
||||
left,
|
||||
};
|
||||
|
||||
|
||||
|
@ -30,5 +30,5 @@ const panic = fn (reason: PanicReason) noreturn{
|
||||
|
||||
const TestFunction = struct{
|
||||
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);
|
||||
environment_values = #cast(argument_address_iterator);
|
||||
const env = environment_values;
|
||||
const result = #import("main").main();
|
||||
std.os.exit(exit_code = result);
|
||||
#import("root").main() catch std.os.exit(1);
|
||||
std.os.exit(0);
|
||||
}
|
||||
|
||||
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_values = argv;
|
||||
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 Executable = std.build.Executable;
|
||||
|
||||
const main = fn () s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn () Error!void {
|
||||
const executable = Executable{
|
||||
.target = .{
|
||||
.cpu = .x86_64,
|
||||
@ -10,13 +14,12 @@ const main = fn () s32 {
|
||||
.abi = .gnu,
|
||||
},
|
||||
.main_source_path = "src/main.nat",
|
||||
.name = "first",
|
||||
.name = "first_build",
|
||||
};
|
||||
|
||||
if (executable.compile()) {
|
||||
return 0;
|
||||
} else {
|
||||
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 Executable = std.build.Executable;
|
||||
|
||||
const main = fn () s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn () Error!void {
|
||||
const executable = Executable{
|
||||
.target = .{
|
||||
.cpu = .x86_64,
|
||||
@ -15,9 +19,8 @@ const main = fn () s32 {
|
||||
};
|
||||
|
||||
if (executable.compile()) {
|
||||
return 0;
|
||||
} else {
|
||||
std.print(bytes = "Executable failed to compile!\n");
|
||||
return 1;
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,2 @@
|
||||
const main = fn () s32 {
|
||||
return 0;
|
||||
const main = fn () *!void {
|
||||
}
|
||||
|
@ -1,8 +1,14 @@
|
||||
const main = fn() s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn() Error!void {
|
||||
const a: s32 = 1;
|
||||
const b: s32 = 2;
|
||||
const c: s32 = a + b;
|
||||
const d: s32 = 3;
|
||||
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 b: s32 = 4;
|
||||
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';
|
||||
var buffer: [1]u8 = undefined;
|
||||
var ptr: &[1]u8 = buffer.&;
|
||||
var index: usize = 0;
|
||||
ptr[index] = ch;
|
||||
const sub: u8 = ptr[index] - ch;
|
||||
const result: u32 = sub;
|
||||
return #cast(result);
|
||||
if (sub != 0) {
|
||||
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;
|
||||
const expected = 'a';
|
||||
const index: usize = 1;
|
||||
@ -6,7 +10,9 @@ const main = fn () s32 {
|
||||
const ch = buffer[index];
|
||||
const sub = expected - ch;
|
||||
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 {
|
||||
|
@ -1,9 +1,13 @@
|
||||
const main = fn () s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn () Error!void {
|
||||
const ch = 'a';
|
||||
var buffer: [1]u8 = undefined;
|
||||
var index: usize = 0;
|
||||
buffer[index] = ch;
|
||||
const sub: u8 = buffer[index] - ch;
|
||||
const result: u32 = sub;
|
||||
return #cast(result);
|
||||
if (buffer[index] - ch != 0) {
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
const std = #import("std");
|
||||
const assert = std.assert;
|
||||
|
||||
const main = fn() s32 {
|
||||
const main = fn() *!void {
|
||||
assert(true);
|
||||
var a: s32 = 1;
|
||||
const is_not_one = a != 1;
|
||||
assert(!is_not_one);
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ const BitStruct = struct(u8) {
|
||||
d: u5,
|
||||
};
|
||||
|
||||
const main = fn () s32 {
|
||||
const main = fn () *!void {
|
||||
var bs = BitStruct{
|
||||
.a = false,
|
||||
.b = true,
|
||||
@ -26,5 +26,4 @@ const main = fn () s32 {
|
||||
};
|
||||
const bitcast_const_bs: u8 = #cast(const_bs);
|
||||
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{
|
||||
.a = 3,
|
||||
.b = 8,
|
||||
@ -26,6 +26,4 @@ const main = fn () s32 {
|
||||
const b = transform(a);
|
||||
assert(a.a == b.a);
|
||||
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;
|
||||
const j: s32 = 5;
|
||||
for (0..10) |_| {
|
||||
@ -8,5 +11,7 @@ const main = fn() s32 {
|
||||
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) {
|
||||
return 0;
|
||||
} 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 divisor: s32 = 6;
|
||||
const div: s32 = dividend / divisor;
|
||||
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);
|
||||
if (a != 123) {
|
||||
return 1;
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
const b = foo(5);
|
||||
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 {
|
||||
|
@ -1,3 +1 @@
|
||||
const main = fn() s32 {
|
||||
return 0;
|
||||
}
|
||||
const main = fn() *!void { }
|
||||
|
@ -1,4 +1,8 @@
|
||||
const main = fn() s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn() Error!void {
|
||||
var counter: s32 = 0;
|
||||
const loop = 10;
|
||||
|
||||
@ -6,5 +10,7 @@ const main = fn() s32 {
|
||||
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 b = [_]u8{1, 4, 6};
|
||||
const expected_result: usize = a.len + b.len;
|
||||
const result = count_slice_byte_count(slices = .{a.&, b.&}.&);
|
||||
print_values(slice = a.&);
|
||||
const main_result: u32 = #cast(expected_result - result);
|
||||
return #cast(main_result);
|
||||
if (expected_result - result != 0) {
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
const std = #import("std");
|
||||
|
||||
const main = fn() s32 {
|
||||
const main = fn() Error!void {
|
||||
if (std.os.duplicate_process()) |pid| {
|
||||
if (pid == 0) {
|
||||
std.print(bytes = "Hello from child\n");
|
||||
std.os.exit(exit_code = 0);
|
||||
} else {
|
||||
std.print(bytes = "Hello from parent\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
std.print(bytes = "Unable to create child process\n");
|
||||
return 1;
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,21 @@
|
||||
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 (pid == 0) {
|
||||
std.print(bytes = "Hello from child\n");
|
||||
const argv = [_:null] ?[&:0]const u8{"/usr/bin/ls"};
|
||||
_ = std.os.execute(path = "/usr/bin/ls", argv = argv.&, env = std.start.environment_values);
|
||||
return 1;
|
||||
return Error.unexpected_result;
|
||||
} else {
|
||||
std.print(bytes = "Hello from parent\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
const main = fn () s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn () Error!void {
|
||||
var function_pointer = foo.&;
|
||||
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{
|
||||
.a = expected_number,
|
||||
.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 main = fn() s32 {
|
||||
const main = fn() *!void {
|
||||
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);
|
||||
if (a != 6) {
|
||||
return 1;
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
const b = foo(5);
|
||||
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 {
|
||||
|
@ -1,13 +1,20 @@
|
||||
const main = fn() s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn() Error!void {
|
||||
const a = foo(5);
|
||||
if (a != 12412) {
|
||||
return 1;
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
const b = foo(5);
|
||||
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 {
|
||||
|
@ -1,5 +1,10 @@
|
||||
const main = fn() s32 {
|
||||
const a: s32 = 5;
|
||||
const b: s32 = 4;
|
||||
return a * b - a * b;
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
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;
|
||||
while (i < 10) {
|
||||
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);
|
||||
if (a != 2501) {
|
||||
return 1;
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
const b = foo(5142);
|
||||
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 {
|
||||
|
@ -1,7 +1,12 @@
|
||||
const main = fn () s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
const main = fn () Error!void {
|
||||
const a = foo(5142);
|
||||
const b = foo(5142);
|
||||
return #cast(a - b);
|
||||
if (a - b != 0) {
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
||||
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 b = foo(5);
|
||||
return a - b;
|
||||
if (a - b != 0) {
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
||||
const foo = fn (arg: s32) s32 {
|
||||
|
@ -1,7 +1,6 @@
|
||||
const std = #import("std");
|
||||
const assert = std.assert;
|
||||
const main = fn() s32 {
|
||||
const main = fn() *!void {
|
||||
var foo = [2:null] ?[&:0]const u8 {"Hi", "Ho"};
|
||||
assert(foo[2] == null);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
const foo = fn(slice: []u8) ?[]u8 {
|
||||
return slice[0..1];
|
||||
}
|
||||
const main = fn() s32 {
|
||||
const main = fn() *!void {
|
||||
_ = 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 b: u32 = 0xffff0000;
|
||||
const c: u32 = 0xffffffff;
|
||||
const result = c - (a | b);
|
||||
return #cast(result);
|
||||
if (result != 0) {
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,16 @@
|
||||
const std = #import("std");
|
||||
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;
|
||||
if (std.os.current_executable_path(buffer = buffer.&)) |bytes| {
|
||||
print(bytes);
|
||||
print(bytes = "\n");
|
||||
return 0;
|
||||
} else {
|
||||
print(bytes = "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 x: u32 = 1;
|
||||
x = x << 5;
|
||||
x = x >> 5;
|
||||
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;
|
||||
if (false_boolean) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
const std = #import("std");
|
||||
const assert = std.assert;
|
||||
const main = fn () s32 {
|
||||
assert(#size(usize) == 8);
|
||||
return 0;
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
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 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 b: []const []const u8 = .{a.&}.&;
|
||||
const c: u8 = b[0][0] - 1;
|
||||
const d: u32 = c;
|
||||
return #cast(c);
|
||||
if (c != 0) {
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
const main = fn () s32 {
|
||||
const main = fn () *!void {
|
||||
_ = foo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const foo = fn () []u8 {
|
||||
|
@ -1,12 +1,18 @@
|
||||
const std = #import("std");
|
||||
const assert = std.assert;
|
||||
|
||||
const main = fn() s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn() Error!void {
|
||||
var buffer: [65]u8 = undefined;
|
||||
const slice = foo(5, buffer.&);
|
||||
assert(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 {
|
||||
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;
|
||||
return a;
|
||||
if (a != 0) {
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
const std = #import("std");
|
||||
|
||||
const main = fn() s32 {
|
||||
const Error = error{
|
||||
unexpected_result,
|
||||
};
|
||||
|
||||
const main = fn() Error!void {
|
||||
const size = 0x1000;
|
||||
|
||||
if (std.page_allocator.allocate(size, alignment = 12)) |result| {
|
||||
@ -8,13 +12,12 @@ const main = fn() s32 {
|
||||
std.print(bytes = "Allocation succeeded. Freeing...\n");
|
||||
if (std.page_allocator.free(bytes_ptr = result.ptr, bytes_len = result.len)) {
|
||||
std.print(bytes = "Memory freed successfully\n");
|
||||
return 0;
|
||||
} else {
|
||||
std.print(bytes = "Memory freed with errors\n");
|
||||
return 1;
|
||||
return Error.unexpected_result;
|
||||
}
|
||||
} else {
|
||||
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 b: s32 = 124;
|
||||
var c: 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 assert = std.assert;
|
||||
const main = fn () s32 {
|
||||
const main = fn () *!void {
|
||||
var a = [2:0]u8 {1, 2};
|
||||
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