Skip to content

Commit

Permalink
Merge branch 'weak_ref' of https://github.com/Princess-org/Princess i…
Browse files Browse the repository at this point in the history
…nto weak_ref
  • Loading branch information
Victorious3 committed May 5, 2024
2 parents 192e13a + 4526888 commit 727f637
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 63 deletions.
2 changes: 1 addition & 1 deletion src/codegen.pr
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
12 changes: 6 additions & 6 deletions src/compiler.pr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -3071,7 +3071,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
Expand Down Expand Up @@ -4034,7 +4034,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 {
Expand Down Expand Up @@ -6639,7 +6639,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
Expand Down Expand Up @@ -8925,7 +8925,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)
Expand Down Expand Up @@ -9177,7 +9177,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)
Expand Down
2 changes: 1 addition & 1 deletion src/debug.pr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/lexer.pr
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export type TokenType = enum {
K_ASSERT
K_TYPE_OF
K_UNDEF
K_WEAK_REF
K_WEAK
INTEGER
FLOAT
STRING
Expand Down Expand Up @@ -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
]
Expand Down
34 changes: 4 additions & 30 deletions src/parser.pr
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion src/runtime.pr
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion src/scope.pr
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
4 changes: 2 additions & 2 deletions src/serialize.pr
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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

Expand Down
41 changes: 22 additions & 19 deletions src/typechecking.pr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}

Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 {

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 727f637

Please sign in to comment.