We have a runtime type-checker that is incomplete - it passes when we expect a TList<Int> and we have a DList with non-Ints in it.
At one point, our type-checker was recursive in that it would look at all values within structures such as lists, to ensure types match, but this recursive nature was very slow, so we gutted it.
Recent efforts have been made to do much of this type-checking upon construction, such that:
Dval
cases contain “ValueTypes” corresponding to the types of data inside
[1]
represented by | DList of items: List<Dval>
would have simply been DList([DInt 1])
DList
definition to | DList of ValueType * items: List<Dval>
, and the Dval of [1]
is now DList(ValueType.Known KnownType.KTInt, [DInt 1])
In most places throughout our codebase, it’s clear what the ValueType(s) of a Dval should be, and we can
DList(VT.int, [DInt 1; DInt 2])
, if we call the function Builtin.List.filter
(with any lambda), we know the output will be a List of the same internal typeMath.asin
will always return an Option of a Float — so we know the Dval should be roughly DEnum("Option", [VT.float], ...)
In other cases, we determine the appropriate ValueTypes dynamically, and fail if attempts are made at creating invalid/inconsistent Dvals
EList([EInt 1; EInt 2])
(e.g. in let x = [1; 2]
), we can dynamically determine that this should be a DList of VT.intEList([EInt 1; EString "two"])
(e.g. in let x = [1; "two"]
), we should error, and let the user know they can’t have a list of inconsistently-typed dataWe are currently pretty close to completing this effort, but some problems remain: