Skip to content

Commit 7a9c556

Browse files
committed
Make interfaces work hopefully
1 parent fd1cfe0 commit 7a9c556

3 files changed

Lines changed: 130 additions & 127 deletions

File tree

src/compiler.pr

Lines changed: 117 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -9458,148 +9458,144 @@ def generate_vtable_function(function: &Function, fdef: typechecking::FunctionDe
94589458
] !InsnSwitch
94599459
push_insn(swtch, state)
94609460

9461-
let hashes = set::make(uint64)
9462-
let keys = map::keys(typechecking::type_registry)
9463-
for var i in 0..keys.size {
9464-
let type_entry = typechecking::type_registry(keys(i))
9465-
if is_ref(type_entry.tpe) and typechecking::implements(type_entry, first_param, state.scope) {
9466-
// FIXME This whole branch isn't working yet because interfaces don't work right now
9467-
let hash = type_entry.id
9468-
if hashes.contains(hash) { continue }
9469-
hashes.add(hash)
9461+
let intf = first_param.resolve()
9462+
assert intf.implementors
9463+
for var key in @intf.implementors.keys() {
9464+
let functions = intf.implementors(key)
9465+
let implementor = key.resolve()
9466+
let hash = key !uint64
94709467

9471-
//let generic = typechecking::get_generic(type_entry.tpe)
9472-
//if generic and generic.tc_incomplete { continue }
9473-
if not type_entry.tpe { continue }
9468+
//let generic = typechecking::get_generic(type_entry.tpe)
9469+
//if generic and generic.tc_incomplete { continue }
94749470

9475-
state.module.imported.add(type_entry.tpe.type_name)
9471+
state.module.imported.add(implementor.type_name)
94769472

9477-
let parameter_t = vector::copy(ftpe.parameter_t)
9478-
parameter_t(0) = [ tpe = type_entry.id ] !typechecking::NamedParameter
9479-
9480-
var score = std::MAX_INT32 !int
9481-
var fun: &typechecking::FunctionDef
9482-
var module: &toolchain::Module = null
9483-
/*for var member in typechecking::iterate_member_functions(type_entry) {
9484-
if member.function.name != ftpe.name { continue }
9485-
let s = typechecking::overload_score(member.function, parameter_t, state.module, true, local_type_defs = make_local_type_defs())
9486-
if s >= 0 and s < score {
9487-
fun = member.function
9488-
module = member.module
9489-
score = s
9490-
}
9491-
}*/
9473+
let parameter_t = vector::copy(ftpe.parameter_t)
9474+
parameter_t(0) = [ tpe = implementor.id ] !typechecking::NamedParameter
9475+
9476+
var score = std::MAX_INT32 !int
9477+
var fun: &typechecking::FunctionDef
9478+
var module: &toolchain::Module = null
9479+
9480+
for var f in functions {
9481+
let fdef = f.fdef
9482+
if typechecking::overload_score(fdef, parameter_t, state.scope, true) == 0 {
9483+
fun = fdef
9484+
module = f.module
9485+
break
9486+
}
9487+
}
94929488

9493-
var kind = 0
9494-
if not fun {
9495-
if function.unmangled.starts_with("__set_") and function.unmangled.ends_with("__") {
9496-
kind = 1
9497-
} else if function.args.length == 1 {
9498-
kind = 2
9499-
} else {
9500-
continue
9501-
}
9489+
if not fun { assert }
9490+
9491+
var kind = 0
9492+
if not fun {
9493+
if function.unmangled.starts_with("__set_") and function.unmangled.ends_with("__") {
9494+
kind = 1
9495+
} else if function.args.length == 1 {
9496+
kind = 2
95029497
} else {
9503-
predeclare_function(@fun, state.module)
9504-
state.module.imported.add(fun.name)
9498+
continue
9499+
}
9500+
} else {
9501+
predeclare_function(@fun, state.module)
9502+
state.module.imported.add(fun.name)
95059503

9506-
if consteval::is_static {
9507-
let fun = scope::get_function(module.scope, parser::make_identifier(fun.unmangled), parameter_t, false, false, false)
9508-
let val = consteval::compile_function(fun, state.scope)
9509-
import_structures(val.get_type(), state.module)
9510-
}
9504+
if consteval::is_static {
9505+
let fun = scope::get_function(module.scope, parser::make_identifier(fun.unmangled), parameter_t, false, false, false)
9506+
let val = consteval::compile_function(fun, state.scope)
9507+
import_structures(val.get_type(), state.module)
95119508
}
9509+
}
95129510

9513-
if kind != 0 and type_entry.tpe.kind != typechecking::TypeKind::STRUCT { continue }
9511+
if kind != 0 and implementor.kind != typechecking::TypeKind::STRUCT { continue }
95149512

9515-
if not consteval::is_static {
9516-
import_structure(type_entry.tpe, state.module)
9517-
}
9513+
if not consteval::is_static {
9514+
import_structure(implementor, state.module)
9515+
}
95189516

9519-
let if_true = make_label(state)
9520-
push_label(if_true, state)
9521-
9522-
let svalue = [
9523-
label_ = if_true,
9524-
value = [ kind = ValueKind::INT, i = hash, tpe = builtins::int64_ ] !Value
9525-
] !SwitchValue
9526-
switch_values.push(svalue)
9517+
let if_true = make_label(state)
9518+
push_label(if_true, state)
9519+
9520+
let svalue = [
9521+
label_ = if_true,
9522+
value = [ kind = ValueKind::INT, i = hash, tpe = builtins::int64_ ] !Value
9523+
] !SwitchValue
9524+
switch_values.push(svalue)
95279525

9528-
9529-
let target_type = fun.to_type().resolve().parameter_t(0).tpe if fun else type_entry.id
9530-
let reference = convert_ref_to_ref(target_type, [ kind = ValueKind::LOCAL, tpe = first_param, name = "__ref.value"] !Value, null, state)
9531-
9532-
if kind == 0 {
9533-
let args = allocate_ref(Value, vector::length(ftpe.parameter_t))
9534-
args(0) = reference
9535-
for var i in 1..vector::length(ftpe.parameter_t) {
9536-
let np = ftpe.parameter_t(i)
9537-
args(i) = [ kind = ValueKind::LOCAL, tpe = np.tpe, name = np.name + ".value" ] !Value
9526+
let target_type = fun.to_type().resolve().parameter_t(0).tpe if fun else implementor.id
9527+
let reference = convert_ref_to_ref(target_type, [ kind = ValueKind::LOCAL, tpe = first_param, name = "__ref.value"] !Value, null, state)
9528+
9529+
if kind == 0 {
9530+
let args = allocate_ref(Value, vector::length(ftpe.parameter_t))
9531+
args(0) = reference
9532+
for var i in 1..vector::length(ftpe.parameter_t) {
9533+
let np = ftpe.parameter_t(i)
9534+
args(i) = [ kind = ValueKind::LOCAL, tpe = np.tpe, name = np.name + ".value" ] !Value
9535+
}
9536+
let r = state.call(fun.name, ret_tpe, args)
9537+
state.ret(r)
9538+
} else if kind == 1 {
9539+
// Setter
9540+
var deref = state.extract_value(pointer(implementor.id), reference, [1])
9541+
var value = state.load(implementor.id, deref)
9542+
let name = function.unmangled.slice(6, function.unmangled.length() - 2)
9543+
var findex: size_t = 0
9544+
var ftpe: &typechecking::Type
9545+
for var field in @implementor.fields {
9546+
if field.name == name {
9547+
findex = field.index
9548+
ftpe = field.tpe
95389549
}
9539-
let r = state.call(fun.name, ret_tpe, args)
9540-
state.ret(r)
9541-
} else if kind == 1 {
9542-
// Setter
9543-
var deref = state.extract_value(pointer(type_entry.tpe), reference, [1])
9544-
var value = state.load(type_entry.tpe, deref)
9545-
let name = function.unmangled.slice(6, function.unmangled.length() - 2)
9546-
var findex: size_t = 0
9547-
var ftpe: &typechecking::Type
9548-
for var field in @type_entry.tpe.resolve().fields {
9550+
}
9551+
9552+
let np = ftpe.parameter_t(1)
9553+
let arg = [ kind = ValueKind::LOCAL, tpe = np.tpe, name = np.name + ".value" ] !Value
9554+
value = state.insert_value(implementor.id, value, arg, [findex !int])
9555+
state.store(deref, value)
9556+
state.ret(NO_VALUE)
9557+
} else {
9558+
// Getter
9559+
let name = function.unmangled
9560+
9561+
var const_field: typechecking::StructMember
9562+
var is_const = false
9563+
let const_fields = implementor.const_fields
9564+
if const_fields {
9565+
for var field in @const_fields {
95499566
if field.name == name {
9550-
findex = field.index
9551-
ftpe = field.tpe
9567+
is_const = true
9568+
const_field = field
9569+
break
95529570
}
95539571
}
9572+
}
95549573

9555-
let np = ftpe.parameter_t(1)
9556-
let arg = [ kind = ValueKind::LOCAL, tpe = np.tpe, name = np.name + ".value" ] !Value
9557-
value = state.insert_value(type_entry.tpe, value, arg, [findex !int])
9558-
state.store(deref, value)
9559-
state.ret(NO_VALUE)
9574+
if is_const {
9575+
let res = convert_to(null !&Value, @const_field.properties.value, ret_tpe, state)
9576+
state.ret(res)
95609577
} else {
9561-
// Getter
9562-
let name = function.unmangled
9578+
var stpe = implementor.id
9579+
// Resolve member
9580+
var deref = state.extract_value(pointer(stpe), reference, [1])
9581+
var value = state.load(stpe, deref)
9582+
value.addr = deref
95639583

9564-
var const_field: typechecking::StructMember
9565-
var is_const = false
9566-
let const_fields = type_entry.tpe.resolve().const_fields
9567-
if const_fields {
9568-
for var field in @const_fields {
9569-
if field.name == name {
9570-
is_const = true
9571-
const_field = field
9572-
break
9573-
}
9574-
}
9584+
let vec = vector::make(Member)
9585+
if not resolve_member(vec, stpe, name) {
9586+
return
95759587
}
95769588

9577-
if is_const {
9578-
let res = convert_to(null !&Value, @const_field.properties.value, ret_tpe, state)
9579-
state.ret(res)
9580-
} else {
9581-
var stpe = type_entry.tpe
9582-
// Resolve member
9583-
var deref = state.extract_value(pointer(stpe), reference, [1])
9584-
var value = state.load(stpe, deref)
9585-
value.addr = deref
9586-
9587-
let vec = vector::make(Member)
9588-
if not resolve_member(vec, stpe, name) {
9589-
return
9590-
}
9591-
9592-
let len = vector::length(vec)
9593-
for var i in 0..len {
9594-
let j = len - i - 1
9595-
let member = vec(j)
9596-
value = walk_MemberAccess_struct(null, stpe, member, value, state)
9597-
stpe = member.tpe
9598-
}
9599-
let val = load_value(value, null, state)
9600-
increase_ref_count_of_value(val, null, state)
9601-
state.ret(val)
9589+
let len = vector::length(vec)
9590+
for var i in 0..len {
9591+
let j = len - i - 1
9592+
let member = vec(j)
9593+
value = walk_MemberAccess_struct(null, stpe, member, value, state)
9594+
stpe = member.tpe
96029595
}
9596+
let val = load_value(value, null, state)
9597+
increase_ref_count_of_value(val, null, state)
9598+
state.ret(val)
96039599
}
96049600
}
96059601
}

src/scope.pr

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ def find_function(scope: &Scope, node: &parser::Node, v: &Value, parameter_t: &V
813813
}
814814

815815
if found != null {
816-
if found.phase == Phase::DEFINED and not dry_run {
816+
if found.phase == Phase::DEFINED {
817817
found = typecheck_function(found, parameter_t, found_scope)
818818
}
819819
return true, found
@@ -2020,6 +2020,8 @@ export def trigger_impl(scope: &Scope, tpe: &typechecking::Type) {
20202020
let temp_scope = enter_scope(scope)
20212021
// TODO score of 1 is hardcoded, we need to check if the resulting type is actually the same
20222022
if typechecking::convert_type_score(impl.left, tpe, temp_scope) <= 1 {
2023+
let functions = vector::make(&Value)
2024+
20232025
// The type matches, now get the right hand side
20242026
let right = impl.right.copy().resolve(temp_scope).resolve()
20252027
// We don't give errors in static context
@@ -2063,6 +2065,10 @@ export def trigger_impl(scope: &Scope, tpe: &typechecking::Type) {
20632065
res = false
20642066
} else {
20652067
let ftpe = fun.fdef.to_type().resolve()
2068+
if not ftpe {
2069+
print_fdef(fun.fdef)
2070+
assert
2071+
}
20662072
for var i in 0..fun.fdef.return_t.length {
20672073
if not typechecking::equals(ftpe.return_t(i), member.return_t(i)){
20682074
res = false
@@ -2079,16 +2085,17 @@ export def trigger_impl(scope: &Scope, tpe: &typechecking::Type) {
20792085
cnt = false
20802086
break
20812087
}
2088+
functions.push(fun)
20822089
}
20832090

20842091
if not cnt {
20852092
continue
20862093
}
20872094

20882095
if not right.implementors {
2089-
right.implementors = set::make(typechecking::TypeId)
2096+
right.implementors = map::make(typechecking::TypeId, type &Vector(&Value))
20902097
}
2091-
right.implementors.add(tpe.id)
2098+
right.implementors(tpe.id) = functions
20922099

20932100
if not tpe.implements {
20942101
tpe.implements = set::make(typechecking::TypeId)

src/typechecking.pr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ export type Type = struct {
250250
//cached: &Map(TypeId, CacheEntry)
251251

252252
implements: &Set(TypeId)
253-
implementors: &Set(TypeId)
253+
implementors: &Map(TypeId, &Vector(&scope::Value))
254254
}
255255

256256
export def has_variant(this: &Type, tpe: &Type) -> bool {
@@ -5040,7 +5040,7 @@ def walk_Cast(node: &parser::Node, state: &State) {
50405040
}
50415041
} else if ltpe.is_ref_or_weak() and
50425042
ltpe.tpe.is_interface() and
5043-
not implements(rtpe, ltpe.tpe, state.scope) and
5043+
not implements(rtpe, ltpe, state.scope) and
50445044
(rtpe.is_struct() or (rtpe.is_ref() and rtpe.tpe.is_struct())) {
50455045

50465046
var dst = pointer(rtpe)
@@ -5080,7 +5080,7 @@ def walk_Cast(node: &parser::Node, state: &State) {
50805080
node.tpe = rtpe
50815081
}
50825082

5083-
left.tpe = rtpe
5083+
//left.tpe = rtpe
50845084
// TODO Dunno if this did anything special
50855085
/*ltpe = initial_ltpe
50865086

0 commit comments

Comments
 (0)