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,8 +6058,13 @@ 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 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 unreachable,
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
},
else => |t| @panic(@tagName(t)),
} }
}, },
.function => |destination_function_prototype_index| { .function => |destination_function_prototype_index| {
@ -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,15 +9941,15 @@ 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).*) {
.pointer => |pointer| right: {
const load_type = switch (type_expect) { const load_type = switch (type_expect) {
.none => b: { .none => b: {
const pointer_type = unit.types.get(pointer_value.type); const pointer_element_type = pointer.type;
const pointer_element_type = pointer_type.pointer.type;
break :b pointer_element_type; break :b pointer_element_type;
}, },
.type => |type_index| type_index, .type => |type_index| type_index,
@ -9952,7 +9958,7 @@ pub const Builder = struct {
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,
}, },
}); });
@ -9965,6 +9971,8 @@ pub const Builder = struct {
.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,6 +10724,138 @@ pub const Builder = struct {
} }
}; };
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 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);
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,
}),
};
},
.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)),
},
else => |t| @panic(@tagName(t)),
},
},
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)),
}
},
.runtime => {
const slice_value: V = switch (unit.types.get(expression_to_slice.type).*) { const slice_value: V = switch (unit.types.get(expression_to_slice.type).*) {
.slice => |slice| blk: { .slice => |slice| blk: {
const extract_value = try unit.instructions.append(context.my_allocator, .{ const extract_value = try unit.instructions.append(context.my_allocator, .{
@ -11165,7 +11302,7 @@ pub const Builder = struct {
.type => |type_index| switch (try builder.typecheck(unit, context, type_index, slice_value.type)) { .type => |type_index| switch (try builder.typecheck(unit, context, type_index, slice_value.type)) {
.success => slice_value, .success => slice_value,
.type_to_error_union => try builder.resolveTypeToErrorUnion(unit, context, type_index, slice_value), .type_to_error_union => try builder.resolveTypeToErrorUnion(unit, context, type_index, slice_value),
.slice_to_nullable => { .slice_to_nullable => b: {
const cast = try unit.instructions.append(context.my_allocator, .{ const cast = try unit.instructions.append(context.my_allocator, .{
.cast = .{ .cast = .{
.id = .slice_to_nullable, .id = .slice_to_nullable,
@ -11175,14 +11312,14 @@ pub const Builder = struct {
}); });
try builder.appendInstruction(unit, context, cast); try builder.appendInstruction(unit, context, cast);
return .{ break :b .{
.value = .{ .value = .{
.runtime = cast, .runtime = cast,
}, },
.type = type_index, .type = type_index,
}; };
}, },
.slice_zero_to_no_termination => { .slice_zero_to_no_termination => b: {
const cast = try unit.instructions.append(context.my_allocator, .{ const cast = try unit.instructions.append(context.my_allocator, .{
.cast = .{ .cast = .{
.id = .slice_zero_to_no_termination, .id = .slice_zero_to_no_termination,
@ -11192,7 +11329,7 @@ pub const Builder = struct {
}); });
try builder.appendInstruction(unit, context, cast); try builder.appendInstruction(unit, context, cast);
return .{ break :b V{
.value = .{ .value = .{
.runtime = cast, .runtime = cast,
}, },
@ -11204,6 +11341,9 @@ pub const Builder = struct {
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}; };
}, },
else => unreachable,
}
},
.keyword_false, .keyword_true => .{ .keyword_false, .keyword_true => .{
.value = .{ .value = .{
.@"comptime" = .{ .@"comptime" = .{
@ -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 {