@@ -219,6 +219,14 @@ export def find_references_to(value: &Value) -> &Vector(parser::SourceLoc) {
219219 return res
220220}
221221
222+ export type Impl = struct {
223+ share: parser::ShareMarker
224+ module: weak &toolchain::Module
225+ left: &typechecking::TypeRef
226+ right: &typechecking::TypeRef
227+ node: weak &parser::Node
228+ }
229+
222230export type ReExport = struct {
223231 module: weak &toolchain::Module
224232 pattern: &parser::Node
@@ -244,6 +252,7 @@ export type Scope = struct {
244252 re_exports: &Vector(ReExport)
245253 // Polymorphic instances
246254 polymorphics: &SMap(&Scope)
255+ impls: &Vector(&Impl)
247256}
248257
249258export def print_scope(scope: &Scope) {
@@ -398,7 +407,8 @@ export def enter_scope(parents: &Vector(weak &Scope), module: &toolchain::Module
398407 fields = map::make(type &Value),
399408 implicits = vector::make(type &Value),
400409 underscore_count = 0,
401- is_global = is_global
410+ is_global = is_global,
411+ impls = vector::make(type &Impl)
402412 ] !&Scope
403413 let function_parent = get_function_parent(s)
404414 if function_parent {
@@ -424,7 +434,8 @@ export def enter_function_scope(scope: &Scope, module: &toolchain::Module, is_gl
424434 implicits = vector::make(type &Value),
425435 is_function = true,
426436 is_global = is_global,
427- scope_count = 0
437+ scope_count = 0,
438+ impls = vector::make(type &Impl)
428439 ] !&Scope
429440}
430441
@@ -1941,6 +1952,153 @@ export def create_type(
19411952 return create_type(scope, name_node, share, tpe, Phase::COMPILED, null)
19421953}
19431954
1955+ export def create_impl(
1956+ scope: &Scope, share: parser::ShareMarker, left: &typechecking::TypeRef, right: &typechecking::TypeRef, node: &parser::Node) {
1957+
1958+ let impl = [
1959+ share = share,
1960+ module = scope.module,
1961+ left = left,
1962+ right = right,
1963+ node = node
1964+ ] !&Impl
1965+
1966+ // We resolve all types conditionally here to make sure
1967+ // that the equality check doesn't fail. If one of the types
1968+ // is a forward declared type, it will be resolved later
1969+ // and the equality check looks at the patterns
1970+
1971+ if left.resolve(scope, error_on_fail = false) {
1972+ right.resolve(scope, error_on_fail = false)
1973+ }
1974+
1975+ for var impl in scope.impls {
1976+ if impl.left.resolve(scope, error_on_fail = false) {
1977+ impl.right.resolve(scope, error_on_fail = false)
1978+ }
1979+ if impl.left == left and impl.right == right {
1980+ errors::errorn(node, "Duplicate impl for `", typechecking::generic_to_string(left), "`")
1981+ return
1982+ }
1983+ }
1984+
1985+ scope.impls.push(impl)
1986+ }
1987+
1988+ def all_impl(scope: &Scope) -> &Vector(&Impl) {
1989+ let vec = vector::make(&Impl)
1990+ all_impl(scope, scope.module, vec)
1991+ return vec
1992+ }
1993+
1994+ def all_impl(scope: &Scope, module: &toolchain::Module, all: &Vector(&Impl)) {
1995+ if not scope { return}
1996+ if scope.imports {
1997+ for var imp in scope.imports {
1998+ all_impl(imp.module.scope, module, all)
1999+ }
2000+ }
2001+ for var parent in scope.parents {
2002+ all_impl(parent, module, all)
2003+ }
2004+ for var impl in scope.impls {
2005+ // Don't include impls from other modules, unless they are exported
2006+ if module != scope.module and not (impl.share !int & parser::ShareMarker::EXPORT !int) {
2007+ continue
2008+ }
2009+ all.push(impl)
2010+ }
2011+ }
2012+
2013+
2014+ // This gets called whenever we create new types to
2015+ // generate concrete implementations for polymorphic functions so that
2016+ // the interface call is able to find them.
2017+ export def trigger_impl(scope: &Scope, tpe: &typechecking::Type) {
2018+ let impls = all_impl(scope)
2019+ for var impl in impls {
2020+ let temp_scope = enter_scope(scope)
2021+ // TODO score of 1 is hardcoded, we need to check if the resulting type is actually the same
2022+ if typechecking::convert_type_score(impl.left, tpe, temp_scope) <= 1 {
2023+ // The type matches, now get the right hand side
2024+ let right = impl.right.copy().resolve(temp_scope).resolve()
2025+ // We don't give errors in static context
2026+ if not right {
2027+ if not consteval::is_static {
2028+ errors::errorn(impl.node, "Couldn't resolve implemented type `", typechecking::generic_to_string(impl.right), "`")
2029+ }
2030+ continue
2031+ }
2032+ if right.implementors and right.implementors.contains(tpe.id) {
2033+ continue
2034+ }
2035+ // Check if we have an interface on the right hand side
2036+ if not (right.kind == typechecking::TypeKind::INTERFACE or
2037+ (right.kind == typechecking::TypeKind::REFERENCE and
2038+ right.tpe and right.tpe.resolve().kind == typechecking::TypeKind::INTERFACE)) {
2039+
2040+ errors::errorn(impl.node, "Right hand side of impl must be an interface, got `", debug::type_to_str(right), "`")
2041+ continue
2042+ }
2043+
2044+ // Lookup all functions in interface
2045+ var intf = right
2046+ if right.kind == typechecking::TypeKind::REFERENCE {
2047+ intf = right.tpe.resolve()
2048+ }
2049+
2050+ var cnt = true
2051+ for var member in intf.members {
2052+ let parameter_t = vector::make(typechecking::NamedParameter)
2053+ parameter_t.push([tpe = tpe.id] !typechecking::NamedParameter)
2054+ for var param in member.parameter_t {
2055+ parameter_t.push(param)
2056+ }
2057+ let name_node = parser::make_identifier(member.name)
2058+ let fun = get_function(impl.module.scope, name_node, parameter_t, dry_run = true)
2059+ var res = fun != null
2060+
2061+ if res {
2062+ if fun.fdef.return_t.length != member.return_t.length {
2063+ res = false
2064+ } else {
2065+ let ftpe = fun.fdef.to_type().resolve()
2066+ for var i in 0..fun.fdef.return_t.length {
2067+ if not typechecking::equals(ftpe.return_t(i), member.return_t(i)){
2068+ res = false
2069+ break
2070+ }
2071+ }
2072+ }
2073+ }
2074+
2075+ if not res {
2076+ if not consteval::is_static {
2077+ errors::errorn(impl.node, "Type `", typechecking::type_to_str(tpe), "` doesn't implement member `", member.name, "` of interface `", debug::type_to_str(right), "`")
2078+ }
2079+ cnt = false
2080+ break
2081+ }
2082+ }
2083+
2084+ if not cnt {
2085+ continue
2086+ }
2087+
2088+ if not right.implementors {
2089+ right.implementors = set::make(typechecking::TypeId)
2090+ }
2091+ right.implementors.add(tpe.id)
2092+
2093+ if not tpe.implements {
2094+ tpe.implements = set::make(typechecking::TypeId)
2095+ }
2096+ tpe.implements.add(right.id)
2097+ }
2098+ }
2099+ }
2100+
2101+
19442102export def enter_namespace(scope: &Scope, scope2: &Scope, node: &parser::Node) -> &Value {
19452103
19462104 scope = create_path(scope, node)
0 commit comments