restructure ComptieInterpreter tests
This commit is contained in:
parent
98899ed0cf
commit
04d281340c
@ -12,3 +12,4 @@ pub const types = @import("lsp.zig");
|
|||||||
pub const URI = @import("uri.zig");
|
pub const URI = @import("uri.zig");
|
||||||
pub const DocumentStore = @import("DocumentStore.zig");
|
pub const DocumentStore = @import("DocumentStore.zig");
|
||||||
pub const ComptimeInterpreter = @import("ComptimeInterpreter.zig");
|
pub const ComptimeInterpreter = @import("ComptimeInterpreter.zig");
|
||||||
|
pub const InternPool = @import("InternPool.zig");
|
||||||
|
@ -1,98 +1,164 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const zls = @import("zls");
|
const zls = @import("zls");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
const Ast = std.zig.Ast;
|
const Ast = std.zig.Ast;
|
||||||
|
|
||||||
const ComptimeInterpreter = zls.ComptimeInterpreter;
|
const ComptimeInterpreter = zls.ComptimeInterpreter;
|
||||||
|
const InternPool = zls.InternPool;
|
||||||
|
const Index = InternPool.Index;
|
||||||
|
const Key = InternPool.Key;
|
||||||
|
|
||||||
const allocator: std.mem.Allocator = std.testing.allocator;
|
const allocator: std.mem.Allocator = std.testing.allocator;
|
||||||
|
|
||||||
test "ComptimeInterpreter - basic test" {
|
test "ComptimeInterpreter - call return primitive type" {
|
||||||
var config = zls.Config{};
|
try testCallCheck(
|
||||||
var doc_store = zls.DocumentStore{
|
\\pub fn Foo() type {
|
||||||
.allocator = allocator,
|
\\ return bool;
|
||||||
.config = &config,
|
|
||||||
};
|
|
||||||
defer doc_store.deinit();
|
|
||||||
|
|
||||||
_ = try doc_store.openDocument("file:///file.zig",
|
|
||||||
\\pub fn ReturnMyType(comptime my_arg: bool) type {
|
|
||||||
\\ var abc = z: {break :z if (!my_arg) 123 else 0;};
|
|
||||||
\\ if (abc == 123) return u69;
|
|
||||||
\\ return u8;
|
|
||||||
\\}
|
\\}
|
||||||
);
|
, &.{}, .{ .simple = .bool });
|
||||||
|
|
||||||
var interpreter = ComptimeInterpreter{
|
try testCallCheck(
|
||||||
.allocator = allocator,
|
\\pub fn Foo() type {
|
||||||
.arena = std.heap.ArenaAllocator.init(allocator),
|
\\ return u32;
|
||||||
.document_store = &doc_store,
|
\\}
|
||||||
.uri = "file:///file.zig",
|
, &.{}, .{ .int_type = .{ .signedness = .unsigned, .bits = 32 } });
|
||||||
};
|
|
||||||
defer interpreter.deinit();
|
|
||||||
|
|
||||||
_ = try interpreter.interpret(0, 0, .{});
|
try testCallCheck(
|
||||||
|
\\pub fn Foo() type {
|
||||||
|
\\ return i128;
|
||||||
|
\\}
|
||||||
|
, &.{}, .{ .int_type = .{ .signedness = .signed, .bits = 128 } });
|
||||||
|
|
||||||
var bool_type = try interpreter.ip.get(allocator, .{ .simple = .bool });
|
try testCallCheck(
|
||||||
var bool_true = try interpreter.ip.get(allocator, .{ .simple = .bool_true });
|
\\pub fn Foo() type {
|
||||||
var bool_false = try interpreter.ip.get(allocator, .{ .simple = .bool_false });
|
\\ const alpha = i128;
|
||||||
|
\\ return alpha;
|
||||||
var arg_false = ComptimeInterpreter.Value{
|
\\}
|
||||||
.interpreter = &interpreter,
|
, &.{}, .{ .int_type = .{ .signedness = .signed, .bits = 128 } });
|
||||||
.node_idx = std.math.maxInt(Ast.Node.Index),
|
|
||||||
.ty = bool_type,
|
|
||||||
.val = bool_false,
|
|
||||||
};
|
|
||||||
var arg_true = ComptimeInterpreter.Value{
|
|
||||||
.interpreter = &interpreter,
|
|
||||||
.node_idx = std.math.maxInt(Ast.Node.Index),
|
|
||||||
.ty = bool_type,
|
|
||||||
.val = bool_true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const function_node: Ast.Node.Index = 4;
|
|
||||||
|
|
||||||
const call_with_false = try interpreter.call(0, function_node, &.{arg_false}, .{});
|
|
||||||
const call_with_true = try interpreter.call(0, function_node, &.{arg_true}, .{});
|
|
||||||
|
|
||||||
try std.testing.expectFmt("u69", "{any}", .{call_with_false.result.value.val.fmtValue(call_with_false.result.value.ty, &interpreter.ip)});
|
|
||||||
try std.testing.expectFmt("u8", "{any}", .{call_with_true.result.value.val.fmtValue(call_with_true.result.value.ty, &interpreter.ip)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ComptimeInterpreter - struct" {
|
test "ComptimeInterpreter - call return struct" {
|
||||||
var config = zls.Config{};
|
var result = try testCall(
|
||||||
var doc_store = zls.DocumentStore{
|
\\pub fn Foo() type {
|
||||||
.allocator = allocator,
|
|
||||||
.config = &config,
|
|
||||||
};
|
|
||||||
defer doc_store.deinit();
|
|
||||||
|
|
||||||
_ = try doc_store.openDocument("file:///file.zig",
|
|
||||||
\\pub fn ReturnMyType() type {
|
|
||||||
\\ return struct {
|
\\ return struct {
|
||||||
\\ slay: bool,
|
\\ slay: bool,
|
||||||
\\ var abc = 123;
|
\\ var abc = 123;
|
||||||
\\ };
|
\\ };
|
||||||
\\}
|
\\}
|
||||||
);
|
, &.{});
|
||||||
|
defer result.deinit();
|
||||||
|
const struct_info = result.key.struct_type;
|
||||||
|
try std.testing.expectEqual(Index.none, struct_info.backing_int_ty);
|
||||||
|
try std.testing.expectEqual(std.builtin.Type.ContainerLayout.Auto, struct_info.layout);
|
||||||
|
try std.testing.expectEqual(@as(usize, 1), struct_info.fields.len);
|
||||||
|
// try std.testing.expectEqualStrings("slay", struct_info.fields[0].name);
|
||||||
|
// try std.testing.expect(struct_info.fields[0].ty != .none); // TODO check for bool
|
||||||
|
}
|
||||||
|
|
||||||
|
test "ComptimeInterpreter - call comptime argument" {
|
||||||
|
const source =
|
||||||
|
\\pub fn Foo(comptime my_arg: bool) type {
|
||||||
|
\\ var abc = z: {break :z if (!my_arg) 123 else 0;};
|
||||||
|
\\ if (abc == 123) return u69;
|
||||||
|
\\ return u8;
|
||||||
|
\\}
|
||||||
|
;
|
||||||
|
|
||||||
|
var result1 = try testCall(source, &.{
|
||||||
|
Value{
|
||||||
|
.ty = .{ .simple = .bool },
|
||||||
|
.val = .{ .simple = .bool_true },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
defer result1.deinit();
|
||||||
|
try std.testing.expectEqual(Key{ .int_type = .{ .signedness = .unsigned, .bits = 8 } }, result1.key);
|
||||||
|
|
||||||
|
var result2 = try testCall(source, &.{
|
||||||
|
Value{
|
||||||
|
.ty = .{ .simple = .bool },
|
||||||
|
.val = .{ .simple = .bool_false },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
defer result2.deinit();
|
||||||
|
try std.testing.expectEqual(Key{ .int_type = .{ .signedness = .unsigned, .bits = 69 } }, result2.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper functions
|
||||||
|
//
|
||||||
|
|
||||||
|
const CallResult = struct {
|
||||||
|
interpreter: ComptimeInterpreter,
|
||||||
|
key: Key,
|
||||||
|
|
||||||
|
pub fn deinit(self: *CallResult) void {
|
||||||
|
self.interpreter.deinit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Value = struct {
|
||||||
|
ty: Key,
|
||||||
|
val: Key,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn testCall(source: []const u8, arguments: []const Value) !CallResult {
|
||||||
|
var config = zls.Config{};
|
||||||
|
var doc_store = zls.DocumentStore{
|
||||||
|
.allocator = allocator,
|
||||||
|
.config = &config,
|
||||||
|
};
|
||||||
|
defer doc_store.deinit();
|
||||||
|
|
||||||
|
const test_uri: []const u8 = switch (builtin.os.tag) {
|
||||||
|
.windows => "file:///C:\\test.zig",
|
||||||
|
else => "file:///test.zig",
|
||||||
|
};
|
||||||
|
|
||||||
|
const handle = try doc_store.openDocument(test_uri, source);
|
||||||
|
|
||||||
var interpreter = ComptimeInterpreter{
|
var interpreter = ComptimeInterpreter{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.arena = std.heap.ArenaAllocator.init(allocator),
|
.arena = std.heap.ArenaAllocator.init(allocator),
|
||||||
.document_store = &doc_store,
|
.document_store = &doc_store,
|
||||||
.uri = "file:///file.zig",
|
.uri = handle.uri,
|
||||||
};
|
};
|
||||||
defer interpreter.deinit();
|
errdefer interpreter.deinit();
|
||||||
|
|
||||||
_ = try interpreter.interpret(0, 0, .{});
|
_ = try interpreter.interpret(0, .none, .{});
|
||||||
|
|
||||||
const function_node: Ast.Node.Index = 3;
|
var args = try allocator.alloc(ComptimeInterpreter.Value, arguments.len);
|
||||||
|
defer allocator.free(args);
|
||||||
|
|
||||||
const call_result = try interpreter.call(0, function_node, &.{}, .{});
|
for (arguments) |argument, i| {
|
||||||
|
args[i] = .{
|
||||||
|
.interpreter = &interpreter,
|
||||||
|
.node_idx = 0,
|
||||||
|
.ty = try interpreter.ip.get(interpreter.allocator, argument.ty),
|
||||||
|
.val = try interpreter.ip.get(interpreter.allocator, argument.val),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const result_struct = interpreter.ip.indexToKey(call_result.result.value.val).struct_type;
|
const func_node = for (handle.tree.nodes.items(.tag)) |tag, i| {
|
||||||
|
if (tag == .fn_decl) break @intCast(Ast.Node.Index, i);
|
||||||
|
} else unreachable;
|
||||||
|
|
||||||
try std.testing.expectEqual(@intCast(usize, 1), result_struct.fields.len);
|
const call_result = try interpreter.call(.none, func_node, args, .{});
|
||||||
try std.testing.expectEqualStrings("slay", result_struct.fields[0].name);
|
|
||||||
try std.testing.expectFmt("bool", "{}", .{result_struct.fields[0].ty.fmtType(&interpreter.ip)});
|
try std.testing.expectEqual(Key{ .simple = .type }, interpreter.ip.indexToKey(call_result.result.value.ty));
|
||||||
|
|
||||||
|
return CallResult{
|
||||||
|
.interpreter = interpreter,
|
||||||
|
.key = interpreter.ip.indexToKey(call_result.result.value.val),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testCallCheck(
|
||||||
|
source: []const u8,
|
||||||
|
arguments: []const Value,
|
||||||
|
expected: Key,
|
||||||
|
) !void {
|
||||||
|
var result = try testCall(source, arguments);
|
||||||
|
defer result.deinit();
|
||||||
|
try std.testing.expectEqual(expected, result.key);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user