Hacky mess but it works (only if your function is the first root decl tho :P)
This commit is contained in:
parent
06e8756849
commit
779c3c0710
@ -180,6 +180,9 @@ pub const ValueData = union(enum) {
|
|||||||
signed_int: i64,
|
signed_int: i64,
|
||||||
float: f64,
|
float: f64,
|
||||||
|
|
||||||
|
runtime,
|
||||||
|
comptime_undetermined,
|
||||||
|
|
||||||
pub fn eql(data: ValueData, other_data: ValueData) bool {
|
pub fn eql(data: ValueData, other_data: ValueData) bool {
|
||||||
if (std.meta.activeTag(data) != std.meta.activeTag(other_data)) return false;
|
if (std.meta.activeTag(data) != std.meta.activeTag(other_data)) return false;
|
||||||
// std.enums.
|
// std.enums.
|
||||||
@ -190,7 +193,8 @@ pub const ValueData = union(enum) {
|
|||||||
.unsigned_int => return data.unsigned_int == other_data.unsigned_int,
|
.unsigned_int => return data.unsigned_int == other_data.unsigned_int,
|
||||||
.signed_int => return data.signed_int == other_data.signed_int,
|
.signed_int => return data.signed_int == other_data.signed_int,
|
||||||
.float => return data.float == other_data.float,
|
.float => return data.float == other_data.float,
|
||||||
else => @panic("Simple eql not implemented!"),
|
|
||||||
|
else => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -395,6 +399,7 @@ pub const InterpretResult = union(enum) {
|
|||||||
return switch (result) {
|
return switch (result) {
|
||||||
.break_with_value => |v| v.value,
|
.break_with_value => |v| v.value,
|
||||||
.value => |v| v,
|
.value => |v| v,
|
||||||
|
.return_with_value => |v| v,
|
||||||
else => null,
|
else => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -414,6 +419,7 @@ pub const InterpretError = std.mem.Allocator.Error || std.fmt.ParseIntError || s
|
|||||||
InvalidOperation,
|
InvalidOperation,
|
||||||
CriticalAstFailure,
|
CriticalAstFailure,
|
||||||
InvalidBuiltin,
|
InvalidBuiltin,
|
||||||
|
IdentifierNotFound,
|
||||||
};
|
};
|
||||||
pub fn interpret(
|
pub fn interpret(
|
||||||
interpreter: *ComptimeInterpreter,
|
interpreter: *ComptimeInterpreter,
|
||||||
@ -623,7 +629,7 @@ pub fn interpret(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std.log.err("Identifier not found: {s}", .{value});
|
std.log.err("Identifier not found: {s}", .{value});
|
||||||
@panic("Could not find identifier");
|
return error.IdentifierNotFound;
|
||||||
},
|
},
|
||||||
.grouped_expression => {
|
.grouped_expression => {
|
||||||
return try interpreter.interpret(data[node_idx].lhs, scope, options);
|
return try interpreter.interpret(data[node_idx].lhs, scope, options);
|
||||||
@ -733,34 +739,17 @@ pub fn interpret(
|
|||||||
=> {
|
=> {
|
||||||
var buffer: [2]Ast.Node.Index = undefined;
|
var buffer: [2]Ast.Node.Index = undefined;
|
||||||
const params = ast.builtinCallParams(tree, node_idx, &buffer).?;
|
const params = ast.builtinCallParams(tree, node_idx, &buffer).?;
|
||||||
|
_ = params;
|
||||||
const call_name = tree.tokenSlice(main_tokens[node_idx]);
|
const call_name = tree.tokenSlice(main_tokens[node_idx]);
|
||||||
|
|
||||||
if (std.mem.eql(u8, call_name, "@compileLog")) {
|
if (std.mem.eql(u8, call_name, "@compileLog")) {
|
||||||
pp: for (params) |param| {
|
|
||||||
const res = try (try interpreter.interpret(param, scope, .{})).getValue();
|
|
||||||
const ti = interpreter.type_info.items[res.@"type".info_idx];
|
|
||||||
switch (ti) {
|
|
||||||
.pointer => |ptr| {
|
|
||||||
const child = interpreter.type_info.items[ptr.child.info_idx];
|
|
||||||
if (ptr.size == .slice and child == .int and child.int.bits == 8 and child.int.signedness == .unsigned) {
|
|
||||||
|
|
||||||
// TODO: Fix once I optimize slices
|
|
||||||
std.debug.print("@compileLog output: ", .{});
|
|
||||||
for (res.value_data.slice_ptr.items) |i| std.debug.print("{c}", .{@truncate(u8, i.unsigned_int)});
|
|
||||||
std.debug.print("\n", .{});
|
|
||||||
|
|
||||||
break :pp;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
@panic("compileLog argument type not printable!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = .{} };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, call_name, "@compileError")) {
|
||||||
|
return InterpretResult{ .@"return" = .{} };
|
||||||
|
}
|
||||||
|
|
||||||
std.log.info("Builtin not implemented: {s}", .{call_name});
|
std.log.info("Builtin not implemented: {s}", .{call_name});
|
||||||
@panic("Builtin not implemented");
|
@panic("Builtin not implemented");
|
||||||
// return error.InvalidBuiltin;
|
// return error.InvalidBuiltin;
|
||||||
@ -844,12 +833,13 @@ pub fn interpret(
|
|||||||
// .value_data = .{ .@"fn" = .{} },
|
// .value_data = .{ .@"fn" = .{} },
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// const name = ast.getDeclName(tree, node_idx).?;
|
// const name = analysis.getDeclName(tree, node_idx).?;
|
||||||
|
// // TODO: DANGER DANGER DANGER
|
||||||
// try scope.?.declarations.put(interpreter.allocator, name, .{
|
// try scope.?.declarations.put(interpreter.allocator, name, .{
|
||||||
// .node_idx = node_idx,
|
// .node_idx = node_idx,
|
||||||
// .name = name,
|
// .name = name,
|
||||||
// .@"type" = value.@"type",
|
// .@"type" = undefined,
|
||||||
// .@"value" = value,
|
// .@"value" = undefined,
|
||||||
// });
|
// });
|
||||||
|
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = .{} };
|
||||||
@ -863,60 +853,28 @@ pub fn interpret(
|
|||||||
.async_call_one,
|
.async_call_one,
|
||||||
.async_call_one_comma,
|
.async_call_one_comma,
|
||||||
=> {
|
=> {
|
||||||
// var params: [1]Ast.Node.Index = undefined;
|
var params: [1]Ast.Node.Index = undefined;
|
||||||
// const call = ast.callFull(tree, node_idx, ¶ms) orelse unreachable;
|
const call_full = ast.callFull(tree, node_idx, ¶ms) orelse unreachable;
|
||||||
|
|
||||||
// const callee = .{ .node = call.ast.fn_expr, .handle = handle };
|
var args = try std.ArrayListUnmanaged(Value).initCapacity(interpreter.allocator, call_full.ast.params.len);
|
||||||
// const decl = (try resolveTypeOfNodeInternal(store, arena, callee, bound_type_params)) orelse
|
defer args.deinit(interpreter.allocator);
|
||||||
// return null;
|
|
||||||
|
|
||||||
// if (decl.type.is_type_val) return null;
|
for (call_full.ast.params) |param| {
|
||||||
// const decl_node = switch (decl.type.data) {
|
try args.append(interpreter.allocator, try (try interpreter.interpret(param, scope, .{})).getValue());
|
||||||
// .other => |n| n,
|
}
|
||||||
// else => return null,
|
|
||||||
// };
|
|
||||||
// var buf: [1]Ast.Node.Index = undefined;
|
|
||||||
// const func_maybe = ast.fnProto(decl.handle.tree, decl_node, &buf);
|
|
||||||
|
|
||||||
// if (func_maybe) |fn_decl| {
|
// TODO: Make this actually resolve function; requires interpreting whole file
|
||||||
// var expected_params = fn_decl.ast.params.len;
|
// const res = try interpreter.interpret(call_full.ast.fn_expr, scope, .{});
|
||||||
// // If we call as method, the first parameter should be skipped
|
// const value = try res.getValue();
|
||||||
// // TODO: Back-parse to extract the self argument?
|
|
||||||
// var it = fn_decl.iterate(&decl.handle.tree);
|
|
||||||
// if (token_tags[call.ast.lparen - 2] == .period) {
|
|
||||||
// if (try hasSelfParam(arena, store, decl.handle, fn_decl)) {
|
|
||||||
// _ = ast.nextFnParam(&it);
|
|
||||||
// expected_params -= 1;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Bind type params to the arguments passed in the call.
|
const call_res = try interpreter.call(tree.rootDecls()[0], args.items, options);
|
||||||
// const param_len = std.math.min(call.ast.params.len, expected_params);
|
// defer call_res.scope.deinit();
|
||||||
// var i: usize = 0;
|
// TODO: Figure out call result memory model
|
||||||
// while (ast.nextFnParam(&it)) |decl_param| : (i += 1) {
|
|
||||||
// if (i >= param_len) break;
|
|
||||||
// if (!isMetaType(decl.handle.tree, decl_param.type_expr))
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
// const argument = .{ .node = call.ast.params[i], .handle = handle };
|
return switch (call_res.result) {
|
||||||
// const argument_type = (try resolveTypeOfNodeInternal(
|
.value => |v| .{ .value = v },
|
||||||
// store,
|
.nothing => .{ .nothing = {} },
|
||||||
// arena,
|
};
|
||||||
// argument,
|
|
||||||
// bound_type_params,
|
|
||||||
// )) orelse
|
|
||||||
// continue;
|
|
||||||
// if (!argument_type.type.is_type_val) continue;
|
|
||||||
|
|
||||||
// try bound_type_params.put(arena.allocator(), decl_param, argument_type);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const has_body = decl.handle.tree.nodes.items(.tag)[decl_node] == .fn_decl;
|
|
||||||
// const body = decl.handle.tree.nodes.items(.data)[decl_node].rhs;
|
|
||||||
// return try resolveReturnType(store, arena, fn_decl, decl.handle, bound_type_params, if (has_body) body else null);
|
|
||||||
// }
|
|
||||||
// return null;
|
|
||||||
return InterpretResult{ .nothing = .{} };
|
|
||||||
},
|
},
|
||||||
.bool_not => {
|
.bool_not => {
|
||||||
const result = try interpreter.interpret(data[node_idx].lhs, scope, .{});
|
const result = try interpreter.interpret(data[node_idx].lhs, scope, .{});
|
||||||
@ -955,16 +913,33 @@ pub fn call(
|
|||||||
|
|
||||||
// TODO: Arguments
|
// TODO: Arguments
|
||||||
_ = options;
|
_ = options;
|
||||||
_ = arguments;
|
// _ = arguments;
|
||||||
|
|
||||||
const tree = interpreter.tree;
|
const tree = interpreter.tree;
|
||||||
const tags = tree.nodes.items(.tag);
|
const tags = tree.nodes.items(.tag);
|
||||||
|
|
||||||
std.debug.assert(tags[func_node_idx] == .fn_decl);
|
std.debug.assert(tags[func_node_idx] == .fn_decl);
|
||||||
|
|
||||||
// TODO: Parent sc]ope exploration (consts, typefuncs, etc.)
|
|
||||||
var fn_scope = try interpreter.newScope(null, func_node_idx);
|
var fn_scope = try interpreter.newScope(null, func_node_idx);
|
||||||
|
|
||||||
|
var buf: [1]Ast.Node.Index = undefined;
|
||||||
|
var proto = ast.fnProto(tree, func_node_idx, &buf).?;
|
||||||
|
|
||||||
|
var arg_it = proto.iterate(&tree);
|
||||||
|
var arg_index: usize = 0;
|
||||||
|
while (ast.nextFnParam(&arg_it)) |param| {
|
||||||
|
if (param.name_token) |nt| {
|
||||||
|
const decl = Declaration{
|
||||||
|
.node_idx = param.type_expr,
|
||||||
|
.name = tree.tokenSlice(nt),
|
||||||
|
.@"type" = arguments[arg_index].@"type",
|
||||||
|
.value = arguments[arg_index],
|
||||||
|
};
|
||||||
|
try fn_scope.declarations.put(interpreter.allocator, tree.tokenSlice(nt), decl);
|
||||||
|
arg_index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const body = tree.nodes.items(.data)[func_node_idx].rhs;
|
const body = tree.nodes.items(.data)[func_node_idx].rhs;
|
||||||
const result = try interpreter.interpret(body, fn_scope, .{});
|
const result = try interpreter.interpret(body, fn_scope, .{});
|
||||||
|
|
||||||
|
@ -484,6 +484,23 @@ fn typeToCompletion(
|
|||||||
null,
|
null,
|
||||||
),
|
),
|
||||||
.primitive, .array_index => {},
|
.primitive, .array_index => {},
|
||||||
|
.@"comptime" => |co| {
|
||||||
|
const ti = co.interpreter.typeToTypeInfo(co.type);
|
||||||
|
switch (ti) {
|
||||||
|
.@"struct" => |st| {
|
||||||
|
var it = st.scope.declarations.iterator();
|
||||||
|
while (it.next()) |entry| {
|
||||||
|
try list.append(allocator, .{
|
||||||
|
.label = entry.key_ptr.*,
|
||||||
|
.kind = if (entry.value_ptr.isConstant(co.interpreter.tree)) .Constant else .Variable,
|
||||||
|
.insertText = entry.key_ptr.*,
|
||||||
|
.insertTextFormat = .PlainText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2663,8 +2680,7 @@ pub fn processJsonRpc(server: *Server, writer: anytype, json: []const u8) !void
|
|||||||
if (s.len == 0) {
|
if (s.len == 0) {
|
||||||
if (field.field_type == ?[]const u8) {
|
if (field.field_type == ?[]const u8) {
|
||||||
break :blk null;
|
break :blk null;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
break :blk s;
|
break :blk s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2727,35 +2743,7 @@ pub fn processJsonRpc(server: *Server, writer: anytype, json: []const u8) !void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const method_map = .{
|
const method_map = .{ .{ "initialized", void, initializedHandler }, .{"$/cancelRequest"}, .{"textDocument/willSave"}, .{ "initialize", requests.Initialize, initializeHandler }, .{ "shutdown", void, shutdownHandler }, .{ "exit", void, exitHandler }, .{ "textDocument/didOpen", requests.OpenDocument, openDocumentHandler }, .{ "textDocument/didChange", requests.ChangeDocument, changeDocumentHandler }, .{ "textDocument/didSave", requests.SaveDocument, saveDocumentHandler }, .{ "textDocument/didClose", requests.CloseDocument, closeDocumentHandler }, .{ "textDocument/semanticTokens/full", requests.SemanticTokensFull, semanticTokensFullHandler }, .{ "textDocument/inlayHint", requests.InlayHint, inlayHintHandler }, .{ "textDocument/completion", requests.Completion, completionHandler }, .{ "textDocument/signatureHelp", requests.SignatureHelp, signatureHelpHandler }, .{ "textDocument/definition", requests.GotoDefinition, gotoDefinitionHandler }, .{ "textDocument/typeDefinition", requests.GotoDefinition, gotoDefinitionHandler }, .{ "textDocument/implementation", requests.GotoDefinition, gotoDefinitionHandler }, .{ "textDocument/declaration", requests.GotoDeclaration, gotoDeclarationHandler }, .{ "textDocument/hover", requests.Hover, hoverHandler }, .{ "textDocument/documentSymbol", requests.DocumentSymbols, documentSymbolsHandler }, .{ "textDocument/formatting", requests.Formatting, formattingHandler }, .{ "textDocument/rename", requests.Rename, renameHandler }, .{ "textDocument/references", requests.References, referencesHandler }, .{ "textDocument/documentHighlight", requests.DocumentHighlight, documentHighlightHandler }, .{ "textDocument/codeAction", requests.CodeAction, codeActionHandler }, .{ "workspace/didChangeConfiguration", Config.DidChangeConfigurationParams, didChangeConfigurationHandler }, .{ "textDocument/foldingRange", requests.FoldingRange, foldingRangeHandler } };
|
||||||
.{ "initialized", void, initializedHandler },
|
|
||||||
.{"$/cancelRequest"},
|
|
||||||
.{"textDocument/willSave"},
|
|
||||||
.{ "initialize", requests.Initialize, initializeHandler },
|
|
||||||
.{ "shutdown", void, shutdownHandler },
|
|
||||||
.{ "exit", void, exitHandler },
|
|
||||||
.{ "textDocument/didOpen", requests.OpenDocument, openDocumentHandler },
|
|
||||||
.{ "textDocument/didChange", requests.ChangeDocument, changeDocumentHandler },
|
|
||||||
.{ "textDocument/didSave", requests.SaveDocument, saveDocumentHandler },
|
|
||||||
.{ "textDocument/didClose", requests.CloseDocument, closeDocumentHandler },
|
|
||||||
.{ "textDocument/semanticTokens/full", requests.SemanticTokensFull, semanticTokensFullHandler },
|
|
||||||
.{ "textDocument/inlayHint", requests.InlayHint, inlayHintHandler },
|
|
||||||
.{ "textDocument/completion", requests.Completion, completionHandler },
|
|
||||||
.{ "textDocument/signatureHelp", requests.SignatureHelp, signatureHelpHandler },
|
|
||||||
.{ "textDocument/definition", requests.GotoDefinition, gotoDefinitionHandler },
|
|
||||||
.{ "textDocument/typeDefinition", requests.GotoDefinition, gotoDefinitionHandler },
|
|
||||||
.{ "textDocument/implementation", requests.GotoDefinition, gotoDefinitionHandler },
|
|
||||||
.{ "textDocument/declaration", requests.GotoDeclaration, gotoDeclarationHandler },
|
|
||||||
.{ "textDocument/hover", requests.Hover, hoverHandler },
|
|
||||||
.{ "textDocument/documentSymbol", requests.DocumentSymbols, documentSymbolsHandler },
|
|
||||||
.{ "textDocument/formatting", requests.Formatting, formattingHandler },
|
|
||||||
.{ "textDocument/rename", requests.Rename, renameHandler },
|
|
||||||
.{ "textDocument/references", requests.References, referencesHandler },
|
|
||||||
.{ "textDocument/documentHighlight", requests.DocumentHighlight, documentHighlightHandler },
|
|
||||||
.{ "textDocument/codeAction", requests.CodeAction, codeActionHandler },
|
|
||||||
.{ "workspace/didChangeConfiguration", Config.DidChangeConfigurationParams, didChangeConfigurationHandler },
|
|
||||||
.{ "textDocument/foldingRange", requests.FoldingRange, foldingRangeHandler },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (zig_builtin.zig_backend == .stage1) {
|
if (zig_builtin.zig_backend == .stage1) {
|
||||||
// Hack to avoid `return`ing in the inline for, which causes bugs.
|
// Hack to avoid `return`ing in the inline for, which causes bugs.
|
||||||
|
@ -5,6 +5,7 @@ const types = @import("types.zig");
|
|||||||
const offsets = @import("offsets.zig");
|
const offsets = @import("offsets.zig");
|
||||||
const log = std.log.scoped(.analysis);
|
const log = std.log.scoped(.analysis);
|
||||||
const ast = @import("ast.zig");
|
const ast = @import("ast.zig");
|
||||||
|
const ComptimeInterpreter = @import("ComptimeInterpreter.zig");
|
||||||
|
|
||||||
var using_trail: std.ArrayList([*]const u8) = undefined;
|
var using_trail: std.ArrayList([*]const u8) = undefined;
|
||||||
var resolve_trail: std.ArrayList(NodeWithHandle) = undefined;
|
var resolve_trail: std.ArrayList(NodeWithHandle) = undefined;
|
||||||
@ -491,7 +492,7 @@ fn resolveUnwrapErrorType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
.type = .{ .data = .{ .other = n }, .is_type_val = rhs.type.is_type_val },
|
.type = .{ .data = .{ .other = n }, .is_type_val = rhs.type.is_type_val },
|
||||||
.handle = rhs.handle,
|
.handle = rhs.handle,
|
||||||
},
|
},
|
||||||
.primitive, .slice, .pointer, .array_index => return null,
|
.primitive, .slice, .pointer, .array_index, .@"comptime" => return null,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (rhs.handle.tree.nodes.items(.tag)[rhs_node] == .error_union) {
|
if (rhs.handle.tree.nodes.items(.tag)[rhs_node] == .error_union) {
|
||||||
@ -742,7 +743,37 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
|
|
||||||
const has_body = decl.handle.tree.nodes.items(.tag)[decl_node] == .fn_decl;
|
const has_body = decl.handle.tree.nodes.items(.tag)[decl_node] == .fn_decl;
|
||||||
const body = decl.handle.tree.nodes.items(.data)[decl_node].rhs;
|
const body = decl.handle.tree.nodes.items(.data)[decl_node].rhs;
|
||||||
return try resolveReturnType(store, arena, fn_decl, decl.handle, bound_type_params, if (has_body) body else null);
|
if (try resolveReturnType(store, arena, fn_decl, decl.handle, bound_type_params, if (has_body) body else null)) |ret| {
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
// TODO: Better case-by-case; we just use the ComptimeInterpreter when all else fails,
|
||||||
|
// probably better to use it more liberally
|
||||||
|
// TODO: Handle non-isolate args; e.g. `const T = u8; TypeFunc(T);`
|
||||||
|
var interpreter = ComptimeInterpreter{ .tree = tree, .allocator = arena.allocator() };
|
||||||
|
|
||||||
|
const result = interpreter.interpret(node, null, .{}) catch |err| {
|
||||||
|
std.log.err("Interpreter error: {s}", .{@errorName(err)});
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
const val = result.getValue() catch |err| {
|
||||||
|
std.log.err("Interpreter error: {s}", .{@errorName(err)});
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ti = interpreter.typeToTypeInfo(val.@"type");
|
||||||
|
if (ti != .@"type") {
|
||||||
|
std.log.err("Not a type: { }", .{interpreter.formatTypeInfo(ti)});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypeWithHandle{
|
||||||
|
.type = .{
|
||||||
|
.data = .{ .@"comptime" = .{ .interpreter = interpreter, .type = val.value_data.@"type" } },
|
||||||
|
.is_type_val = true,
|
||||||
|
},
|
||||||
|
.handle = node_handle.handle,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@ -965,6 +996,10 @@ pub const Type = struct {
|
|||||||
other: Ast.Node.Index,
|
other: Ast.Node.Index,
|
||||||
primitive: Ast.Node.Index,
|
primitive: Ast.Node.Index,
|
||||||
array_index,
|
array_index,
|
||||||
|
@"comptime": struct {
|
||||||
|
interpreter: ComptimeInterpreter,
|
||||||
|
type: ComptimeInterpreter.Type,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
/// If true, the type `type`, the attached data is the value of the type value.
|
/// If true, the type `type`, the attached data is the value of the type value.
|
||||||
is_type_val: bool,
|
is_type_val: bool,
|
||||||
|
@ -9,8 +9,8 @@ const allocator: std.mem.Allocator = std.testing.allocator;
|
|||||||
|
|
||||||
test "ComptimeInterpreter - basic test" {
|
test "ComptimeInterpreter - basic test" {
|
||||||
var tree = try std.zig.parse(allocator,
|
var tree = try std.zig.parse(allocator,
|
||||||
\\pub fn ReturnMyType() type {
|
\\pub fn ReturnMyType(comptime my_arg: bool) type {
|
||||||
\\ var abc = z: {break :z if (!false) 123 else 0;};
|
\\ var abc = z: {break :z if (!my_arg) 123 else 0;};
|
||||||
\\ if (abc == 123) return u69;
|
\\ if (abc == 123) return u69;
|
||||||
\\ return u8;
|
\\ return u8;
|
||||||
\\}
|
\\}
|
||||||
@ -20,10 +20,29 @@ test "ComptimeInterpreter - basic test" {
|
|||||||
var interpreter = ComptimeInterpreter{ .tree = tree, .allocator = allocator };
|
var interpreter = ComptimeInterpreter{ .tree = tree, .allocator = allocator };
|
||||||
defer interpreter.deinit();
|
defer interpreter.deinit();
|
||||||
|
|
||||||
const z = try interpreter.call(tree.rootDecls()[0], &.{}, .{});
|
var bool_type = try interpreter.createType(std.math.maxInt(std.zig.Ast.Node.Index), .{ .@"bool" = .{} });
|
||||||
defer z.scope.deinit();
|
var arg_false = ComptimeInterpreter.Value{
|
||||||
|
.node_idx = std.math.maxInt(std.zig.Ast.Node.Index),
|
||||||
|
.@"type" = bool_type,
|
||||||
|
.value_data = .{ .@"bool" = false },
|
||||||
|
};
|
||||||
|
var arg_true = ComptimeInterpreter.Value{
|
||||||
|
.node_idx = std.math.maxInt(std.zig.Ast.Node.Index),
|
||||||
|
.@"type" = bool_type,
|
||||||
|
.value_data = .{ .@"bool" = true },
|
||||||
|
};
|
||||||
|
|
||||||
try std.testing.expectFmt("u69", "{any}", .{interpreter.formatTypeInfo(interpreter.typeToTypeInfo(z.result.value.value_data.@"type"))});
|
const call_with_false = try interpreter.call(tree.rootDecls()[0], &.{
|
||||||
|
arg_false,
|
||||||
|
}, .{});
|
||||||
|
defer call_with_false.scope.deinit();
|
||||||
|
const call_with_true = try interpreter.call(tree.rootDecls()[0], &.{
|
||||||
|
arg_true,
|
||||||
|
}, .{});
|
||||||
|
defer call_with_true.scope.deinit();
|
||||||
|
|
||||||
|
try std.testing.expectFmt("u69", "{any}", .{interpreter.formatTypeInfo(interpreter.typeToTypeInfo(call_with_false.result.value.value_data.@"type"))});
|
||||||
|
try std.testing.expectFmt("u8", "{any}", .{interpreter.formatTypeInfo(interpreter.typeToTypeInfo(call_with_true.result.value.value_data.@"type"))});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ComptimeInterpreter - struct" {
|
test "ComptimeInterpreter - struct" {
|
||||||
|
Loading…
Reference in New Issue
Block a user