From 51899ca4af331f50050c9d05d499168a40a5b400 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Tue, 23 Apr 2024 12:03:29 -0600 Subject: [PATCH] Fix slice expression with comptime range --- bootstrap/Compilation.zig | 800 ++++++++++++++++++++++---------------- src/main.nat | 74 +++- 2 files changed, 535 insertions(+), 339 deletions(-) diff --git a/bootstrap/Compilation.zig b/bootstrap/Compilation.zig index 3cddf47..9f7e0ef 100644 --- a/bootstrap/Compilation.zig +++ b/bootstrap/Compilation.zig @@ -4717,7 +4717,6 @@ pub const Builder = struct { switch (array_type.type) { .u8 => { var value: u64 = 0; - _ = &value; for (constant_array.values, 0..) |array_value, i| { value |= array_value.constant_int.value << @as(u6, @intCast(i * 8)); } @@ -5883,6 +5882,7 @@ pub const Builder = struct { slice_to_nullable, slice_coerce_to_zero_termination, slice_zero_to_no_termination, + pointer_to_array_coerce_to_slice, materialize_int, optional_wrap, sign_extend, @@ -6058,7 +6058,12 @@ pub const Builder = struct { }, .pointer => |source_pointer| if (source_pointer.type == destination_slice.child_type) { unreachable; - } else unreachable, + } else switch (unit.types.get(source_pointer.type).*) { + .array => |array| if (array.type == destination_slice.child_type) { + return .pointer_to_array_coerce_to_slice; + } else unreachable, + else => |t| @panic(@tagName(t)), + }, else => |t| @panic(@tagName(t)), } }, @@ -6584,10 +6589,6 @@ pub const Builder = struct { } }, .type_to_error_union => return try builder.resolveTypeToErrorUnion(unit, context, expected_type_index, v), - .error_to_all_errors_error_union => unreachable, - .error_union_to_all_error_union => unreachable, - .error_union_same_error => unreachable, - .error_to_all_errors => unreachable, .slice_zero_to_no_termination => { const cast = try unit.instructions.append(context.my_allocator, .{ .cast = .{ @@ -6605,6 +6606,11 @@ pub const Builder = struct { .type = expected_type_index, }; }, + .pointer_to_array_coerce_to_slice => unreachable, + .error_to_all_errors_error_union => unreachable, + .error_union_to_all_error_union => unreachable, + .error_union_same_error => unreachable, + .error_to_all_errors => unreachable, } }, .array => |expected_array_descriptor| { @@ -9935,35 +9941,37 @@ pub const Builder = struct { }; }, else => { - const pointer_value = try builder.resolveRuntimeValue(unit, context, pointer_type_expect, node.left, .right); + const pointer_like_value = try builder.resolveRuntimeValue(unit, context, pointer_type_expect, node.left, .right); break :block switch (side) { - .left => pointer_value, - .right => right: { - const load_type = switch (type_expect) { - .none => b: { - const pointer_type = unit.types.get(pointer_value.type); - const pointer_element_type = pointer_type.pointer.type; - break :b pointer_element_type; - }, - .type => |type_index| type_index, - else => unreachable, - }; + .left => pointer_like_value, + .right => switch (unit.types.get(pointer_like_value.type).*) { + .pointer => |pointer| right: { + const load_type = switch (type_expect) { + .none => b: { + const pointer_element_type = pointer.type; + break :b pointer_element_type; + }, + .type => |type_index| type_index, + else => unreachable, + }; - const load = try unit.instructions.append(context.my_allocator, .{ - .load = .{ - .value = pointer_value, - .type = load_type, - }, + const load = try unit.instructions.append(context.my_allocator, .{ + .load = .{ + .value = pointer_like_value, + .type = load_type, + }, }); - try builder.appendInstruction(unit, context, load); + try builder.appendInstruction(unit, context, load); - break :right .{ - .value = .{ - .runtime = load, - }, - .type = load_type, - }; + break :right .{ + .value = .{ + .runtime = load, + }, + .type = load_type, + }; + }, + else => |t| @panic(@tagName(t)), }, }; }, @@ -10117,10 +10125,7 @@ pub const Builder = struct { }; } }, - .add, .wrapping_add, .saturated_add, - .sub, .wrapping_sub, .saturated_sub, - .mul, .wrapping_mul, .saturated_mul, - .div, .mod, .bit_and, .bit_or, .bit_xor, .shift_left, .shift_right, .bool_and, .bool_or => block: { + .add, .wrapping_add, .saturated_add, .sub, .wrapping_sub, .saturated_sub, .mul, .wrapping_mul, .saturated_mul, .div, .mod, .bit_and, .bit_or, .bit_xor, .shift_left, .shift_right, .bool_and, .bool_or => block: { const left_node_index = node.left; const right_node_index = node.right; const binary_operation_id: ArithmeticLogicIntegerInstruction = switch (node.id) { @@ -10719,175 +10724,167 @@ pub const Builder = struct { } }; - const slice_value: V = switch (unit.types.get(expression_to_slice.type).*) { - .slice => |slice| blk: { - const extract_value = try unit.instructions.append(context.my_allocator, .{ - .extract_value = .{ - .expression = expression_to_slice, - .index = 0, - }, - }); - try builder.appendInstruction(unit, context, extract_value); + switch (len_expression.value) { + .@"comptime" => { + const pointer_value = switch (unit.types.get(expression_to_slice.type).*) { + .pointer => |pointer| switch (pointer.many) { + true => unreachable, + false => switch (unit.types.get(pointer.type).*) { + .slice => |slice| slice: { + const load = try unit.instructions.append(context.my_allocator, .{ + .load = .{ + .value = expression_to_slice, + .type = slice.child_pointer_type, + }, + }); + try builder.appendInstruction(unit, context, load); - const pointer_type = slice.child_pointer_type; - const pointer_gep = try unit.instructions.append(context.my_allocator, .{ - .get_element_pointer = .{ - .pointer = extract_value, - .is_struct = false, - .base_type = slice.child_type, - .index = range_start, - .name = try unit.processIdentifier(context, "slice_pointer_gep"), - }, - }); - try builder.appendInstruction(unit, context, pointer_gep); + const gep = try unit.instructions.append(context.my_allocator, .{ + .get_element_pointer = .{ + .pointer = load, + .index = range_start, + .base_type = slice.child_type, + .name = try unit.processIdentifier(context, "slice_comptime_expression_slice"), + .is_struct = false, + }, + }); + try builder.appendInstruction(unit, context, gep); - const slice_builder = try unit.instructions.append(context.my_allocator, .{ - .insert_value = .{ - .expression = V{ - .value = .{ - .@"comptime" = .undefined, + break :slice V{ + .value = .{ + .runtime = gep, + }, + .type = try unit.getPointerType(context, .{ + .type = try unit.getArrayType(context, .{ + .type = slice.child_type, + .count = len_expression.value.@"comptime".constant_int.value, + .termination = slice.termination, + }), + .termination = .none, + .mutability = slice.mutability, + .many = true, + .nullable = false, + }), + }; }, - .type = expression_to_slice.type, - }, - .index = 0, - .new_value = .{ - .value = .{ - .runtime = pointer_gep, + .pointer => |child_pointer| switch (type_expect) { + .type => |destination_type_index| switch (unit.types.get(destination_type_index).*) { + .slice => |slice| if (slice.child_type == child_pointer.type) { + unreachable; + } else switch (unit.types.get(child_pointer.type).*) { + .array => |array| if (array.type == slice.child_type) pointer: { + const load = try unit.instructions.append(context.my_allocator, .{ + .load = .{ + .value = expression_to_slice, + .type = pointer.type, + }, + }); + try builder.appendInstruction(unit, context, load); + const gep = try unit.instructions.append(context.my_allocator, .{ + .get_element_pointer = .{ + .pointer = load, + .index = range_start, + .base_type = slice.child_type, + .name = try unit.processIdentifier(context, "slice_comptime_expression_pointer"), + .is_struct = false, + }, + }); + try builder.appendInstruction(unit, context, gep); + break :pointer V{ + .value = .{ + .runtime = gep, + }, + .type = pointer.type, + }; + } else unreachable, + else => |t| @panic(@tagName(t)), + }, + else => |t| @panic(@tagName(t)), + }, + else => |t| @panic(@tagName(t)), }, - .type = pointer_type, + else => |t| @panic(@tagName(t)), }, }, - }); - try builder.appendInstruction(unit, context, slice_builder); - - const final_slice = try unit.instructions.append(context.my_allocator, .{ - .insert_value = .{ - .expression = V{ - .value = .{ - .runtime = slice_builder, - }, - .type = expression_to_slice.type, - }, - .index = 1, - .new_value = len_expression, - }, - }); - - try builder.appendInstruction(unit, context, final_slice); - - break :blk .{ - .value = .{ - .runtime = final_slice, - }, - .type = expression_to_slice.type, + else => |t| @panic(@tagName(t)), }; + + switch (type_expect) { + .type => |destination_type_index| switch (try builder.typecheck(unit, context, destination_type_index, pointer_value.type)) { + .pointer_to_array_coerce_to_slice => switch (pointer_value.value) { + .runtime => { + const insert_pointer = try unit.instructions.append(context.my_allocator, .{ + .insert_value = .{ + .expression = .{ + .value = .{ + .@"comptime" = .@"undefined", + }, + .type = destination_type_index, + }, + .index = 0, + .new_value = pointer_value, + }, + }); + try builder.appendInstruction(unit, context, insert_pointer); + + const insert_length = try unit.instructions.append(context.my_allocator, .{ + .insert_value = .{ + .expression = .{ + .value = .{ + .runtime = insert_pointer, + }, + .type = destination_type_index, + }, + .index = 1, + .new_value = len_expression, + }, + }); + try builder.appendInstruction(unit, context, insert_length); + + break :block V{ + .value = .{ + .runtime = insert_length, + }, + .type = destination_type_index, + }; + }, + else => |t| @panic(@tagName(t)), + }, + else => |t| @panic(@tagName(t)), + }, + else => |t| @panic(@tagName(t)), + } }, - .pointer => |pointer| switch (pointer.many) { - true => blk: { - const pointer_gep = try unit.instructions.append(context.my_allocator, .{ - .get_element_pointer = .{ - .pointer = expression_to_slice.value.runtime, - .is_struct = false, - .base_type = pointer.type, - .index = range_start, - .name = try unit.processIdentifier(context, "pointer_many_slice"), - }, - }); - try builder.appendInstruction(unit, context, pointer_gep); - - const pointer_type = try unit.getPointerType(context, .{ - .type = pointer.type, - .termination = pointer.termination, - .mutability = pointer.mutability, - .many = true, - .nullable = false, - }); - - const slice_type = try unit.getSliceType(context, .{ - .child_type = pointer.type, - .child_pointer_type = pointer_type, - .mutability = pointer.mutability, - .termination = pointer.termination, - .nullable = false, - }); - - const slice_builder = try unit.instructions.append(context.my_allocator, .{ - .insert_value = .{ - .expression = V{ - .value = .{ - .@"comptime" = .undefined, - }, - .type = slice_type, + .runtime => { + const slice_value: V = switch (unit.types.get(expression_to_slice.type).*) { + .slice => |slice| blk: { + const extract_value = try unit.instructions.append(context.my_allocator, .{ + .extract_value = .{ + .expression = expression_to_slice, + .index = 0, }, - .index = 0, - .new_value = .{ - .value = .{ - .runtime = pointer_gep, - }, - .type = pointer_type, - }, - }, - }); - try builder.appendInstruction(unit, context, slice_builder); + }); + try builder.appendInstruction(unit, context, extract_value); - const final_slice = try unit.instructions.append(context.my_allocator, .{ - .insert_value = .{ - .expression = V{ - .value = .{ - .runtime = slice_builder, - }, - .type = slice_type, - }, - .index = 1, - .new_value = len_expression, - }, - }); - try builder.appendInstruction(unit, context, final_slice); - - break :blk .{ - .value = .{ - .runtime = final_slice, - }, - .type = slice_type, - }; - }, - false => switch (unit.types.get(pointer.type).*) { - .array => |array| blk: { - assert(!pointer.nullable); + const pointer_type = slice.child_pointer_type; const pointer_gep = try unit.instructions.append(context.my_allocator, .{ .get_element_pointer = .{ - .pointer = expression_to_slice.value.runtime, - .base_type = array.type, + .pointer = extract_value, .is_struct = false, + .base_type = slice.child_type, .index = range_start, - .name = try unit.processIdentifier(context, "array_slice"), + .name = try unit.processIdentifier(context, "slice_pointer_gep"), }, }); try builder.appendInstruction(unit, context, pointer_gep); - const pointer_type = try unit.getPointerType(context, .{ - .type = array.type, - .termination = array.termination, - .mutability = pointer.mutability, - .many = true, - .nullable = false, - }); - - const slice_type = try unit.getSliceType(context, .{ - .child_type = array.type, - .child_pointer_type = pointer_type, - .termination = array.termination, - .mutability = pointer.mutability, - .nullable = pointer.nullable, - }); - const slice_builder = try unit.instructions.append(context.my_allocator, .{ .insert_value = .{ .expression = V{ .value = .{ .@"comptime" = .undefined, }, - .type = slice_type, + .type = expression_to_slice.type, }, .index = 0, .new_value = .{ @@ -10906,56 +10903,48 @@ pub const Builder = struct { .value = .{ .runtime = slice_builder, }, - .type = slice_type, + .type = expression_to_slice.type, }, .index = 1, .new_value = len_expression, }, }); + try builder.appendInstruction(unit, context, final_slice); break :blk .{ .value = .{ .runtime = final_slice, }, - .type = slice_type, + .type = expression_to_slice.type, }; }, - .pointer => |child_pointer| switch (child_pointer.many) { + .pointer => |pointer| switch (pointer.many) { true => blk: { - assert(!child_pointer.nullable); - const load = try unit.instructions.append(context.my_allocator, .{ - .load = .{ - .value = expression_to_slice, - .type = pointer.type, - }, - }); - try builder.appendInstruction(unit, context, load); - const pointer_gep = try unit.instructions.append(context.my_allocator, .{ .get_element_pointer = .{ - .pointer = load, - .base_type = child_pointer.type, + .pointer = expression_to_slice.value.runtime, .is_struct = false, + .base_type = pointer.type, .index = range_start, - .name = try unit.processIdentifier(context, "double_many_pointer_slice"), + .name = try unit.processIdentifier(context, "pointer_many_slice"), }, }); try builder.appendInstruction(unit, context, pointer_gep); const pointer_type = try unit.getPointerType(context, .{ - .type = child_pointer.type, - .termination = child_pointer.termination, - .mutability = child_pointer.mutability, + .type = pointer.type, + .termination = pointer.termination, + .mutability = pointer.mutability, .many = true, .nullable = false, }); const slice_type = try unit.getSliceType(context, .{ - .child_type = child_pointer.type, + .child_type = pointer.type, .child_pointer_type = pointer_type, - .termination = child_pointer.termination, - .mutability = child_pointer.mutability, + .mutability = pointer.mutability, + .termination = pointer.termination, .nullable = false, }); @@ -10999,23 +10988,16 @@ pub const Builder = struct { .type = slice_type, }; }, - false => switch (unit.types.get(child_pointer.type).*) { + false => switch (unit.types.get(pointer.type).*) { .array => |array| blk: { - const load = try unit.instructions.append(context.my_allocator, .{ - .load = .{ - .value = expression_to_slice, - .type = pointer.type, - }, - }); - try builder.appendInstruction(unit, context, load); - + assert(!pointer.nullable); const pointer_gep = try unit.instructions.append(context.my_allocator, .{ .get_element_pointer = .{ - .pointer = load, + .pointer = expression_to_slice.value.runtime, .base_type = array.type, .is_struct = false, .index = range_start, - .name = try unit.processIdentifier(context, "double_array_slice"), + .name = try unit.processIdentifier(context, "array_slice"), }, }); try builder.appendInstruction(unit, context, pointer_gep); @@ -11023,7 +11005,7 @@ pub const Builder = struct { const pointer_type = try unit.getPointerType(context, .{ .type = array.type, .termination = array.termination, - .mutability = child_pointer.mutability, + .mutability = pointer.mutability, .many = true, .nullable = false, }); @@ -11032,8 +11014,8 @@ pub const Builder = struct { .child_type = array.type, .child_pointer_type = pointer_type, .termination = array.termination, - .mutability = child_pointer.mutability, - .nullable = false, + .mutability = pointer.mutability, + .nullable = pointer.nullable, }); const slice_builder = try unit.instructions.append(context.my_allocator, .{ @@ -11076,133 +11058,291 @@ pub const Builder = struct { .type = slice_type, }; }, + .pointer => |child_pointer| switch (child_pointer.many) { + true => blk: { + assert(!child_pointer.nullable); + const load = try unit.instructions.append(context.my_allocator, .{ + .load = .{ + .value = expression_to_slice, + .type = pointer.type, + }, + }); + try builder.appendInstruction(unit, context, load); + + const pointer_gep = try unit.instructions.append(context.my_allocator, .{ + .get_element_pointer = .{ + .pointer = load, + .base_type = child_pointer.type, + .is_struct = false, + .index = range_start, + .name = try unit.processIdentifier(context, "double_many_pointer_slice"), + }, + }); + try builder.appendInstruction(unit, context, pointer_gep); + + const pointer_type = try unit.getPointerType(context, .{ + .type = child_pointer.type, + .termination = child_pointer.termination, + .mutability = child_pointer.mutability, + .many = true, + .nullable = false, + }); + + const slice_type = try unit.getSliceType(context, .{ + .child_type = child_pointer.type, + .child_pointer_type = pointer_type, + .termination = child_pointer.termination, + .mutability = child_pointer.mutability, + .nullable = false, + }); + + const slice_builder = try unit.instructions.append(context.my_allocator, .{ + .insert_value = .{ + .expression = V{ + .value = .{ + .@"comptime" = .undefined, + }, + .type = slice_type, + }, + .index = 0, + .new_value = .{ + .value = .{ + .runtime = pointer_gep, + }, + .type = pointer_type, + }, + }, + }); + try builder.appendInstruction(unit, context, slice_builder); + + const final_slice = try unit.instructions.append(context.my_allocator, .{ + .insert_value = .{ + .expression = V{ + .value = .{ + .runtime = slice_builder, + }, + .type = slice_type, + }, + .index = 1, + .new_value = len_expression, + }, + }); + try builder.appendInstruction(unit, context, final_slice); + + break :blk .{ + .value = .{ + .runtime = final_slice, + }, + .type = slice_type, + }; + }, + false => switch (unit.types.get(child_pointer.type).*) { + .array => |array| blk: { + const load = try unit.instructions.append(context.my_allocator, .{ + .load = .{ + .value = expression_to_slice, + .type = pointer.type, + }, + }); + try builder.appendInstruction(unit, context, load); + + const pointer_gep = try unit.instructions.append(context.my_allocator, .{ + .get_element_pointer = .{ + .pointer = load, + .base_type = array.type, + .is_struct = false, + .index = range_start, + .name = try unit.processIdentifier(context, "double_array_slice"), + }, + }); + try builder.appendInstruction(unit, context, pointer_gep); + + const pointer_type = try unit.getPointerType(context, .{ + .type = array.type, + .termination = array.termination, + .mutability = child_pointer.mutability, + .many = true, + .nullable = false, + }); + + const slice_type = try unit.getSliceType(context, .{ + .child_type = array.type, + .child_pointer_type = pointer_type, + .termination = array.termination, + .mutability = child_pointer.mutability, + .nullable = false, + }); + + const slice_builder = try unit.instructions.append(context.my_allocator, .{ + .insert_value = .{ + .expression = V{ + .value = .{ + .@"comptime" = .undefined, + }, + .type = slice_type, + }, + .index = 0, + .new_value = .{ + .value = .{ + .runtime = pointer_gep, + }, + .type = pointer_type, + }, + }, + }); + try builder.appendInstruction(unit, context, slice_builder); + + const final_slice = try unit.instructions.append(context.my_allocator, .{ + .insert_value = .{ + .expression = V{ + .value = .{ + .runtime = slice_builder, + }, + .type = slice_type, + }, + .index = 1, + .new_value = len_expression, + }, + }); + try builder.appendInstruction(unit, context, final_slice); + + break :blk .{ + .value = .{ + .runtime = final_slice, + }, + .type = slice_type, + }; + }, + else => |t| @panic(@tagName(t)), + }, + }, + .slice => |slice| blk: { + const load = try unit.instructions.append(context.my_allocator, .{ + .load = .{ + .value = expression_to_slice, + .type = pointer.type, + }, + }); + try builder.appendInstruction(unit, context, load); + + const extract_pointer = try unit.instructions.append(context.my_allocator, .{ + .extract_value = .{ + .expression = .{ + .value = .{ + .runtime = load, + }, + .type = pointer.type, + }, + .index = 0, + }, + }); + try builder.appendInstruction(unit, context, extract_pointer); + + const pointer_gep = try unit.instructions.append(context.my_allocator, .{ + .get_element_pointer = .{ + .pointer = extract_pointer, + .base_type = slice.child_type, + .is_struct = false, + .index = range_start, + .name = try unit.processIdentifier(context, "slice_ptr_gep"), + }, + }); + try builder.appendInstruction(unit, context, pointer_gep); + + const slice_type = pointer.type; + + const slice_builder = try unit.instructions.append(context.my_allocator, .{ + .insert_value = .{ + .expression = V{ + .value = .{ + .@"comptime" = .undefined, + }, + .type = slice_type, + }, + .index = 0, + .new_value = .{ + .value = .{ + .runtime = pointer_gep, + }, + .type = slice.child_pointer_type, + }, + }, + }); + try builder.appendInstruction(unit, context, slice_builder); + + const final_slice = try unit.instructions.append(context.my_allocator, .{ + .insert_value = .{ + .expression = V{ + .value = .{ + .runtime = slice_builder, + }, + .type = slice_type, + }, + .index = 1, + .new_value = len_expression, + }, + }); + try builder.appendInstruction(unit, context, final_slice); + + break :blk .{ + .value = .{ + .runtime = final_slice, + }, + .type = slice_type, + }; + }, else => |t| @panic(@tagName(t)), }, }, - .slice => |slice| blk: { - const load = try unit.instructions.append(context.my_allocator, .{ - .load = .{ - .value = expression_to_slice, - .type = pointer.type, - }, - }); - try builder.appendInstruction(unit, context, load); + else => |t| @panic(@tagName(t)), + }; - const extract_pointer = try unit.instructions.append(context.my_allocator, .{ - .extract_value = .{ - .expression = .{ - .value = .{ - .runtime = load, - }, - .type = pointer.type, + break :block switch (type_expect) { + .none => slice_value, + .type => |type_index| switch (try builder.typecheck(unit, context, type_index, slice_value.type)) { + .success => slice_value, + .type_to_error_union => try builder.resolveTypeToErrorUnion(unit, context, type_index, slice_value), + .slice_to_nullable => b: { + const cast = try unit.instructions.append(context.my_allocator, .{ + .cast = .{ + .id = .slice_to_nullable, + .value = slice_value, + .type = type_index, }, - .index = 0, - }, - }); - try builder.appendInstruction(unit, context, extract_pointer); + }); - const pointer_gep = try unit.instructions.append(context.my_allocator, .{ - .get_element_pointer = .{ - .pointer = extract_pointer, - .base_type = slice.child_type, - .is_struct = false, - .index = range_start, - .name = try unit.processIdentifier(context, "slice_ptr_gep"), - }, - }); - try builder.appendInstruction(unit, context, pointer_gep); - - const slice_type = pointer.type; - - const slice_builder = try unit.instructions.append(context.my_allocator, .{ - .insert_value = .{ - .expression = V{ - .value = .{ - .@"comptime" = .undefined, - }, - .type = slice_type, + try builder.appendInstruction(unit, context, cast); + break :b .{ + .value = .{ + .runtime = cast, }, - .index = 0, - .new_value = .{ - .value = .{ - .runtime = pointer_gep, - }, - .type = slice.child_pointer_type, + .type = type_index, + }; + }, + .slice_zero_to_no_termination => b: { + const cast = try unit.instructions.append(context.my_allocator, .{ + .cast = .{ + .id = .slice_zero_to_no_termination, + .value = slice_value, + .type = type_index, }, - }, - }); - try builder.appendInstruction(unit, context, slice_builder); + }); - const final_slice = try unit.instructions.append(context.my_allocator, .{ - .insert_value = .{ - .expression = V{ - .value = .{ - .runtime = slice_builder, - }, - .type = slice_type, + try builder.appendInstruction(unit, context, cast); + break :b V{ + .value = .{ + .runtime = cast, }, - .index = 1, - .new_value = len_expression, - }, - }); - try builder.appendInstruction(unit, context, final_slice); - - break :blk .{ - .value = .{ - .runtime = final_slice, - }, - .type = slice_type, - }; + .type = type_index, + }; + }, + else => |t| @panic(@tagName(t)), }, else => |t| @panic(@tagName(t)), - }, + }; }, - else => |t| @panic(@tagName(t)), - }; - - break :block switch (type_expect) { - .none => slice_value, - .type => |type_index| switch (try builder.typecheck(unit, context, type_index, slice_value.type)) { - .success => slice_value, - .type_to_error_union => try builder.resolveTypeToErrorUnion(unit, context, type_index, slice_value), - .slice_to_nullable => { - const cast = try unit.instructions.append(context.my_allocator, .{ - .cast = .{ - .id = .slice_to_nullable, - .value = slice_value, - .type = type_index, - }, - }); - - try builder.appendInstruction(unit, context, cast); - return .{ - .value = .{ - .runtime = cast, - }, - .type = type_index, - }; - }, - .slice_zero_to_no_termination => { - const cast = try unit.instructions.append(context.my_allocator, .{ - .cast = .{ - .id = .slice_zero_to_no_termination, - .value = slice_value, - .type = type_index, - }, - }); - - try builder.appendInstruction(unit, context, cast); - return .{ - .value = .{ - .runtime = cast, - }, - .type = type_index, - }; - }, - else => |t| @panic(@tagName(t)), - }, - else => |t| @panic(@tagName(t)), - }; + else => unreachable, + } }, .keyword_false, .keyword_true => .{ .value = .{ @@ -17331,11 +17471,13 @@ pub const Unit = struct { fn resolve_character_literal(unit: *Unit, node_index: Node.Index) !V.Comptime { const node = unit.getNode(node_index); const ch_literal = unit.getExpectedTokenBytes(node.token, .character_literal); - const character = switch (ch_literal.len) { + const character: u8 = switch (ch_literal.len) { 3 => ch_literal[1], // This has a escape character 4 => switch (ch_literal[2]) { 'n' => '\n', + 'r' => '\r', + 't' => '\t', else => unreachable, }, else => unreachable, diff --git a/src/main.nat b/src/main.nat index 032ccb7..1e89b6c 100644 --- a/src/main.nat +++ b/src/main.nat @@ -6,14 +6,75 @@ const print = std.print; const print_usize = std.print_usize; const exit = std.os.exit; -const lex = fn (arena: &Arena, bytes: []const u8) *!void { +const Parser = struct{ + text: [&]const u8, + index: u32 = 0, + length: u32, + current_line: u32 = 0, + current_line_offset: u32 = 0, + + const skip_whitespace = fn (parser: &Parser) void { + const length = parser.length; + + const pointer = parser.text; + while (parser.index < length) { + const ch = pointer[parser.index]; + const new_line = ch == '\r'; + const is_space = ch == ' ' or ch == '\t' or new_line or ch == '\r'; + if (new_line) { + parser.current_line += 1; + parser.current_line_offset = parser.index + 1; + } + + if (!is_space) { + break; + } + + parser.index += 1; + } + } +}; + +const parse = fn (arena: &Arena, bytes: []const u8) *!void { if (bytes.length >= 0xffffffff) { unreachable; } const length: u32 = #cast(bytes.length); + var parser = Parser{ + .text = bytes.pointer, + .length = length, + }; - const max_initial_keyword_len: u32 = 8; + //var index: u32 = 0; + //while (index < length) { + // parser.skip_whitespace(); + + // if (index == length) { + // break; + // } + + // const slice_8 = bytes[index..][0..8]; + // const slice_4 = bytes[index..][0..4]; + // const chunk_8: u64 = #cast(slice_8.@); + // const chunk_4: u64 = #cast(slice_4.@); + // const comptime_mask: u64 = #cast("comptime".@); + // const test_mask: u32 = #cast("test").@; + // const const_mask: u32 = #cast("const").@; + // const var_mask: u32 = #cast("var ").@; + // const is_comptime = chunk_8 == comptime_mask; + // const is_test = chunk_4 == test_mask; + // const is_const = chunk_4 == const_mask; + // const is_var = (chunk_4 & 0xffffff) == (var_mask & 0xffffff); + + // const is_valid = is_comptime or is_test or is_const or is_var; + + // if (is_valid) { + // exit(0); + // } else { + // exit(1); + // } + //} //var index: u32 = 0; //while (index + 64 < length) { @@ -36,13 +97,6 @@ const lex = fn (arena: &Arena, bytes: []const u8) *!void { // const word_byte_count = #trailing_zeroes(space); // const word = bytes[index..][0..word_byte_count]; - // if (byte_equal(word, #name(FileStartToken."comptime"))) { - // } else if (byte_equal(word, #name(FileStartToken."test"))) { - // } else if (byte_equal(word, #name(FileStartToken."const"))) { - // } else if (byte_equal(word, #name(FileStartToken."var"))) { - // } else { - // print("Wrong file declaration start\n"); - // } // break; //} @@ -164,7 +218,7 @@ const command_exe = fn (arena: &Arena, command_arguments: []const [&:0]const u8) const file_buffer = try arena.new_array($u8, file_size); file_descriptor.read_all(file_buffer); - lex(arena, file_buffer); + parse(arena, file_buffer); } const main = fn() *!void {