Add param type resolution & stop using stage2, still a bit broken :(
This commit is contained in:
parent
b91a193d04
commit
411e74d364
@ -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);
|
||||||
|
@ -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"),
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user