Merge pull request #164 from birth-software/fix-slice-expression

Fix slice expression with comptime range
This commit is contained in:
David 2024-04-23 12:08:16 -06:00 committed by GitHub
commit eb31e4b663
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 535 additions and 339 deletions

View File

@ -4717,7 +4717,6 @@ pub const Builder = struct {
switch (array_type.type) { switch (array_type.type) {
.u8 => { .u8 => {
var value: u64 = 0; var value: u64 = 0;
_ = &value;
for (constant_array.values, 0..) |array_value, i| { for (constant_array.values, 0..) |array_value, i| {
value |= array_value.constant_int.value << @as(u6, @intCast(i * 8)); value |= array_value.constant_int.value << @as(u6, @intCast(i * 8));
} }
@ -5883,6 +5882,7 @@ pub const Builder = struct {
slice_to_nullable, slice_to_nullable,
slice_coerce_to_zero_termination, slice_coerce_to_zero_termination,
slice_zero_to_no_termination, slice_zero_to_no_termination,
pointer_to_array_coerce_to_slice,
materialize_int, materialize_int,
optional_wrap, optional_wrap,
sign_extend, sign_extend,
@ -6058,7 +6058,12 @@ pub const Builder = struct {
}, },
.pointer => |source_pointer| if (source_pointer.type == destination_slice.child_type) { .pointer => |source_pointer| if (source_pointer.type == destination_slice.child_type) {
unreachable; 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)), 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), .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 => { .slice_zero_to_no_termination => {
const cast = try unit.instructions.append(context.my_allocator, .{ const cast = try unit.instructions.append(context.my_allocator, .{
.cast = .{ .cast = .{
@ -6605,6 +6606,11 @@ pub const Builder = struct {
.type = expected_type_index, .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| { .array => |expected_array_descriptor| {
@ -9935,35 +9941,37 @@ pub const Builder = struct {
}; };
}, },
else => { 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) { break :block switch (side) {
.left => pointer_value, .left => pointer_like_value,
.right => right: { .right => switch (unit.types.get(pointer_like_value.type).*) {
const load_type = switch (type_expect) { .pointer => |pointer| right: {
.none => b: { const load_type = switch (type_expect) {
const pointer_type = unit.types.get(pointer_value.type); .none => b: {
const pointer_element_type = pointer_type.pointer.type; const pointer_element_type = pointer.type;
break :b pointer_element_type; break :b pointer_element_type;
}, },
.type => |type_index| type_index, .type => |type_index| type_index,
else => unreachable, else => unreachable,
}; };
const load = try unit.instructions.append(context.my_allocator, .{ const load = try unit.instructions.append(context.my_allocator, .{
.load = .{ .load = .{
.value = pointer_value, .value = pointer_like_value,
.type = load_type, .type = load_type,
}, },
}); });
try builder.appendInstruction(unit, context, load); try builder.appendInstruction(unit, context, load);
break :right .{ break :right .{
.value = .{ .value = .{
.runtime = load, .runtime = load,
}, },
.type = load_type, .type = load_type,
}; };
},
else => |t| @panic(@tagName(t)),
}, },
}; };
}, },
@ -10117,10 +10125,7 @@ pub const Builder = struct {
}; };
} }
}, },
.add, .wrapping_add, .saturated_add, .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: {
.sub, .wrapping_sub, .saturated_sub,
.mul, .wrapping_mul, .saturated_mul,
.div, .mod, .bit_and, .bit_or, .bit_xor, .shift_left, .shift_right, .bool_and, .bool_or => block: {
const left_node_index = node.left; const left_node_index = node.left;
const right_node_index = node.right; const right_node_index = node.right;
const binary_operation_id: ArithmeticLogicIntegerInstruction = switch (node.id) { const binary_operation_id: ArithmeticLogicIntegerInstruction = switch (node.id) {
@ -10719,175 +10724,167 @@ pub const Builder = struct {
} }
}; };
const slice_value: V = switch (unit.types.get(expression_to_slice.type).*) { switch (len_expression.value) {
.slice => |slice| blk: { .@"comptime" => {
const extract_value = try unit.instructions.append(context.my_allocator, .{ const pointer_value = switch (unit.types.get(expression_to_slice.type).*) {
.extract_value = .{ .pointer => |pointer| switch (pointer.many) {
.expression = expression_to_slice, true => unreachable,
.index = 0, false => switch (unit.types.get(pointer.type).*) {
}, .slice => |slice| slice: {
}); const load = try unit.instructions.append(context.my_allocator, .{
try builder.appendInstruction(unit, context, extract_value); .load = .{
.value = expression_to_slice,
.type = slice.child_pointer_type,
},
});
try builder.appendInstruction(unit, context, load);
const pointer_type = slice.child_pointer_type; const gep = try unit.instructions.append(context.my_allocator, .{
const pointer_gep = try unit.instructions.append(context.my_allocator, .{ .get_element_pointer = .{
.get_element_pointer = .{ .pointer = load,
.pointer = extract_value, .index = range_start,
.is_struct = false, .base_type = slice.child_type,
.base_type = slice.child_type, .name = try unit.processIdentifier(context, "slice_comptime_expression_slice"),
.index = range_start, .is_struct = false,
.name = try unit.processIdentifier(context, "slice_pointer_gep"), },
}, });
}); try builder.appendInstruction(unit, context, gep);
try builder.appendInstruction(unit, context, pointer_gep);
const slice_builder = try unit.instructions.append(context.my_allocator, .{ break :slice V{
.insert_value = .{ .value = .{
.expression = V{ .runtime = gep,
.value = .{ },
.@"comptime" = .undefined, .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, .pointer => |child_pointer| switch (type_expect) {
}, .type => |destination_type_index| switch (unit.types.get(destination_type_index).*) {
.index = 0, .slice => |slice| if (slice.child_type == child_pointer.type) {
.new_value = .{ unreachable;
.value = .{ } else switch (unit.types.get(child_pointer.type).*) {
.runtime = pointer_gep, .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)),
}, },
}, },
}); 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,
}; };
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) { .runtime => {
true => blk: { const slice_value: V = switch (unit.types.get(expression_to_slice.type).*) {
const pointer_gep = try unit.instructions.append(context.my_allocator, .{ .slice => |slice| blk: {
.get_element_pointer = .{ const extract_value = try unit.instructions.append(context.my_allocator, .{
.pointer = expression_to_slice.value.runtime, .extract_value = .{
.is_struct = false, .expression = expression_to_slice,
.base_type = pointer.type, .index = 0,
.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,
}, },
.index = 0, });
.new_value = .{ try builder.appendInstruction(unit, context, extract_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, .{ const pointer_type = slice.child_pointer_type;
.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_gep = try unit.instructions.append(context.my_allocator, .{ const pointer_gep = try unit.instructions.append(context.my_allocator, .{
.get_element_pointer = .{ .get_element_pointer = .{
.pointer = expression_to_slice.value.runtime, .pointer = extract_value,
.base_type = array.type,
.is_struct = false, .is_struct = false,
.base_type = slice.child_type,
.index = range_start, .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); 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, .{ const slice_builder = try unit.instructions.append(context.my_allocator, .{
.insert_value = .{ .insert_value = .{
.expression = V{ .expression = V{
.value = .{ .value = .{
.@"comptime" = .undefined, .@"comptime" = .undefined,
}, },
.type = slice_type, .type = expression_to_slice.type,
}, },
.index = 0, .index = 0,
.new_value = .{ .new_value = .{
@ -10906,56 +10903,48 @@ pub const Builder = struct {
.value = .{ .value = .{
.runtime = slice_builder, .runtime = slice_builder,
}, },
.type = slice_type, .type = expression_to_slice.type,
}, },
.index = 1, .index = 1,
.new_value = len_expression, .new_value = len_expression,
}, },
}); });
try builder.appendInstruction(unit, context, final_slice); try builder.appendInstruction(unit, context, final_slice);
break :blk .{ break :blk .{
.value = .{ .value = .{
.runtime = final_slice, .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: { 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, .{ const pointer_gep = try unit.instructions.append(context.my_allocator, .{
.get_element_pointer = .{ .get_element_pointer = .{
.pointer = load, .pointer = expression_to_slice.value.runtime,
.base_type = child_pointer.type,
.is_struct = false, .is_struct = false,
.base_type = pointer.type,
.index = range_start, .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); try builder.appendInstruction(unit, context, pointer_gep);
const pointer_type = try unit.getPointerType(context, .{ const pointer_type = try unit.getPointerType(context, .{
.type = child_pointer.type, .type = pointer.type,
.termination = child_pointer.termination, .termination = pointer.termination,
.mutability = child_pointer.mutability, .mutability = pointer.mutability,
.many = true, .many = true,
.nullable = false, .nullable = false,
}); });
const slice_type = try unit.getSliceType(context, .{ const slice_type = try unit.getSliceType(context, .{
.child_type = child_pointer.type, .child_type = pointer.type,
.child_pointer_type = pointer_type, .child_pointer_type = pointer_type,
.termination = child_pointer.termination, .mutability = pointer.mutability,
.mutability = child_pointer.mutability, .termination = pointer.termination,
.nullable = false, .nullable = false,
}); });
@ -10999,23 +10988,16 @@ pub const Builder = struct {
.type = slice_type, .type = slice_type,
}; };
}, },
false => switch (unit.types.get(child_pointer.type).*) { false => switch (unit.types.get(pointer.type).*) {
.array => |array| blk: { .array => |array| blk: {
const load = try unit.instructions.append(context.my_allocator, .{ assert(!pointer.nullable);
.load = .{
.value = expression_to_slice,
.type = pointer.type,
},
});
try builder.appendInstruction(unit, context, load);
const pointer_gep = try unit.instructions.append(context.my_allocator, .{ const pointer_gep = try unit.instructions.append(context.my_allocator, .{
.get_element_pointer = .{ .get_element_pointer = .{
.pointer = load, .pointer = expression_to_slice.value.runtime,
.base_type = array.type, .base_type = array.type,
.is_struct = false, .is_struct = false,
.index = range_start, .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); try builder.appendInstruction(unit, context, pointer_gep);
@ -11023,7 +11005,7 @@ pub const Builder = struct {
const pointer_type = try unit.getPointerType(context, .{ const pointer_type = try unit.getPointerType(context, .{
.type = array.type, .type = array.type,
.termination = array.termination, .termination = array.termination,
.mutability = child_pointer.mutability, .mutability = pointer.mutability,
.many = true, .many = true,
.nullable = false, .nullable = false,
}); });
@ -11032,8 +11014,8 @@ pub const Builder = struct {
.child_type = array.type, .child_type = array.type,
.child_pointer_type = pointer_type, .child_pointer_type = pointer_type,
.termination = array.termination, .termination = array.termination,
.mutability = child_pointer.mutability, .mutability = pointer.mutability,
.nullable = false, .nullable = pointer.nullable,
}); });
const slice_builder = try unit.instructions.append(context.my_allocator, .{ const slice_builder = try unit.instructions.append(context.my_allocator, .{
@ -11076,133 +11058,291 @@ pub const Builder = struct {
.type = slice_type, .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)), else => |t| @panic(@tagName(t)),
}, },
}, },
.slice => |slice| blk: { else => |t| @panic(@tagName(t)),
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, .{ break :block switch (type_expect) {
.extract_value = .{ .none => slice_value,
.expression = .{ .type => |type_index| switch (try builder.typecheck(unit, context, type_index, slice_value.type)) {
.value = .{ .success => slice_value,
.runtime = load, .type_to_error_union => try builder.resolveTypeToErrorUnion(unit, context, type_index, slice_value),
}, .slice_to_nullable => b: {
.type = pointer.type, 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, .{ try builder.appendInstruction(unit, context, cast);
.get_element_pointer = .{ break :b .{
.pointer = extract_pointer, .value = .{
.base_type = slice.child_type, .runtime = cast,
.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, .type = type_index,
.new_value = .{ };
.value = .{ },
.runtime = pointer_gep, .slice_zero_to_no_termination => b: {
}, const cast = try unit.instructions.append(context.my_allocator, .{
.type = slice.child_pointer_type, .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, .{ try builder.appendInstruction(unit, context, cast);
.insert_value = .{ break :b V{
.expression = V{ .value = .{
.value = .{ .runtime = cast,
.runtime = slice_builder,
},
.type = slice_type,
}, },
.index = 1, .type = type_index,
.new_value = len_expression, };
}, },
}); else => |t| @panic(@tagName(t)),
try builder.appendInstruction(unit, context, final_slice);
break :blk .{
.value = .{
.runtime = final_slice,
},
.type = slice_type,
};
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}, };
}, },
else => |t| @panic(@tagName(t)), else => unreachable,
}; }
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)),
};
}, },
.keyword_false, .keyword_true => .{ .keyword_false, .keyword_true => .{
.value = .{ .value = .{
@ -17331,11 +17471,13 @@ pub const Unit = struct {
fn resolve_character_literal(unit: *Unit, node_index: Node.Index) !V.Comptime { fn resolve_character_literal(unit: *Unit, node_index: Node.Index) !V.Comptime {
const node = unit.getNode(node_index); const node = unit.getNode(node_index);
const ch_literal = unit.getExpectedTokenBytes(node.token, .character_literal); 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], 3 => ch_literal[1],
// This has a escape character // This has a escape character
4 => switch (ch_literal[2]) { 4 => switch (ch_literal[2]) {
'n' => '\n', 'n' => '\n',
'r' => '\r',
't' => '\t',
else => unreachable, else => unreachable,
}, },
else => unreachable, else => unreachable,

View File

@ -6,14 +6,75 @@ const print = std.print;
const print_usize = std.print_usize; const print_usize = std.print_usize;
const exit = std.os.exit; const exit = std.os.exit;
const lex = fn (arena: &Arena, bytes: []const u8) *!void { 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) { if (bytes.length >= 0xffffffff) {
unreachable; unreachable;
} }
const length: u32 = #cast(bytes.length); 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; //var index: u32 = 0;
//while (index + 64 < length) { //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_byte_count = #trailing_zeroes(space);
// const word = bytes[index..][0..word_byte_count]; // 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; // 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); const file_buffer = try arena.new_array($u8, file_size);
file_descriptor.read_all(file_buffer); file_descriptor.read_all(file_buffer);
lex(arena, file_buffer); parse(arena, file_buffer);
} }
const main = fn() *!void { const main = fn() *!void {