From 452688856db92de158c944505dd286e95cedb558 Mon Sep 17 00:00:00 2001 From: Vic Nightfall Date: Sat, 4 May 2024 14:07:04 +0200 Subject: [PATCH] Change syntax for weak ref --- src/codegen.pr | 2 +- src/compiler.pr | 12 ++++++------ src/debug.pr | 2 +- src/lexer.pr | 4 ++-- src/parser.pr | 34 ++++------------------------------ src/runtime.pr | 7 ++++++- src/scope.pr | 2 +- src/serialize.pr | 4 ++-- src/typechecking.pr | 41 ++++++++++++++++++++++------------------- 9 files changed, 45 insertions(+), 63 deletions(-) diff --git a/src/codegen.pr b/src/codegen.pr index 97dd1914..3044fdfe 100644 --- a/src/codegen.pr +++ b/src/codegen.pr @@ -12,7 +12,7 @@ import builtins def type_to_str(tpe: &typechecking::Type) -> Str { if not tpe { return "void" } if tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk } var ret: StringBuffer = "" switch tpe.kind !int { diff --git a/src/compiler.pr b/src/compiler.pr index 4b3de144..09f041cd 100644 --- a/src/compiler.pr +++ b/src/compiler.pr @@ -1110,7 +1110,7 @@ def import_structure(tpe: &typechecking::Type, module: &toolchain::Module) { export def import_structures(tpe: &typechecking::Type, module: &toolchain::Module) { if not tpe { return } if tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk } switch tpe.kind !int { case typechecking::TypeKind::STRUCT..=typechecking::TypeKind::UNION @@ -3058,7 +3058,7 @@ def walk_Call(node: &parser::Node, state: &State) -> Value { insert_copy_constructor(ret, expr, loc, state) expr = state.load(expr.tpe, ret, loc) } - // TODO Does this need to do something for weak references? + // TODO Does this need to do something for wk references? if typechecking::is_ref(last_np.tpe) and not typechecking::is_ref(n.tpe) { create_type(reference(n.tpe), state.module) // We need to increase the ref count and add the destructor call @@ -4021,7 +4021,7 @@ def walk_MemberAccess_struct(node: &parser::Node, tpe: &typechecking::Type, memb var member_type = member.tpe if member.tpe.kind == typechecking::TypeKind::BOX { - member_type = member.tpe.weak + member_type = member.tpe.wk } if tpe.kind == typechecking::TypeKind::UNION { @@ -6626,7 +6626,7 @@ def di_type(tpe: &typechecking::Type, state: &State) -> &Value { (@state).ditypes(tpe) = ditpep if tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk } switch tpe.kind !int { // TODO compare with char for special casing @@ -8906,7 +8906,7 @@ def do_create_type(tpe: &typechecking::Type, svalue: &scope::Value, module: &too if toolchain::no_stdlib { return NO_VALUE } if tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk } let generic = typechecking::get_generic(tpe) @@ -9158,7 +9158,7 @@ type TypeEntry = struct { export def create_type(tpe: &typechecking::Type, module: &toolchain::Module, cache: &Vector(TypeEntry)) -> &Value { if not tpe { return null } if tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk } if tpe.tc_incomplete { return null } let generic = typechecking::get_generic(tpe) diff --git a/src/debug.pr b/src/debug.pr index 3dc490f4..5186c8fd 100644 --- a/src/debug.pr +++ b/src/debug.pr @@ -835,7 +835,7 @@ export def type_to_str(tpe: &typechecking::Type, full_name: bool = false) -> Str if tpe.tc_tpe { return tc_args_to_string(tpe, full_name) } switch tpe.kind !int { case typechecking::TypeKind::BOX - return "Box<" + type_to_str(tpe.weak, full_name) + ">" + return "Box<" + type_to_str(tpe.wk, full_name) + ">" case typechecking::TypeKind::VOID return "void" case typechecking::TypeKind::BOOL diff --git a/src/lexer.pr b/src/lexer.pr index 111b73d1..489d895f 100644 --- a/src/lexer.pr +++ b/src/lexer.pr @@ -99,7 +99,7 @@ export type TokenType = enum { K_ASSERT K_TYPE_OF K_UNDEF - K_WEAK_REF + K_WEAK INTEGER FLOAT STRING @@ -223,7 +223,7 @@ let KEYWORDS = [ [token_type = TokenType::K_DEFINED, str = "defined"] !Keyword, [token_type = TokenType::K_DEFER, str = "defer"] !Keyword, [token_type = TokenType::K_TYPE_OF, str = "type_of"] !Keyword, - [token_type = TokenType::K_WEAK_REF, str = "weak_ref"] !Keyword, + [token_type = TokenType::K_WEAK, str = "weak"] !Keyword, [token_type = TokenType::K_YIELD, str = "yield"] !Keyword, [token_type = TokenType::K_IMPLICIT, str = "implicit"] !Keyword ] diff --git a/src/parser.pr b/src/parser.pr index ec02c3f3..667c73ce 100644 --- a/src/parser.pr +++ b/src/parser.pr @@ -1855,43 +1855,17 @@ def expect_array_or_tuple(parse_state: &ParseState) -> &Node { } def expect_weak_ref(parse_state: &ParseState, inline_types: bool) -> &Node { - var tok = expect(parse_state, lexer::TokenType::K_WEAK_REF, "Expected weak_ref") + var tok = expect(parse_state, lexer::TokenType::K_WEAK, "Expected weak") let line = tok.line let column = tok.column - - var tpe: &Node = null - var kw = VarDecl::VAR - tok = peek(parse_state) - if tok.tpe == lexer::TokenType::O_PAREN { - pop(parse_state) - skip_newline(parse_state) - tok = peek(parse_state) - if tok.tpe == lexer::TokenType::K_VAR { - pop(parse_state) - skip_newline(parse_state) - } else if tok.tpe == lexer::TokenType::K_LET { - pop(parse_state) - kw = VarDecl::LET - skip_newline(parse_state) - } - - var tokens = parse_state.tokens - tpe = parse_type(parse_state, inline_types) - if not tpe { - parse_state.tokens = tokens - } - - skip_newline(parse_state) - expect(parse_state, lexer::TokenType::C_PAREN, "Expected ')'") - } + let tpe = expect_type(parse_state) var node = make_node(NodeKind::WEAK_REF_T, line, column, parse_state) node.value.t_parr = [ - kw = kw, tpe = tpe ] !NodePtrArrayT - node._hash = combine_hashes(node.kind !uint64, kw !uint64, hash(tpe)) + node._hash = combine_hashes(node.kind !uint64, hash(tpe)) return node } @@ -2413,7 +2387,7 @@ def parse_type2(parse_state: &ParseState, inline_types: bool) -> &Node { tok.tpe == lexer::TokenType::OP_BAND { back(parse_state) return expect_ptr_ref(parse_state, tok.tpe == lexer::TokenType::OP_BAND, inline_types) - } else if tok.tpe == lexer::TokenType::K_WEAK_REF { + } else if tok.tpe == lexer::TokenType::K_WEAK { back(parse_state) return expect_weak_ref(parse_state, inline_types) } else if tok.tpe == lexer::TokenType::DOUBLE_COLON or diff --git a/src/runtime.pr b/src/runtime.pr index fbddf30b..cf15cafd 100644 --- a/src/runtime.pr +++ b/src/runtime.pr @@ -89,8 +89,13 @@ export type Field = struct { tpe: *Type } +export type Refcount = struct { + strong_cnt: int64 + weak_cnt: int64 +} + export type Ref = struct { - ref_count: *int64 + ref_count: *Refcount value: * tpe: *Type } diff --git a/src/scope.pr b/src/scope.pr index 69f80490..58794ae9 100644 --- a/src/scope.pr +++ b/src/scope.pr @@ -938,7 +938,7 @@ export def generate_function(scope: &Scope, node: &parser::Node, parameter_t: &V for var i in 0..found_member.return_t.length { var tpe = found_member.return_t(i) if tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk } return_t.push(typechecking::copy(tpe)) } diff --git a/src/serialize.pr b/src/serialize.pr index b3f797cd..d159f4ec 100644 --- a/src/serialize.pr +++ b/src/serialize.pr @@ -25,7 +25,7 @@ def add_type(tpe: &typechecking::Type, state: &Serialize) -> int64 { if not tpe { return -1 } if tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk assert tpe.kind != typechecking::TypeKind::BOX } @@ -139,7 +139,7 @@ def serialize_type(fp: File, tpe: &typechecking::Type, state: &Serialize) { return } if tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk } assert tpe.kind != typechecking::TypeKind::BOX diff --git a/src/typechecking.pr b/src/typechecking.pr index c2b291bf..df7b795a 100644 --- a/src/typechecking.pr +++ b/src/typechecking.pr @@ -59,9 +59,9 @@ export type TypeKind = enum { // Tagged union types, very similar to VARIANT but the equality relation is different // This is actually called variant in runtime TUNION - // References to structs are using a weak reference, ie. Type::weak instead of Type::_tpe + // References to structs are using a wk reference, ie. Type::wk instead of Type::_tpe // This is because references to structs can cause cycles - // TODO I think we don't really need this because we can just use weak directly + // TODO I think we don't really need this because we can just use wk directly BOX VOID TO_INFER // Placeholder type for inference @@ -141,7 +141,7 @@ export type Type = struct { // This is also used for type arguments to specify the actual type // And tagged unions carry the underlying union type _tpe: &Type - weak: weak_ref(Type) + wk: weak_ref(Type) packed: bool // Fields for struct, array of StructMember fields: &[StructMember] @@ -177,7 +177,7 @@ export type Type = struct { svalue: weak_ref(scope::Value) // This is used by deserialization to check if a type is in the - // type cache, so that structs can keep a weak reference to the type + // type cache, so that structs can keep a wk reference to the type is_in_type_cache: bool // Set on type arguments is_type_argument: bool @@ -490,7 +490,7 @@ export def defmodule(tpe: &Type) -> weak_ref(toolchain::Module) { export def tpe(tpe: &Type) -> &Type { if not tpe { return null } if tpe._tpe and tpe._tpe.kind == TypeKind::BOX { - return tpe._tpe.weak + return tpe._tpe.wk } return tpe._tpe } @@ -504,7 +504,7 @@ export def get_module(tpe: &Type) -> &toolchain::Module { export def box(tpe: &Type) -> &Type { if not tpe { return null } let box = make_type_raw(TypeKind::BOX) - box.weak = tpe + box.wk = tpe return box } @@ -522,7 +522,7 @@ export type NamedParameter = struct { export def tpe(np: NamedParameter) -> &Type { if not np._tpe { return null } if np._tpe.kind == TypeKind::BOX { - return np._tpe.weak + return np._tpe.wk } return np._tpe } @@ -670,7 +670,7 @@ export def is_box(tpe: &Type) -> bool { export def unbox(tpe: &Type) -> &Type { if not tpe { return null } if tpe.kind == TypeKind::BOX { - return tpe.weak + return tpe.wk } return tpe } @@ -1116,7 +1116,7 @@ export def copy(a: &Type) -> &Type { a.kind == TypeKind::TYPE_DEF or a.kind == TypeKind::TYPE { if a._tpe and a._tpe.kind == TypeKind::BOX { - t._tpe = copy(a._tpe.weak) // Unbox for copy + t._tpe = copy(a._tpe.wk) // Unbox for copy } else { t._tpe = copy(a._tpe) } @@ -1141,10 +1141,10 @@ export def equals(a: &Type, b: &Type) -> bool { } if not a or not b { return false } if a.kind == TypeKind::BOX { - a = a.weak + a = a.wk } if b.kind == TypeKind::BOX { - b = b.weak + b = b.wk } if a.kind != TypeKind::TYPE and a._hash and b._hash { @@ -1329,7 +1329,7 @@ def has_function(entry: &TypeEntry, intf: &Type, mb: StructuralTypeMember, modul let ta = return_t(k) var tb = mb.return_t(k) if tb.kind == TypeKind::BOX { - tb = tb.weak + tb = tb.wk } if not equals(ta, tb) { mismatch = true @@ -1383,9 +1383,9 @@ export def implements(a: &Type, b: &Type, module: &toolchain::Module, visited: & for var k in 0..vector::length(ma.return_t) { var ta = ma.return_t(k) - if ta.kind == TypeKind::BOX { ta = ta.weak } + if ta.kind == TypeKind::BOX { ta = ta.wk } var tb = mb.return_t(k) - if tb.kind == TypeKind::BOX { ta = tb.weak } + if tb.kind == TypeKind::BOX { ta = tb.wk } if not equals(ta, tb) { mismatch = true break @@ -1536,10 +1536,10 @@ const IMPLICIT = 15 export def convert_type_score(a: &Type, b: &Type, module: &toolchain::Module, is_type: bool = false, impl: bool = true) -> int { if not a or not b { return 0 } if a.kind == TypeKind::BOX { - a = a.weak + a = a.wk } if b.kind == TypeKind::BOX { - b = b.weak + b = b.wk } if equals(a, b) { @@ -2653,7 +2653,10 @@ export def do_type_lookup(node: &parser::Node, state: &State, current_type: &Typ node.scope = state.scope if node.value.t_parr.tpe { node.value.t_parr.tpe.parent = node } var tpe = type_lookup(node.value.t_parr.tpe, state, current_type, lookup_default, cache) - tpe = weak_reference(tpe, node.value.t_parr.kw) + if not tpe or tpe.kind != TypeKind::REFERENCE { + errors::errorn(node, "Weak reference must point at a reference!") + } + tpe = weak_reference(tpe.tpe, tpe.kw) return tpe } else if node.kind == parser::NodeKind::STRUCT_T or node.kind == parser::NodeKind::UNION_T { @@ -5072,7 +5075,7 @@ export def walk_Call(node: &parser::Node, dry_run: bool, state: &State) -> bool var tpe = (@left).tpe if tpe and tpe.kind == typechecking::TypeKind::BOX { - tpe = tpe.weak + tpe = tpe.wk } var arguments = vector::make(NamedParameter) @@ -5722,7 +5725,7 @@ def walk_MemberAccess_aggregate(node: &parser::Node, ucs: bool, state: &State) - return false } if rtpe.kind == TypeKind::BOX { - rtpe = rtpe.weak + rtpe = rtpe.wk } node.tpe = rtpe } else if (@tpe).kind == TypeKind::ARRAY or (@tpe).kind == TypeKind::STATIC_ARRAY {