add predefined values to Index
This commit is contained in:
		
							parent
							
								
									6278880f42
								
							
						
					
					
						commit
						57fc10eec0
					
				| @ -20,7 +20,7 @@ pub const ComptimeInterpreter = @This(); | ||||
| const log = std.log.scoped(.comptime_interpreter); | ||||
| 
 | ||||
| allocator: std.mem.Allocator, | ||||
| ip: InternPool = .{}, | ||||
| ip: InternPool, | ||||
| document_store: *DocumentStore, | ||||
| uri: DocumentStore.Uri, | ||||
| namespaces: std.MultiArrayList(Namespace) = .{}, | ||||
| @ -209,8 +209,6 @@ pub fn interpret( | ||||
|         // .tagged_union_enum_tag_trailing, | ||||
|         .root, | ||||
|         => { | ||||
|             const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }); | ||||
| 
 | ||||
|             try interpreter.namespaces.append(interpreter.allocator, .{ | ||||
|                 .parent = namespace, | ||||
|                 .node_idx = node_idx, | ||||
| @ -243,7 +241,7 @@ pub fn interpret( | ||||
|                 else | ||||
|                     (try (try interpreter.interpret(container_field.ast.value_expr, container_namespace, .{})).getValue()).val; // TODO check ty | ||||
| 
 | ||||
|                 if (init_type_value.ty != type_type) { | ||||
|                 if (init_type_value.ty != Index.type) { | ||||
|                     try interpreter.recordError( | ||||
|                         container_field.ast.type_expr, | ||||
|                         "expected_type", | ||||
| @ -269,7 +267,7 @@ pub fn interpret( | ||||
|             return InterpretResult{ .value = Value{ | ||||
|                 .interpreter = interpreter, | ||||
|                 .node_idx = node_idx, | ||||
|                 .ty = type_type, | ||||
|                 .ty = Index.type, | ||||
|                 .val = struct_type, | ||||
|             } }; | ||||
|         }, | ||||
| @ -316,8 +314,7 @@ pub fn interpret( | ||||
|             if (type_value == null and init_value == null) return InterpretResult{ .nothing = {} }; | ||||
| 
 | ||||
|             if (type_value) |v| { | ||||
|                 const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }); | ||||
|                 if (v.ty != type_type) return InterpretResult{ .nothing = {} }; | ||||
|                 if (v.ty != Index.type) return InterpretResult{ .nothing = {} }; | ||||
|             } | ||||
| 
 | ||||
|             const decl = interpreter.ip.getDecl(decl_index); | ||||
| @ -385,44 +382,53 @@ pub fn interpret( | ||||
|         .identifier => { | ||||
|             const identifier = offsets.nodeToSlice(tree, node_idx); | ||||
| 
 | ||||
|             const simples = std.ComptimeStringMap(InternPool.Simple, .{ | ||||
|                 .{ "anyerror", .anyerror }, | ||||
|                 .{ "anyframe", .@"anyframe" }, | ||||
|                 .{ "anyopaque", .anyopaque }, | ||||
|                 .{ "bool", .bool }, | ||||
|                 .{ "c_int", .c_int }, | ||||
|                 .{ "c_long", .c_long }, | ||||
|                 .{ "c_longdouble", .c_longdouble }, | ||||
|                 .{ "c_longlong", .c_longlong }, | ||||
|                 .{ "c_short", .c_short }, | ||||
|                 .{ "c_uint", .c_uint }, | ||||
|                 .{ "c_ulong", .c_ulong }, | ||||
|                 .{ "c_ulonglong", .c_ulonglong }, | ||||
|                 .{ "c_ushort", .c_ushort }, | ||||
|                 .{ "comptime_float", .comptime_float }, | ||||
|                 .{ "comptime_int", .comptime_int }, | ||||
|                 .{ "f128", .f128 }, | ||||
|                 .{ "f16", .f16 }, | ||||
|                 .{ "f32", .f32 }, | ||||
|                 .{ "f64", .f64 }, | ||||
|                 .{ "f80", .f80 }, | ||||
|                 .{ "false", .bool_false }, | ||||
|                 .{ "isize", .isize }, | ||||
|                 .{ "noreturn", .noreturn }, | ||||
|                 .{ "null", .null_value }, | ||||
|                 .{ "true", .bool_true }, | ||||
|                 .{ "type", .type }, | ||||
|                 .{ "undefined", .undefined_value }, | ||||
|                 .{ "usize", .usize }, | ||||
|                 .{ "void", .void }, | ||||
|             const simples = std.ComptimeStringMap(Index, .{ | ||||
|                 .{ "anyerror", Index.anyerror }, | ||||
|                 .{ "anyframe", Index.@"anyframe" }, | ||||
|                 .{ "anyopaque", Index.anyopaque }, | ||||
|                 .{ "bool", Index.bool }, | ||||
|                 .{ "c_int", Index.c_int }, | ||||
|                 .{ "c_long", Index.c_long }, | ||||
|                 .{ "c_longdouble", Index.c_longdouble }, | ||||
|                 .{ "c_longlong", Index.c_longlong }, | ||||
|                 .{ "c_short", Index.c_short }, | ||||
|                 .{ "c_uint", Index.c_uint }, | ||||
|                 .{ "c_ulong", Index.c_ulong }, | ||||
|                 .{ "c_ulonglong", Index.c_ulonglong }, | ||||
|                 .{ "c_ushort", Index.c_ushort }, | ||||
|                 .{ "comptime_float", Index.comptime_float }, | ||||
|                 .{ "comptime_int", Index.comptime_int }, | ||||
|                 .{ "f128", Index.f128 }, | ||||
|                 .{ "f16", Index.f16 }, | ||||
|                 .{ "f32", Index.f32 }, | ||||
|                 .{ "f64", Index.f64 }, | ||||
|                 .{ "f80", Index.f80 }, | ||||
|                 .{ "false", Index.bool_false }, | ||||
|                 .{ "isize", Index.isize }, | ||||
|                 .{ "noreturn", Index.noreturn }, | ||||
|                 .{ "null", Index.null_value }, | ||||
|                 .{ "true", Index.bool_true }, | ||||
|                 .{ "type", Index.type }, | ||||
|                 .{ "undefined", Index.undefined_value }, | ||||
|                 .{ "usize", Index.usize }, | ||||
|                 .{ "void", Index.void }, | ||||
|             }); | ||||
| 
 | ||||
|             if (simples.get(identifier)) |simple| { | ||||
|             if (simples.get(identifier)) |index| { | ||||
|                 const ty: Index = switch (index) { | ||||
|                     .undefined_value => .undefined_type, | ||||
|                     .void_value => .void, | ||||
|                     .unreachable_value => .noreturn, | ||||
|                     .null_value => .null_type, | ||||
|                     .bool_true => .bool, | ||||
|                     .bool_false => .bool, | ||||
|                     else => .type, | ||||
|                 }; | ||||
|                 return InterpretResult{ .value = Value{ | ||||
|                     .interpreter = interpreter, | ||||
|                     .node_idx = node_idx, | ||||
|                     .ty = try interpreter.ip.get(interpreter.allocator, Key{ .simple = simple.toType() }), | ||||
|                     .val = try interpreter.ip.get(interpreter.allocator, Key{ .simple = simple }), | ||||
|                     .ty = ty, | ||||
|                     .val = index, | ||||
|                 } }; | ||||
|             } | ||||
| 
 | ||||
| @ -430,7 +436,7 @@ pub fn interpret( | ||||
|                 return InterpretResult{ .value = Value{ | ||||
|                     .interpreter = interpreter, | ||||
|                     .node_idx = node_idx, | ||||
|                     .ty = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }), | ||||
|                     .ty = Index.type, | ||||
|                     .val = try interpreter.ip.get(interpreter.allocator, Key{ .int_type = .{ | ||||
|                         .signedness = if (identifier[0] == 'u') .unsigned else .signed, | ||||
|                         .bits = std.fmt.parseInt(u16, identifier[1..], 10) catch break :blk, | ||||
| @ -456,7 +462,8 @@ pub fn interpret( | ||||
|                 "use of undeclared identifier '{s}'", | ||||
|                 .{identifier}, | ||||
|             ); | ||||
|             return error.IdentifierNotFound; | ||||
|             // return error.IdentifierNotFound; | ||||
|             return InterpretResult{ .nothing = {} }; | ||||
|         }, | ||||
|         .field_access => { | ||||
|             if (data[node_idx].rhs == 0) return error.CriticalAstFailure; | ||||
| @ -472,7 +479,7 @@ pub fn interpret( | ||||
|             }; | ||||
| 
 | ||||
|             const can_have_fields: bool = switch (inner_lhs) { | ||||
|                 .simple => |simple| switch (simple) { | ||||
|                 .simple_type => |simple| switch (simple) { | ||||
|                     .type => blk: { | ||||
|                         if (irv.val == .none) break :blk true; | ||||
| 
 | ||||
| @ -530,7 +537,7 @@ pub fn interpret( | ||||
|                                 .value = Value{ | ||||
|                                     .interpreter = interpreter, | ||||
|                                     .node_idx = data[node_idx].rhs, | ||||
|                                     .ty = try interpreter.ip.get(interpreter.allocator, .{ .simple = .usize }), | ||||
|                                     .ty = Index.usize, | ||||
|                                     .val = .none, // TODO resolve length of Slice | ||||
|                                 }, | ||||
|                             }; | ||||
| @ -541,7 +548,7 @@ pub fn interpret( | ||||
|                                 .value = Value{ | ||||
|                                     .interpreter = interpreter, | ||||
|                                     .node_idx = data[node_idx].rhs, | ||||
|                                     .ty = try interpreter.ip.get(interpreter.allocator, .{ .simple = .usize }), | ||||
|                                     .ty = Index.usize, | ||||
|                                     .val = .none, // TODO resolve length of Slice | ||||
|                                 }, | ||||
|                             }; | ||||
| @ -556,7 +563,7 @@ pub fn interpret( | ||||
|                         return InterpretResult{ .value = Value{ | ||||
|                             .interpreter = interpreter, | ||||
|                             .node_idx = data[node_idx].rhs, | ||||
|                             .ty = try interpreter.ip.get(interpreter.allocator, .{ .simple = .comptime_int }), | ||||
|                             .ty = Index.comptime_int, | ||||
|                             .val = len_value, | ||||
|                         } }; | ||||
|                     } | ||||
| @ -564,8 +571,7 @@ pub fn interpret( | ||||
|                 }, | ||||
|                 .optional_type => |optional_info| blk: { | ||||
|                     if (!std.mem.eql(u8, field_name, "?")) break :blk false; | ||||
|                     const null_value = try interpreter.ip.get(interpreter.allocator, .{ .simple = .null_value }); | ||||
|                     if (irv.val == null_value) { | ||||
|                     if (irv.val == Index.null_value) { | ||||
|                         try interpreter.recordError( | ||||
|                             node_idx, | ||||
|                             "null_unwrap", | ||||
| @ -613,7 +619,7 @@ pub fn interpret( | ||||
|                 else => false, | ||||
|             }; | ||||
| 
 | ||||
|             const accessed_ty = if (inner_lhs == .simple and inner_lhs.simple == .type) irv.val else irv.ty; | ||||
|             const accessed_ty = if (inner_lhs == .simple_type and inner_lhs.simple_type == .type) irv.val else irv.ty; | ||||
|             if (accessed_ty != .none) { | ||||
|                 if (can_have_fields) { | ||||
|                     try interpreter.recordError( | ||||
| @ -657,12 +663,9 @@ pub fn interpret( | ||||
|             // if (options.observe_values) { | ||||
|             const ir = try interpreter.interpret(if_info.ast.cond_expr, namespace, options); | ||||
| 
 | ||||
|             const false_value = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .bool_false }); | ||||
|             const true_value = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .bool_true }); | ||||
| 
 | ||||
|             const condition = (try ir.getValue()).val; | ||||
|             std.debug.assert(condition == false_value or condition == true_value); | ||||
|             if (condition == true_value) { | ||||
|             std.debug.assert(condition == Index.bool_false or condition == Index.bool_true); | ||||
|             if (condition == Index.bool_true) { | ||||
|                 return try interpreter.interpret(if_info.ast.then_expr, namespace, options); | ||||
|             } else { | ||||
|                 if (if_info.ast.else_expr != 0) { | ||||
| @ -679,8 +682,8 @@ pub fn interpret( | ||||
|                 .value = Value{ | ||||
|                     .interpreter = interpreter, | ||||
|                     .node_idx = node_idx, | ||||
|                     .ty = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .bool }), | ||||
|                     .val = try interpreter.ip.get(interpreter.allocator, Key{ .simple = if (a_value.val == b_value.val) .bool_true else .bool_false }), // TODO eql function required? | ||||
|                     .ty = Index.bool, | ||||
|                     .val = if (a_value.val == b_value.val) Index.bool_true else Index.bool_false, // TODO eql function required? | ||||
|                 }, | ||||
|             }; | ||||
|         }, | ||||
| @ -690,9 +693,7 @@ pub fn interpret( | ||||
| 
 | ||||
|             if (nl == .failure) return error.CriticalAstFailure; | ||||
| 
 | ||||
|             const number_type = try interpreter.ip.get(interpreter.allocator, Key{ | ||||
|                 .simple = if (nl == .float) .comptime_float else .comptime_int, | ||||
|             }); | ||||
|             const number_type = if (nl == .float) Index.comptime_float else Index.comptime_int; | ||||
| 
 | ||||
|             const value = try interpreter.ip.get( | ||||
|                 interpreter.allocator, | ||||
| @ -826,7 +827,7 @@ pub fn interpret( | ||||
|                         .interpreter = interpreter, | ||||
|                         .node_idx = node_idx, | ||||
|                         .ty = try interpreter.ip.get(interpreter.allocator, Key{ .struct_type = struct_index }), | ||||
|                         .val = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .undefined_value }), | ||||
|                         .val = Index.undefined_value, | ||||
|                     } }; | ||||
|                 } | ||||
| 
 | ||||
| @ -834,13 +835,13 @@ pub fn interpret( | ||||
|                 defer interpreter.allocator.free(import_uri); | ||||
| 
 | ||||
|                 var handle = interpreter.document_store.getOrLoadHandle(import_uri) orelse return error.ImportFailure; | ||||
|                 try interpreter.document_store.ensureInterpreterExists(handle.uri); | ||||
|                 _ = try interpreter.document_store.ensureInterpreterExists(handle.uri); | ||||
| 
 | ||||
|                 return InterpretResult{ | ||||
|                     .value = Value{ | ||||
|                         .interpreter = interpreter, | ||||
|                         .node_idx = node_idx, | ||||
|                         .ty = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }), | ||||
|                         .ty = Index.type, | ||||
|                         .val = .none, // TODO | ||||
|                     }, | ||||
|                 }; | ||||
| @ -853,7 +854,7 @@ pub fn interpret( | ||||
|                 return InterpretResult{ .value = Value{ | ||||
|                     .interpreter = interpreter, | ||||
|                     .node_idx = node_idx, | ||||
|                     .ty = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }), | ||||
|                     .ty = Index.type, | ||||
|                     .val = value.ty, | ||||
|                 } }; | ||||
|             } | ||||
| @ -864,9 +865,7 @@ pub fn interpret( | ||||
|                 const value = try (try interpreter.interpret(params[0], namespace, options)).getValue(); | ||||
|                 const field_name = try (try interpreter.interpret(params[1], namespace, options)).getValue(); | ||||
| 
 | ||||
|                 const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }); | ||||
| 
 | ||||
|                 if (value.ty != type_type or value.ty == .none) return error.InvalidBuiltin; | ||||
|                 if (value.ty != Index.type or value.ty == .none) return error.InvalidBuiltin; | ||||
|                 if (interpreter.ip.indexToKey(field_name.ty) != .pointer_type) return error.InvalidBuiltin; // Check if it's a []const u8 | ||||
|                 if (value.val == .none) return error.InvalidBuiltin; | ||||
| 
 | ||||
| @ -881,8 +880,8 @@ pub fn interpret( | ||||
|                 return InterpretResult{ .value = Value{ | ||||
|                     .interpreter = interpreter, | ||||
|                     .node_idx = node_idx, | ||||
|                     .ty = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .bool }), | ||||
|                     .val = try interpreter.ip.get(interpreter.allocator, Key{ .simple = if (has_decl) .bool_true else .bool_false }), | ||||
|                     .ty = Index.bool, | ||||
|                     .val = if (has_decl) Index.bool_true else Index.bool_false, | ||||
|                 } }; | ||||
|             } | ||||
| 
 | ||||
| @ -892,9 +891,7 @@ pub fn interpret( | ||||
|                 const as_type = try (try interpreter.interpret(params[0], namespace, options)).getValue(); | ||||
|                 const value = try (try interpreter.interpret(params[1], namespace, options)).getValue(); | ||||
| 
 | ||||
|                 const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }); | ||||
| 
 | ||||
|                 if (as_type.ty != type_type) return error.InvalidBuiltin; | ||||
|                 if (as_type.ty != Index.type) return error.InvalidBuiltin; | ||||
| 
 | ||||
|                 return InterpretResult{ | ||||
|                     .value = Value{ | ||||
| @ -955,8 +952,6 @@ pub fn interpret( | ||||
| 
 | ||||
|             // TODO: Resolve function type | ||||
| 
 | ||||
|             const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }); | ||||
| 
 | ||||
|             const function_type = try interpreter.ip.get(interpreter.allocator, Key{ .function_type = .{ | ||||
|                 .calling_convention = .Unspecified, | ||||
|                 .alignment = 0, | ||||
| @ -995,7 +990,7 @@ pub fn interpret( | ||||
| 
 | ||||
|                 const decl_index = try interpreter.ip.createDecl(interpreter.allocator, .{ | ||||
|                     .name = name, | ||||
|                     .ty = type_type, | ||||
|                     .ty = Index.type, | ||||
|                     .val = function_type, | ||||
|                     .alignment = 0, // TODO | ||||
|                     .address_space = .generic, // TODO | ||||
| @ -1040,10 +1035,9 @@ pub fn interpret( | ||||
|         }, | ||||
|         .bool_not => { | ||||
|             const result = try interpreter.interpret(data[node_idx].lhs, namespace, .{}); | ||||
|             const bool_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .bool }); | ||||
|             const value = try result.getValue(); | ||||
| 
 | ||||
|             if (value.ty != bool_type) { | ||||
|             if (value.ty != Index.bool) { | ||||
|                 try interpreter.recordError( | ||||
|                     node_idx, | ||||
|                     "invalid_deref", | ||||
| @ -1053,15 +1047,12 @@ pub fn interpret( | ||||
|                 return error.InvalidOperation; | ||||
|             } | ||||
| 
 | ||||
|             const false_value = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .bool_false }); | ||||
|             const true_value = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .bool_true }); | ||||
| 
 | ||||
|             std.debug.assert(value.val == false_value or value.val == true_value); | ||||
|             std.debug.assert(value.val == Index.bool_false or value.val == Index.bool_true); | ||||
|             return InterpretResult{ .value = .{ | ||||
|                 .interpreter = interpreter, | ||||
|                 .node_idx = node_idx, | ||||
|                 .ty = bool_type, | ||||
|                 .val = if (value.val == false_value) true_value else false_value, | ||||
|                 .ty = Index.bool, | ||||
|                 .val = if (value.val == Index.bool_false) Index.bool_true else Index.bool_false, | ||||
|             } }; | ||||
|         }, | ||||
|         .address_of => { | ||||
| @ -1146,14 +1137,12 @@ pub fn call( | ||||
|     }); | ||||
|     const fn_namespace = @intToEnum(Namespace.Index, interpreter.namespaces.len - 1); | ||||
| 
 | ||||
|     const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }); | ||||
| 
 | ||||
|     var arg_it = proto.iterate(&tree); | ||||
|     var arg_index: usize = 0; | ||||
|     while (ast.nextFnParam(&arg_it)) |param| { | ||||
|         if (arg_index >= arguments.len) return error.MissingArguments; | ||||
|         var tex = try (try interpreter.interpret(param.type_expr, fn_namespace, options)).getValue(); | ||||
|         if (tex.ty != type_type) { | ||||
|         if (tex.ty != Index.type) { | ||||
|             try interpreter.recordError( | ||||
|                 param.type_expr, | ||||
|                 "expected_type", | ||||
|  | ||||
| @ -989,16 +989,26 @@ pub fn enumCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle | ||||
|     return try self.tagStoreCompletionItems(arena, handle, "enum_completions"); | ||||
| } | ||||
| 
 | ||||
| pub fn ensureInterpreterExists(self: *DocumentStore, uri: Uri) !void { | ||||
| pub fn ensureInterpreterExists(self: *DocumentStore, uri: Uri) !*ComptimeInterpreter { | ||||
|     var handle = self.handles.get(uri).?; | ||||
|     if (handle.interpreter == null) { | ||||
|         var int = try self.allocator.create(ComptimeInterpreter); | ||||
|         int.* = ComptimeInterpreter{ | ||||
|     if (handle.interpreter != null) return handle.interpreter.?; | ||||
| 
 | ||||
|     { | ||||
|         var interpreter = try self.allocator.create(ComptimeInterpreter); | ||||
|         errdefer self.allocator.destroy(interpreter); | ||||
| 
 | ||||
|         var ip = try ComptimeInterpreter.InternPool.init(self.allocator); | ||||
|         errdefer ip.deinit(self.allocator); | ||||
| 
 | ||||
|         interpreter.* = ComptimeInterpreter{ | ||||
|             .allocator = self.allocator, | ||||
|             .ip = ip, | ||||
|             .document_store = self, | ||||
|             .uri = uri, | ||||
|         }; | ||||
|         handle.interpreter = int; | ||||
|         _ = try int.interpret(0, .none, .{}); | ||||
|         handle.interpreter = interpreter; | ||||
|     } | ||||
| 
 | ||||
|     _ = try handle.interpreter.?.interpret(0, .none, .{}); | ||||
|     return handle.interpreter.?; | ||||
| } | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -21,7 +21,7 @@ pub fn dotCompletions( | ||||
|     }; | ||||
| 
 | ||||
|     switch (inner_key) { | ||||
|         .simple => |simple| switch (simple) { | ||||
|         .simple_type => |simple| switch (simple) { | ||||
|             .type => { | ||||
|                 const ty_key = ip.indexToKey(val); | ||||
|                 const namespace = ty_key.getNamespace(ip.*); | ||||
| @ -147,6 +147,7 @@ pub fn dotCompletions( | ||||
|         .anyframe_type, | ||||
|         => {}, | ||||
| 
 | ||||
|         .simple_value, | ||||
|         .int_u64_value, | ||||
|         .int_i64_value, | ||||
|         .int_big_value, | ||||
|  | ||||
| @ -7,6 +7,7 @@ const URI = @import("uri.zig"); | ||||
| const log = std.log.scoped(.analysis); | ||||
| const ast = @import("ast.zig"); | ||||
| const ComptimeInterpreter = @import("ComptimeInterpreter.zig"); | ||||
| const InternPool = ComptimeInterpreter.InternPool; | ||||
| 
 | ||||
| var using_trail: std.ArrayList([*]const u8) = undefined; | ||||
| var resolve_trail: std.ArrayList(NodeWithHandle) = undefined; | ||||
| @ -765,14 +766,13 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl | ||||
| 
 | ||||
|                     log.info("Invoking interpreter!", .{}); | ||||
| 
 | ||||
|                     store.ensureInterpreterExists(handle.uri) catch |err| { | ||||
|                     const interpreter = store.ensureInterpreterExists(handle.uri) catch |err| { | ||||
|                         log.err("Failed to interpret file: {s}", .{@errorName(err)}); | ||||
|                         if (@errorReturnTrace()) |trace| { | ||||
|                             std.debug.dumpStackTrace(trace.*); | ||||
|                         } | ||||
|                         return null; | ||||
|                     }; | ||||
|                     var interpreter: *ComptimeInterpreter = handle.interpreter.?; | ||||
| 
 | ||||
|                     const root_namespace = @intToEnum(ComptimeInterpreter.Namespace.Index, 0); | ||||
| 
 | ||||
| @ -792,16 +792,13 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl | ||||
|                         return null; | ||||
|                     }; | ||||
| 
 | ||||
|                     const type_type = try interpreter.ip.get(interpreter.allocator, ComptimeInterpreter.Key{ .simple = .type }); | ||||
|                     const is_type_val = value.ty == type_type; | ||||
| 
 | ||||
|                     return TypeWithHandle{ | ||||
|                         .type = .{ | ||||
|                             .data = .{ .@"comptime" = .{ | ||||
|                                 .interpreter = interpreter, | ||||
|                                 .value = value, | ||||
|                             } }, | ||||
|                             .is_type_val = is_type_val, | ||||
|                             .is_type_val = value.ty == InternPool.Index.type, | ||||
|                         }, | ||||
|                         .handle = node_handle.handle, | ||||
|                     }; | ||||
|  | ||||
| @ -14,32 +14,32 @@ const offsets = zls.offsets; | ||||
| const allocator: std.mem.Allocator = std.testing.allocator; | ||||
| 
 | ||||
| test "ComptimeInterpreter - primitive types" { | ||||
|     try testExpr("true", .{ .simple = .bool }, .{ .simple = .bool_true }); | ||||
|     try testExpr("false", .{ .simple = .bool }, .{ .simple = .bool_false }); | ||||
|     try testExpr("5", .{ .simple = .comptime_int }, .{ .int_u64_value = 5 }); | ||||
|     // TODO try testExpr("-2", .{ .simple = .comptime_int }, .{ .int_i64_value = -2 }); | ||||
|     try testExpr("3.0", .{ .simple = .comptime_float }, null); | ||||
|     try testExpr("true", .{ .simple_type = .bool }, .{ .simple_value = .bool_true }); | ||||
|     try testExpr("false", .{ .simple_type = .bool }, .{ .simple_value = .bool_false }); | ||||
|     try testExpr("5", .{ .simple_type = .comptime_int }, .{ .int_u64_value = 5 }); | ||||
|     // TODO try testExpr("-2", .{ .simple_type = .comptime_int }, .{ .int_i64_value = -2 }); | ||||
|     try testExpr("3.0", .{ .simple_type = .comptime_float }, null); | ||||
| 
 | ||||
|     try testExpr("null", .{ .simple = .null_type }, .{ .simple = .null_value }); | ||||
|     try testExpr("void", .{ .simple = .type }, .{ .simple = .void }); | ||||
|     try testExpr("undefined", .{ .simple = .undefined_type }, .{ .simple = .undefined_value }); | ||||
|     try testExpr("noreturn", .{ .simple = .type }, .{ .simple = .noreturn }); | ||||
|     try testExpr("null", .{ .simple_type = .null_type }, .{ .simple_value = .null_value }); | ||||
|     try testExpr("void", .{ .simple_type = .type }, .{ .simple_type = .void }); | ||||
|     try testExpr("undefined", .{ .simple_type = .undefined_type }, .{ .simple_value = .undefined_value }); | ||||
|     try testExpr("noreturn", .{ .simple_type = .type }, .{ .simple_type = .noreturn }); | ||||
| } | ||||
| 
 | ||||
| test "ComptimeInterpreter - expressions" { | ||||
|     if (true) return error.SkipZigTest; // TODO | ||||
|     try testExpr("5 + 3", .{ .simple = .comptime_int }, .{ .int_u64_value = 8 }); | ||||
|     try testExpr("5.2 + 4.2", .{ .simple = .comptime_float }, null); | ||||
|     try testExpr("5 + 3", .{ .simple_type = .comptime_int }, .{ .int_u64_value = 8 }); | ||||
|     try testExpr("5.2 + 4.2", .{ .simple_type = .comptime_float }, null); | ||||
| 
 | ||||
|     try testExpr("3 == 3", .{ .simple = .bool }, .{ .simple = .bool_true }); | ||||
|     try testExpr("5.2 == 2.1", .{ .simple = .bool }, .{ .simple = .bool_false }); | ||||
|     try testExpr("3 == 3", .{ .simple_type = .bool }, .{ .simple_valueclear = .bool_true }); | ||||
|     try testExpr("5.2 == 2.1", .{ .simple_type = .bool }, .{ .simple_value = .bool_false }); | ||||
| 
 | ||||
|     try testExpr("@as(?bool, null) orelse true", .{ .simple = .bool }, .{ .simple = .bool_true }); | ||||
|     try testExpr("@as(?bool, null) orelse true", .{ .simple_type = .bool }, .{ .simple_value = .bool_true }); | ||||
| } | ||||
| 
 | ||||
| test "ComptimeInterpreter - builtins" { | ||||
|     if (true) return error.SkipZigTest; // TODO | ||||
|     try testExpr("@as(bool, true)", .{ .simple = .bool }, .{ .simple = .bool_true }); | ||||
|     try testExpr("@as(bool, true)", .{ .simple_type = .bool }, .{ .simple_value = .bool_true }); | ||||
|     try testExpr("@as(u32, 3)", .{ .int_type = .{ | ||||
|         .signedness = .unsigned, | ||||
|         .bits = 32, | ||||
| @ -64,12 +64,12 @@ test "ComptimeInterpreter - labeled block" { | ||||
|         \\blk: { | ||||
|         \\    break :blk true; | ||||
|         \\} | ||||
|     , .{ .simple = .bool }, .{ .simple = .bool_true }); | ||||
|     , .{ .simple_type = .bool }, .{ .simple_value = .bool_true }); | ||||
|     try testExpr( | ||||
|         \\blk: { | ||||
|         \\    break :blk 3; | ||||
|         \\} | ||||
|     , .{ .simple = .comptime_int }, .{ .int_u64_value = 3 }); | ||||
|     , .{ .simple_type = .comptime_int }, .{ .int_u64_value = 3 }); | ||||
| } | ||||
| 
 | ||||
| test "ComptimeInterpreter - if" { | ||||
| @ -77,18 +77,18 @@ test "ComptimeInterpreter - if" { | ||||
|         \\blk: { | ||||
|         \\    break :blk if (true) true else false; | ||||
|         \\} | ||||
|     , .{ .simple = .bool }, .{ .simple = .bool_true }); | ||||
|     , .{ .simple_type = .bool }, .{ .simple_value = .bool_true }); | ||||
|     try testExpr( | ||||
|         \\blk: { | ||||
|         \\    break :blk if (false) true else false; | ||||
|         \\} | ||||
|     , .{ .simple = .bool }, .{ .simple = .bool_false }); | ||||
|     , .{ .simple_type = .bool }, .{ .simple_value = .bool_false }); | ||||
|     try testExpr( | ||||
|         \\blk: { | ||||
|         \\    if (false) break :blk true; | ||||
|         \\    break :blk false; | ||||
|         \\} | ||||
|     , .{ .simple = .bool }, .{ .simple = .bool_false }); | ||||
|     , .{ .simple_type = .bool }, .{ .simple_value = .bool_false }); | ||||
|     // TODO | ||||
|     // try testExpr( | ||||
|     //     \\outer: { | ||||
| @ -97,7 +97,7 @@ test "ComptimeInterpreter - if" { | ||||
|     //     \\    }) break :outer true; | ||||
|     //     \\    break :outer false; | ||||
|     //     \\} | ||||
|     // , .{ .simple = .bool }, .{ .simple = .bool_true }); | ||||
|     // , .{ .simple_type = .bool }, .{ .simple_value = .bool_true }); | ||||
| } | ||||
| 
 | ||||
| test "ComptimeInterpreter - variable lookup" { | ||||
| @ -106,7 +106,7 @@ test "ComptimeInterpreter - variable lookup" { | ||||
|         \\    var foo = 42; | ||||
|         \\    break :blk foo; | ||||
|         \\} | ||||
|     , .{ .simple = .comptime_int }, .{ .int_u64_value = 42 }); | ||||
|     , .{ .simple_type = .comptime_int }, .{ .int_u64_value = 42 }); | ||||
|     try testExpr( | ||||
|         \\blk: { | ||||
|         \\    var foo = 1; | ||||
| @ -114,7 +114,7 @@ test "ComptimeInterpreter - variable lookup" { | ||||
|         \\    var baz = 3; | ||||
|         \\    break :blk bar; | ||||
|         \\} | ||||
|     , .{ .simple = .comptime_int }, .{ .int_u64_value = 2 }); | ||||
|     , .{ .simple_type = .comptime_int }, .{ .int_u64_value = 2 }); | ||||
| 
 | ||||
|     var context = try Context.init( | ||||
|         \\const bar = foo; | ||||
| @ -123,7 +123,7 @@ test "ComptimeInterpreter - variable lookup" { | ||||
|     defer context.deinit(); | ||||
| 
 | ||||
|     const result = try context.interpret(context.findVar("bar")); | ||||
|     try expectEqualKey(context.interpreter.ip, .{ .simple = .comptime_int }, result.ty); | ||||
|     try expectEqualKey(context.interpreter.ip, .{ .simple_type = .comptime_int }, result.ty); | ||||
|     try expectEqualKey(context.interpreter.ip, .{ .int_u64_value = 3 }, result.val); | ||||
| } | ||||
| 
 | ||||
| @ -133,7 +133,7 @@ test "ComptimeInterpreter - field access" { | ||||
|         \\    const foo: struct {alpha: u64, beta: bool} = undefined; | ||||
|         \\    break :blk foo.beta; | ||||
|         \\} | ||||
|     , .{ .simple = .bool }, null); | ||||
|     , .{ .simple_type = .bool }, null); | ||||
|     try testExpr( | ||||
|         \\blk: { | ||||
|         \\    const foo: struct {alpha: u64, beta: bool} = undefined; | ||||
| @ -152,13 +152,13 @@ test "ComptimeInterpreter - optional operations" { | ||||
|         \\    const foo: ?bool = true; | ||||
|         \\    break :blk foo.?; | ||||
|         \\} | ||||
|     , .{ .simple = .bool }, .{ .simple = .bool_true }); | ||||
|     , .{ .simple_type = .bool }, .{ .simple_value = .bool_true }); | ||||
|     try testExpr( | ||||
|         \\blk: { | ||||
|         \\    const foo: ?bool = true; | ||||
|         \\    break :blk foo == null; | ||||
|         \\} | ||||
|     , .{ .simple = .bool }, .{ .simple = .bool_false }); | ||||
|     , .{ .simple_type = .bool }, .{ .simple_value = .bool_false }); | ||||
| } | ||||
| 
 | ||||
| test "ComptimeInterpreter - pointer operations" { | ||||
| @ -168,20 +168,20 @@ test "ComptimeInterpreter - pointer operations" { | ||||
|         \\    const foo: []const u8 = ""; | ||||
|         \\    break :blk foo.len; | ||||
|         \\} | ||||
|     , .{ .simple = .usize }, .{ .bytes = "" }); | ||||
|     , .{ .simple_type = .usize }, .{ .bytes = "" }); | ||||
|     try testExpr( | ||||
|         \\blk: { | ||||
|         \\    const foo = true; | ||||
|         \\    break :blk &foo; | ||||
|         \\} | ||||
|     , @panic("TODO"), .{ .simple = .bool_true }); | ||||
|     , @panic("TODO"), .{ .simple_value = .bool_true }); | ||||
|     try testExpr( | ||||
|         \\blk: { | ||||
|         \\    const foo = true; | ||||
|         \\    const bar = &foo; | ||||
|         \\    break :blk bar.*; | ||||
|         \\} | ||||
|     , @panic("TODO"), .{ .simple = .bool_true }); | ||||
|     , @panic("TODO"), .{ .simple_value = .bool_true }); | ||||
| } | ||||
| 
 | ||||
| test "ComptimeInterpreter - call return primitive type" { | ||||
| @ -189,7 +189,7 @@ test "ComptimeInterpreter - call return primitive type" { | ||||
|         \\pub fn Foo() type { | ||||
|         \\    return bool; | ||||
|         \\} | ||||
|     , &.{}, .{ .simple = .bool }); | ||||
|     , &.{}, .{ .simple_type = .bool }); | ||||
| 
 | ||||
|     try testCall( | ||||
|         \\pub fn Foo() type { | ||||
| @ -223,17 +223,15 @@ test "ComptimeInterpreter - call return struct" { | ||||
|     defer context.deinit(); | ||||
|     const result = try context.call(context.findFn("Foo"), &.{}); | ||||
| 
 | ||||
|     try std.testing.expect(result.ty == .simple); | ||||
|     try std.testing.expect(result.ty.simple == .type); | ||||
|     try std.testing.expect(result.ty == .simple_type); | ||||
|     try std.testing.expect(result.ty.simple_type == .type); | ||||
|     const struct_info = context.interpreter.ip.getStruct(result.val.?.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); | ||||
| 
 | ||||
|     const bool_type = try context.interpreter.ip.get(allocator, .{ .simple = .bool }); | ||||
| 
 | ||||
|     try std.testing.expectEqual(@as(usize, 1), struct_info.fields.count()); | ||||
|     try std.testing.expectEqualStrings("slay", struct_info.fields.keys()[0]); | ||||
|     try std.testing.expect(struct_info.fields.values()[0].ty == bool_type); | ||||
|     try std.testing.expect(struct_info.fields.values()[0].ty == Index.bool); | ||||
| } | ||||
| 
 | ||||
| test "ComptimeInterpreter - call comptime argument" { | ||||
| @ -247,19 +245,19 @@ test "ComptimeInterpreter - call comptime argument" { | ||||
|     defer context.deinit(); | ||||
| 
 | ||||
|     const result1 = try context.call(context.findFn("Foo"), &.{KV{ | ||||
|         .ty = .{ .simple = .bool }, | ||||
|         .val = .{ .simple = .bool_true }, | ||||
|         .ty = .{ .simple_type = .bool }, | ||||
|         .val = .{ .simple_value = .bool_true }, | ||||
|     }}); | ||||
|     try std.testing.expect(result1.ty == .simple); | ||||
|     try std.testing.expect(result1.ty.simple == .type); | ||||
|     try std.testing.expect(result1.ty == .simple_type); | ||||
|     try std.testing.expect(result1.ty.simple_type == .type); | ||||
|     try std.testing.expectEqual(Key{ .int_type = .{ .signedness = .unsigned, .bits = 8 } }, result1.val.?); | ||||
| 
 | ||||
|     var result2 = try context.call(context.findFn("Foo"), &.{KV{ | ||||
|         .ty = .{ .simple = .bool }, | ||||
|         .val = .{ .simple = .bool_false }, | ||||
|         .ty = .{ .simple_type = .bool }, | ||||
|         .val = .{ .simple_value = .bool_false }, | ||||
|     }}); | ||||
|     try std.testing.expect(result2.ty == .simple); | ||||
|     try std.testing.expect(result2.ty.simple == .type); | ||||
|     try std.testing.expect(result2.ty == .simple_type); | ||||
|     try std.testing.expect(result2.ty.simple_type == .type); | ||||
|     try std.testing.expectEqual(Key{ .int_type = .{ .signedness = .unsigned, .bits = 69 } }, result2.val.?); | ||||
| } | ||||
| 
 | ||||
| @ -303,6 +301,7 @@ const Context = struct { | ||||
| 
 | ||||
|         interpreter.* = .{ | ||||
|             .allocator = allocator, | ||||
|             .ip = try InternPool.init(allocator), | ||||
|             .document_store = document_store, | ||||
|             .uri = handle.uri, | ||||
|         }; | ||||
| @ -399,7 +398,7 @@ fn testCall( | ||||
| 
 | ||||
|     const result = try context.call(context.findFn("Foo"), arguments); | ||||
| 
 | ||||
|     try expectEqualKey(context.interpreter.ip, Key{ .simple = .type }, result.ty); | ||||
|     try expectEqualKey(context.interpreter.ip, Key{ .simple_type = .type }, result.ty); | ||||
|     try expectEqualKey(context.interpreter.ip, expected_ty, result.val); | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user