Add param type resolution & stop using stage2, still a bit broken :(

This commit is contained in:
Auguste Rame 2022-11-08 15:54:30 -05:00
parent b91a193d04
commit 411e74d364
No known key found for this signature in database
GPG Key ID: 3A5E3F90DF2AAEFE
2 changed files with 38 additions and 18 deletions

View File

@ -13,7 +13,7 @@ pub fn build(b: *std.build.Builder) !void {
const mode = b.standardReleaseOptions(); const mode = b.standardReleaseOptions();
const exe = b.addExecutable("zls", "src/main.zig"); const exe = b.addExecutable("zls", "src/main.zig");
// exe.use_stage1 = true; exe.use_stage1 = true;
const exe_options = b.addOptions(); const exe_options = b.addOptions();
exe.addOptions("build_options", exe_options); exe.addOptions("build_options", exe_options);
@ -134,7 +134,7 @@ pub fn build(b: *std.build.Builder) !void {
}); });
} }
// tests.use_stage1 = true; tests.use_stage1 = true;
tests.addPackage(.{ .name = "zls", .source = .{ .path = "src/zls.zig" }, .dependencies = exe.packages.items }); tests.addPackage(.{ .name = "zls", .source = .{ .path = "src/zls.zig" }, .dependencies = exe.packages.items });
tests.setBuildMode(.Debug); tests.setBuildMode(.Debug);
tests.setTarget(target); tests.setTarget(target);

View File

@ -67,7 +67,8 @@ pub const TypeInfo = union(enum) {
return self.hasher.final(); return self.hasher.final();
} }
pub fn eql(self: @This(), a: TypeInfo, b: TypeInfo) bool { pub fn eql(self: @This(), a: TypeInfo, b: TypeInfo) bool {
return TypeInfo.eql(self.interpreter, a, b); _ = self;
return TypeInfo.eql(a, b);
} }
}; };
@ -130,15 +131,14 @@ pub const TypeInfo = union(enum) {
array: Array, array: Array,
pub fn eql(interpreter: ComptimeInterpreter, a: TypeInfo, b: TypeInfo) bool { pub fn eql(a: TypeInfo, b: TypeInfo) bool {
if (std.meta.activeTag(a) != std.meta.activeTag(b)) return false; if (std.meta.activeTag(a) != std.meta.activeTag(b)) return false;
return switch (a) { return switch (a) {
.@"struct" => false, // Struct declarations can never be equal .@"struct" => false, // Struct declarations can never be equal (this is a lie, gotta fix this)
.pointer => p: { .pointer => p: {
const ap = a.pointer; const ap = a.pointer;
const bp = b.pointer; const bp = b.pointer;
break :p ap.size == bp.size and ap.is_const == bp.is_const and ap.is_volatile == bp.is_volatile and eql( break :p ap.size == bp.size and ap.is_const == bp.is_const and ap.is_volatile == bp.is_volatile and eql(
interpreter,
ap.child.getTypeInfo(), ap.child.getTypeInfo(),
bp.child.getTypeInfo(), bp.child.getTypeInfo(),
) and ap.is_allowzero == bp.is_allowzero and ((ap.sentinel == null and bp.sentinel == null) or ((ap.sentinel != null and bp.sentinel != null) and ap.sentinel.?.eql(bp.sentinel.?))); ) and ap.is_allowzero == bp.is_allowzero and ((ap.sentinel == null and bp.sentinel == null) or ((ap.sentinel != null and bp.sentinel != null) and ap.sentinel.?.eql(bp.sentinel.?)));
@ -460,7 +460,10 @@ pub const ValueFormatter = struct {
return switch (ti) { return switch (ti) {
.int, .@"comptime_int" => switch (value.value_data.*) { .int, .@"comptime_int" => switch (value.value_data.*) {
inline .unsigned_int, .signed_int, .big_int => |a| try writer.print("{d}", .{a}), .unsigned_int => |a| try writer.print("{d}", .{a}),
.signed_int => |a| try writer.print("{d}", .{a}),
.big_int => |a| try writer.print("{d}", .{a}),
else => unreachable, else => unreachable,
}, },
.@"type" => try writer.print("{ }", .{form.interpreter.formatTypeInfo(value.value_data.@"type".getTypeInfo())}), .@"type" => try writer.print("{ }", .{form.interpreter.formatTypeInfo(value.value_data.@"type".getTypeInfo())}),
@ -668,14 +671,19 @@ pub fn cast(
const to_type_info = dest_type.getTypeInfo(); const to_type_info = dest_type.getTypeInfo();
const from_type_info = value.@"type".getTypeInfo(); const from_type_info = value.@"type".getTypeInfo();
// TODO: Implement more implicit casts
if (from_type_info.eql(to_type_info)) return value;
const err = switch (from_type_info) { const err = switch (from_type_info) {
.@"comptime_int" => switch (to_type_info) { .@"comptime_int" => switch (to_type_info) {
.int => { .int => {
if (value_data.bitCount().? > to_type_info.int.bits) { if (value_data.bitCount().? > to_type_info.int.bits) {
switch (value_data.*) { switch (value_data.*) {
inline .unsigned_int, .signed_int, .big_int => |bi| { .unsigned_int => |bi| try interpreter.recordError(node_idx, "invalid_cast", try std.fmt.allocPrint(interpreter.allocator, "integer value {d} cannot be coerced to type '{s}'", .{ bi, interpreter.formatTypeInfo(to_type_info) })),
try interpreter.recordError(node_idx, "invalid_cast", try std.fmt.allocPrint(interpreter.allocator, "integer value {d} cannot be coerced to type '{s}'", .{ bi, interpreter.formatTypeInfo(to_type_info) })); .signed_int => |bi| try interpreter.recordError(node_idx, "invalid_cast", try std.fmt.allocPrint(interpreter.allocator, "integer value {d} cannot be coerced to type '{s}'", .{ bi, interpreter.formatTypeInfo(to_type_info) })),
}, .big_int => |bi| try interpreter.recordError(node_idx, "invalid_cast", try std.fmt.allocPrint(interpreter.allocator, "integer value {d} cannot be coerced to type '{s}'", .{ bi, interpreter.formatTypeInfo(to_type_info) })),
else => unreachable, else => unreachable,
} }
return error.InvalidCast; return error.InvalidCast;
@ -956,8 +964,8 @@ pub fn interpret(
return InterpretResult{ .value = try (interpreter.huntItDown(scope.?, value, options) catch |err| { return InterpretResult{ .value = try (interpreter.huntItDown(scope.?, value, options) catch |err| {
if (err == error.IdentifierNotFound) try interpreter.recordError( if (err == error.IdentifierNotFound) try interpreter.recordError(
node_idx, node_idx,
"identifier_not_found", "undeclared_identifier",
try std.fmt.allocPrint(interpreter.allocator, "Couldn't find identifier \"{s}\"", .{value}), try std.fmt.allocPrint(interpreter.allocator, "use of undeclared identifier '{s}'", .{value}),
); );
return err; return err;
}).getValue() }; }).getValue() };
@ -974,8 +982,8 @@ pub fn interpret(
var scope_sub_decl = irv.value_data.@"type".interpreter.huntItDown(sub_scope, rhs_str, options) catch |err| { var scope_sub_decl = irv.value_data.@"type".interpreter.huntItDown(sub_scope, rhs_str, options) catch |err| {
if (err == error.IdentifierNotFound) try interpreter.recordError( if (err == error.IdentifierNotFound) try interpreter.recordError(
node_idx, node_idx,
"identifier_not_found", "undeclared_identifier",
try std.fmt.allocPrint(interpreter.allocator, "Couldn't find identifier \"{s}\"", .{rhs_str}), try std.fmt.allocPrint(interpreter.allocator, "use of undeclared identifier '{s}'", .{rhs_str}),
); );
return err; return err;
}; };
@ -1063,7 +1071,10 @@ pub fn interpret(
=> { => {
// TODO: Actually consider operators // TODO: Actually consider operators
if (std.mem.eql(u8, tree.getNodeSource(data[node_idx].lhs), "_")) return InterpretResult{ .nothing = {} }; if (std.mem.eql(u8, tree.getNodeSource(data[node_idx].lhs), "_")) {
_ = try interpreter.interpret(data[node_idx].rhs, scope.?, options);
return InterpretResult{ .nothing = {} };
}
var ir = try interpreter.interpret(data[node_idx].lhs, scope, options); var ir = try interpreter.interpret(data[node_idx].lhs, scope, options);
var to_value = try ir.getValue(); var to_value = try ir.getValue();
@ -1400,7 +1411,7 @@ pub fn call(
arguments: []const Value, arguments: []const Value,
options: InterpretOptions, options: InterpretOptions,
) InterpretError!CallResult { ) InterpretError!CallResult {
_ = options; // _ = options;
// TODO: type check args // TODO: type check args
@ -1419,12 +1430,21 @@ pub fn call(
var arg_index: usize = 0; var arg_index: usize = 0;
while (ast.nextFnParam(&arg_it)) |param| { while (ast.nextFnParam(&arg_it)) |param| {
if (arg_index >= arguments.len) return error.MissingArguments; if (arg_index >= arguments.len) return error.MissingArguments;
var tex = try (try interpreter.interpret(param.type_expr, fn_scope, options)).getValue();
if (tex.@"type".getTypeInfo() != .@"type") {
try interpreter.recordError(
param.type_expr,
"expected_type",
std.fmt.allocPrint(interpreter.allocator, "expected type 'type', found '{s}'", .{interpreter.formatTypeInfo(tex.@"type".getTypeInfo())}) catch return error.CriticalAstFailure,
);
return error.InvalidCast;
}
if (param.name_token) |nt| { if (param.name_token) |nt| {
const decl = Declaration{ const decl = Declaration{
.scope = fn_scope, .scope = fn_scope,
.node_idx = param.type_expr, .node_idx = param.type_expr,
.name = tree.tokenSlice(nt), .name = tree.tokenSlice(nt),
.value = arguments[arg_index], .value = try interpreter.cast(arguments[arg_index].node_idx, tex.value_data.@"type", arguments[arg_index]),
}; };
try fn_scope.declarations.put(interpreter.allocator, tree.tokenSlice(nt), decl); try fn_scope.declarations.put(interpreter.allocator, tree.tokenSlice(nt), decl);
arg_index += 1; arg_index += 1;
@ -1438,7 +1458,7 @@ pub fn call(
return CallResult{ return CallResult{
.scope = fn_scope, .scope = fn_scope,
.result = switch (result) { .result = switch (result) {
.@"return" => .{ .nothing = {} }, .@"return", .nothing => .{ .nothing = {} }, // nothing could be due to an error
.@"return_with_value" => |v| .{ .value = v }, .@"return_with_value" => |v| .{ .value = v },
else => @panic("bruh"), else => @panic("bruh"),
}, },