Skip to content

Commit

Permalink
interfaces: actually check interfaces!
Browse files Browse the repository at this point in the history
  • Loading branch information
hishamhm committed Jan 23, 2024
1 parent 2e83118 commit fd5bcab
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 29 deletions.
43 changes: 31 additions & 12 deletions tl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1845,6 +1845,9 @@ local table_types = {









Expand Down Expand Up @@ -6844,7 +6847,7 @@ tl.type_check = function(ast, opts)
seen[orig_t] = rt
return rt, false
end
same = false
all_same = false
t = rt
end
end
Expand Down Expand Up @@ -6980,7 +6983,7 @@ tl.type_check = function(ast, opts)
end
end

copy.typeid = same and orig_t.typeid or new_typeid()
copy.typeid = same and t.typeid or new_typeid()
return copy, same and all_same
end

Expand Down Expand Up @@ -7506,10 +7509,16 @@ tl.type_check = function(ast, opts)
end

local function resolve_decl_into_nominal(t, found)
local resolved = match_typevals(t, found.def)
if not resolved then
error_at(t, table.concat(t.names, ".") .. " cannot be resolved in scope")
return INVALID
local def = found.def
local resolved
if def.typename == "record" or def.typename == "function" then
resolved = match_typevals(t, def)
if not resolved then
error_at(t, table.concat(t.names, ".") .. " cannot be resolved in scope")
return INVALID
end
else
resolved = def
end

if not t.filename then
Expand Down Expand Up @@ -7976,6 +7985,11 @@ tl.type_check = function(ast, opts)
["record"] = {
["record"] = eqtype_record,
},
["interface"] = {
["interface"] = function(a, b)
return a.typeid == b.typeid
end,
},
["function"] = {
["function"] = function(a, b)
local argdelta = a.is_method and 1 or 0
Expand Down Expand Up @@ -8248,7 +8262,7 @@ a.types[i], b.types[i]), }
["record"] = function(a, b)
local def = a.def
if def.fields then
return subtype_record(a.def, b)
return subtype_record(def, b)
end
end,
},
Expand Down Expand Up @@ -9406,9 +9420,9 @@ a.types[i], b.types[i]), }
old.meta_fields = nil

edit_type(old, "map")
assert(old.typename == "map")
old.keys = STRING
old.values = values
local map = old
map.keys = STRING
map.values = values
elseif old.typename == "union" then
edit_type(old, "union")
table.insert(old.types, drop_constant_value(new))
Expand Down Expand Up @@ -9508,7 +9522,12 @@ a.types[i], b.types[i]), }
local def = found.def
if def.fields and def.fields[exp.e2.tk] then
table.insert(t.names, exp.e2.tk)
t.found = def.fields[exp.e2.tk]
local ft = def.fields[exp.e2.tk]
if type(ft) == "table" then
t.found = ft
else
return nil
end
end
end
end
Expand Down Expand Up @@ -11629,7 +11648,7 @@ expand_type(node, values, elements) })

local t = types_op[ra.typename]

if not t then
if not t and ra.fields then
t = find_in_interface_list(ra, function(ty)
return types_op[ty.typename]
end)
Expand Down
53 changes: 36 additions & 17 deletions tl.tl
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,8 @@ local record StringType
literal: string
end

local type TypeType = TypeAliasType | TypeDeclType

local record TypeDeclType
is Type
where self.typename == "typedecl"
Expand Down Expand Up @@ -1611,6 +1613,7 @@ local record UnresolvedType
end

local interface HasTypeArgs
is Type
where self.typeargs

typeargs: {TypeArgType}
Expand All @@ -1626,7 +1629,7 @@ local record NominalType

names: {string}
typevals: {Type}
found: Type -- type is found but typeargs are not resolved
found: TypeType -- type is found but typeargs are not resolved
resolved: Type -- type is found and typeargs are resolved
end

Expand Down Expand Up @@ -1990,7 +1993,7 @@ local record Node
exps: Node

-- newtype
newtype: TypeAliasType | TypeDeclType
newtype: TypeType
elide_type: boolean

-- expressions
Expand Down Expand Up @@ -6844,7 +6847,7 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
seen[orig_t] = rt
return rt, false
end
same = false
all_same = false
t = rt
end
end
Expand Down Expand Up @@ -6980,7 +6983,7 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
end
end

copy.typeid = same and orig_t.typeid or new_typeid()
copy.typeid = same and t.typeid or new_typeid()
return copy, same and all_same
end

Expand Down Expand Up @@ -7506,10 +7509,16 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
end

local function resolve_decl_into_nominal(t: NominalType, found: TypeDeclType): Type
local resolved = match_typevals(t, found.def)
if not resolved then
error_at(t, table.concat(t.names, ".") .. " cannot be resolved in scope")
return INVALID
local def = found.def
local resolved: Type
if def is RecordType or def is FunctionType then
resolved = match_typevals(t, def)
if not resolved then
error_at(t, table.concat(t.names, ".") .. " cannot be resolved in scope")
return INVALID
end
else
resolved = def
end

if not t.filename then
Expand Down Expand Up @@ -7976,6 +7985,11 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
["record"] = {
["record"] = eqtype_record,
},
["interface"] = {
["interface"] = function(a: InterfaceType, b: InterfaceType): boolean, {Error}
return a.typeid == b.typeid
end,
},
["function"] = {
["function"] = function(a: FunctionType, b: FunctionType): boolean, {Error}
local argdelta = a.is_method and 1 or 0
Expand Down Expand Up @@ -8070,7 +8084,7 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
end,
},
["poly"] = {
["*"] = function(a: Type, b: Type): boolean, {Error} -- ∃ t ∈ a, t <: b
["*"] = function(a: PolyType, b: Type): boolean, {Error} -- ∃ t ∈ a, t <: b
if exists_supertype_in(b, a) then -- ───────────────
return true -- a poly <: b
end
Expand Down Expand Up @@ -8121,7 +8135,7 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
["number"] = compare_true,
},
["interface"] = {
["interface"] = function(a: Type, b: Type): boolean, {Error}
["interface"] = function(a: InterfaceType, b: InterfaceType): boolean, {Error}
if find_in_interface_list(a, function(t: Type): boolean return (is_a(t, b)) end) then
return true
end
Expand Down Expand Up @@ -8248,7 +8262,7 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
["record"] = function(a: TypeDeclType, b: RecordType): boolean, {Error}
local def = a.def
if def is RecordLikeType then
return subtype_record(a.def, b) -- record as prototype
return subtype_record(def, b) -- record as prototype
end
end,
},
Expand Down Expand Up @@ -9406,9 +9420,9 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
old.meta_fields = nil

edit_type(old, "map")
assert(old is MapType)
old.keys = STRING
old.values = values
local map = old as MapType
map.keys = STRING
map.values = values
elseif old is UnionType then
edit_type(old, "union")
table.insert(old.types, drop_constant_value(new))
Expand Down Expand Up @@ -9508,7 +9522,12 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
local def = found.def
if def is RecordLikeType and def.fields[exp.e2.tk] then
table.insert(t.names, exp.e2.tk)
t.found = def.fields[exp.e2.tk]
local ft = def.fields[exp.e2.tk]
if ft is TypeType then
t.found = ft
else
return nil
end
end
end
end
Expand Down Expand Up @@ -11629,7 +11648,7 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string

local t = types_op[ra.typename]

if not t then
if not t and ra is RecordLikeType then
t = find_in_interface_list(ra, function(ty: Type): Type
return types_op[ty.typename]
end)
Expand Down Expand Up @@ -11952,7 +11971,7 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
end,
},
["record"] = {
before = function(typ: Type)
before = function(typ: RecordType)
begin_scope()
add_var(nil, "@self", type_at(typ, a_typedecl(typ)))

Expand Down

0 comments on commit fd5bcab

Please sign in to comment.