From 9cde2495b2969097d7ffde21b3af9b26f5fe5fa3 Mon Sep 17 00:00:00 2001 From: Techatrix <19954306+Techatrix@users.noreply.github.com> Date: Sat, 28 Jan 2023 18:54:16 +0100 Subject: [PATCH] bug fixes --- src/ComptimeInterpreter.zig | 62 ++++++++++++------- .../comptime_interpreter.zig | 10 +++ 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/src/ComptimeInterpreter.zig b/src/ComptimeInterpreter.zig index f90a90e..ba9934e 100644 --- a/src/ComptimeInterpreter.zig +++ b/src/ComptimeInterpreter.zig @@ -214,7 +214,7 @@ pub fn interpret( try interpreter.namespaces.append(interpreter.allocator, .{ .parent = namespace, .node_idx = node_idx, - .ty = undefined, + .ty = .none, }); const container_namespace = @intToEnum(Namespace.Index, interpreter.namespaces.len - 1); @@ -263,7 +263,7 @@ pub fn interpret( }); } - const struct_type = try interpreter.ip.get(interpreter.allocator, Key{ .struct_type = struct_index }); // TODO potential double free on struct_info.field + const struct_type = try interpreter.ip.get(interpreter.allocator, Key{ .struct_type = struct_index }); interpreter.namespaces.items(.ty)[@enumToInt(container_namespace)] = struct_type; return InterpretResult{ .value = Value{ @@ -282,16 +282,36 @@ pub fn interpret( .aligned_var_decl, .simple_var_decl, => { - var decls = &interpreter.namespaces.items(.decls)[@enumToInt(namespace)]; + var decls: *std.StringArrayHashMapUnmanaged(InternPool.DeclIndex) = &interpreter.namespaces.items(.decls)[@enumToInt(namespace)]; const name = analysis.getDeclName(tree, node_idx).?; - if (decls.contains(name)) + const decl_index = try interpreter.ip.createDecl(interpreter.allocator, .{ + .name = name, + .ty = .none, + .val = .none, + .alignment = 0, // TODO + .address_space = .generic, // TODO + .is_pub = true, // TODO + .is_exported = false, // TODO + }); + + const gop = try decls.getOrPutValue(interpreter.allocator, name, decl_index); + if (gop.found_existing) { return InterpretResult{ .nothing = {} }; + } - const decl = tree.fullVarDecl(node_idx).?; + const var_decl = tree.fullVarDecl(node_idx).?; - const type_value = if (decl.ast.type_node != 0) (try interpreter.interpret(decl.ast.type_node, namespace, .{})).maybeGetValue() else null; - const init_value = if (decl.ast.init_node != 0) (try interpreter.interpret(decl.ast.init_node, namespace, .{})).maybeGetValue() else null; + const type_value = blk: { + if (var_decl.ast.type_node == 0) break :blk null; + const result = interpreter.interpret(var_decl.ast.type_node, namespace, .{}) catch break :blk null; + break :blk result.maybeGetValue(); + }; + const init_value = blk: { + if (var_decl.ast.init_node == 0) break :blk null; + const result = interpreter.interpret(var_decl.ast.init_node, namespace, .{}) catch break :blk null; + break :blk result.maybeGetValue(); + }; if (type_value == null and init_value == null) return InterpretResult{ .nothing = {} }; @@ -300,16 +320,9 @@ pub fn interpret( if (v.ty != type_type) return InterpretResult{ .nothing = {} }; } - const decl_index = try interpreter.ip.createDecl(interpreter.allocator, .{ - .name = name, - .ty = if (type_value) |v| v.val else init_value.?.ty, - .val = if (init_value) |init| init.val else .none, - .alignment = 0, // TODO - .address_space = .generic, // TODO - .is_pub = true, // TODO - .is_exported = false, // TODO - }); - try decls.putNoClobber(interpreter.allocator, name, decl_index); + const decl = interpreter.ip.getDecl(decl_index); + decl.ty = if (type_value) |v| v.val else init_value.?.ty; + decl.val = if (init_value) |init| init.val else .none; // TODO: Am I a dumbo shrimp? (e.g. is this tree shaking correct? works on my machine so like...) @@ -428,6 +441,7 @@ pub fn interpret( // Logic to find identifiers in accessible scopes if (interpreter.huntItDown(namespace, identifier, options)) |decl_index| { const decl = interpreter.ip.getDecl(decl_index); + if(decl.ty == .none) return InterpretResult{ .nothing = {} }; return InterpretResult{ .value = Value{ .interpreter = interpreter, .node_idx = node_idx, @@ -656,12 +670,14 @@ pub fn interpret( .equal_equal => { var a = try interpreter.interpret(data[node_idx].lhs, namespace, options); var b = try interpreter.interpret(data[node_idx].rhs, namespace, options); + const a_value = a.maybeGetValue() orelse return InterpretResult{ .nothing = {} }; + const b_value = b.maybeGetValue() orelse return InterpretResult{ .nothing = {} }; 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 (a.value.val == b.value.val) .bool_true else .bool_false }), // TODO eql function required? + .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? }, }; }, @@ -847,9 +863,10 @@ pub fn interpret( const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }); - if (value.ty != type_type) return error.InvalidBuiltin; + if (value.ty != type_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; + const value_namespace = interpreter.ip.indexToKey(value.val).getNamespace(interpreter.ip); if (value_namespace == .none) return error.InvalidBuiltin; @@ -930,6 +947,9 @@ pub fn interpret( var buf: [1]Ast.Node.Index = undefined; const func = tree.fullFnProto(&buf, node_idx).?; + if (func.name_token == null) return InterpretResult{ .nothing = {} }; + const name = offsets.tokenToSlice(tree, func.name_token.?); + // TODO: Resolve function type const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type }); @@ -967,8 +987,6 @@ pub fn interpret( // if ((try interpreter.interpret(func.ast.return_type, func_scope_idx, .{ .observe_values = true, .is_comptime = true })).maybeGetValue()) |value| // fnd.return_type = value.value_data.@"type"; - const name = offsets.tokenToSlice(tree, func.name_token.?); - if (namespace != .none) { const decls = &interpreter.namespaces.items(.decls)[@enumToInt(namespace)]; diff --git a/tests/language_features/comptime_interpreter.zig b/tests/language_features/comptime_interpreter.zig index 36c442d..3e7928f 100644 --- a/tests/language_features/comptime_interpreter.zig +++ b/tests/language_features/comptime_interpreter.zig @@ -94,6 +94,16 @@ test "ComptimeInterpreter - variable lookup" { \\ break :blk bar; \\} , .{ .simple = .comptime_int }, .{ .int_u64_value = 2 }); + + var context = try Context.init( + \\const bar = foo; + \\const foo = 3; + ); + 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, .{ .int_u64_value = 3 }, result.val); } test "ComptimeInterpreter - field access" {