类型系统
本文档描述 KCL 的类型系统,包括:
类型规则
基础定义
S 的所有自由变量都定义在 Γ 中
Γ 是一个变量的类型声明环境(well-formed environment),如:x1:T1, ..., xn:Tn
S 的断言有三种形式:
环境断言 断言表示 Γ 是良构类型 (well-formed type)
良构类型断言 在环境 Γ 下,nat 是类型表达式
Γ⊢nat 类型判断(断言 在环境 Γ 下,E 具有类型 T
Γ⊢E:T 推理规则
表示法
Γ⊢SΓ⊢S1,...,Γ⊢Sn 推理规则中的 u, v, w 用于表示变量,i, j, k 用于表示整数,a, b 用于表示浮点数,s 用于表示字符串,c 代表常量(整数、浮点数、字符串、布尔)的字面值, f 用于表示函数, T, S, U 用于表示类型。
环境规则
Env ⌀
⌀⊢◇ 类型定义
Type Bool
Γ⊢booleanΓ⊢◇ Type Int
Γ⊢integerΓ⊢◇ Type Float
Γ⊢floatΓ⊢◇ Type String
Γ⊢stringΓ⊢◇ Type Literal
Γ⊢literalof(c)c∈{boolean,integer,float,string} Type List
Γ⊢listof(T)Γ⊢T T=Void Type Dict
Γ⊢dictof(Tk=T1,Tv=T2)Γ⊢T1 Γ⊢T2 T1=Void T2=Void Type Struct
Γ⊢structof(K1:T1,...,Kn:Tn)Γ⊢T1 ... Γ⊢Tn Ti=Void K1=Kn Type Union
Γ⊢unionof(T1,...,Tn)Γ⊢T1 ... Γ⊢Tn Ti=Void Type None
Γ⊢NoneΓ⊢◇ Type Undefined
Γ⊢UndefinedΓ⊢◇ Type Void
Γ⊢VoidΓ⊢◇ Type Any
Γ⊢AnyΓ⊢◇ Type Nothing
Γ⊢NothingΓ⊢◇ 类型判断规则
Operand Expr
Exp Truth
Γ⊢true:booleanΓ⊢◇ Γ⊢false:booleanΓ⊢◇ Exp Int
Γ⊢int:integerΓ⊢◇ Exp Flt
Γ⊢flt:floatΓ⊢◇ Exp Str
Γ⊢str:stringΓ⊢◇ Exp None
Γ⊢none:noneΓ⊢◇ Exp Undefined
Γ⊢undefined:undefinedΓ⊢◇ Expr ListExp
Γ⊢[E1,E2,...,En]:listof sup(T1,T2,...,Tn)Γ⊢E1:T1 E2:T2 ... En:Tn Expr ListComp
Γ⊢[E1 for v in E2 if E3]:listof(T1)Γ⊢E1:T1 Γ⊢v:T Γ⊢E2:listof T Γ⊢E3:boolean Expr DictExp
Γ⊢{Ek1:Ev1,...,Ekn:Evn}:dictof(Tk=sup(Tk1,Tk2,...Tkn), Tv=sup(Tv1,Tv2,...,Tvn))Γ⊢Ek1:Tk1 Γ⊢Ev1:Tv1 ... Γ⊢Ekn:TkN Γ⊢Evn:TvN Expr DictComp
Γ⊢{E1:E2 for (v1,v2) in E3 if E4}:dictof(Tk=sup(Trk1,Trk2,...,Trkn),Tv=sup(Trv1,Trv2,...,Trvn))Γ⊢E1:Trki Γ⊢E2:Trvi Γ⊢v1:Tk Γ⊢v2:Tv Γ⊢E3:dictof(Tk, Tv) Γ⊢E4:boolean Expr StructExpr
Γ⊢{K1=E1,...,Kn=En}:structof(K1:T1,...,Kn:Tn)Γ⊢E1:T1 ... Γ⊢En:Tn K1=Kn Literal 类型是基础类型的值类型,Union 类型是类型的组合类型,Void、Any、Nothing 是特殊的类型指代,本身没有直接的值表达式对应关系。
Primary Expr
Expr Index
Γ⊢E[Index]:TΓ⊢E:listof(T) Γ⊢Index:integer Expr Call
Γ⊢E1 (E2):T2Γ⊢E1:T1→T2 Γ⊢E2:T1 Expr List Selector
Γ⊢E.[Index]:TΓ⊢E:listof(T) Γ⊢Index:integer Expr Dict Selector
Γ⊢E.{S1,...,Sn}:dictof(Tk=T1,Tv=T2)Γ⊢E:dictof(Tk=T1,Tv=T2) Γ⊢S1:string ... Γ⊢Sn:string Expr Struct Selector
Γ⊢E.Ki:TiΓ⊢E:structof(K1:T1,...,Kn:Tn) Γ⊢Ki:string Unary Expr
Expr +
Γ⊢ +E:TΓ⊢E:T T∈{integer,float} Expr -
Γ⊢ −E:TΓ⊢E:T T∈{integer,float} Expr ~
Γ⊢ E:integerΓ⊢E:integer Expr not
Γ⊢ not E:booleanΓ⊢E:boolean Binary Expr
算数运算符
Expr op, op ∈ {-, /, %, **, //}
Γ⊢E1 op E2:TΓ⊢E1:T Γ⊢E2:T T∈{integer,float} Expr +
Γ⊢E1 + E2:TΓ⊢E1:T Γ⊢E2:T T∈{integer,float,string,listof(T1)} Expr *
Γ⊢E1 ∗ E2:TΓ⊢E1:T1 Γ⊢E2:T2 (T1==T2∈{integer,float}) or (T1==interger and T2 ∈ {string,listof(T3)}) or (T2==interger and T1 ∈ {string,listof(T3)}) 示例
Expr %
Γ⊢E1 % E2:intergerΓ⊢E1:interger Γ⊢E2:integer 逻辑运算符
Expr op, op ∈ {or, and}
Γ⊢E1 op E2:booleanΓ⊢E1:boolean Γ⊢E2:boolean 示例
Expr and
Γ⊢E1 and E2:booleanΓ⊢E1:boolean Γ⊢E2:boolean 比较运算符
Expr op, op ∈ {==, !=, <, >, <=, >=}
Γ⊢E1 op E2:booleanΓ⊢E1:T Γ⊢E2:T 示例
Expr >
Γ⊢E1 > E2:booleanΓ⊢E1:boolean Γ⊢E2:boolean 位运算符
Expr op, op ∈ {&, ^, ~, <<, >>}
Γ⊢E1 op E2:integerΓ⊢E1:integer Γ⊢E2:integer Expr |
Γ⊢E1 ∣ E2:TΓ⊢E1:T Γ⊢E2:T T∈{integer,listof(T1),dictof(Tk,Tv),structof(K1=T1,...,Kn=Tn)} 成员运算符
Expr op, op ∈ {in, not in}
Γ⊢E1 op E2:boolΓ⊢E1:string Γ⊢E2:T T∈{dictof,structof} Expr op, op ∈ {in, not in}
Γ⊢E1 op E2:boolΓ⊢E1:T Γ⊢E2:listof(S),T⊑S 身份运算符
Expr op ∈ {is, is not}
Γ⊢E1 op E2:boolΓ⊢E1:T Γ⊢E2:T IF Expr
Expr If
Γ⊢if E1 then E2 else E3:TΓ⊢E1:boolean Γ⊢E2:T Γ⊢E3:T Stmt
Stmt If
Γ⊢if E1 then S1 else S2:VoidΓ⊢E1:boolean Γ⊢S1:Void Γ⊢S2:Void Stmt Assign
Γ⊢id:T1 = E:VoidΓ⊢id:T0 Γ⊢T1 Γ⊢E:T2 Type Alias
Γ⊢type id = T1:VoidΓ⊢id:T0 Γ⊢T1 Union
Union 规则
List Union
Γ⊢ listof(unionof(T,S))Γ⊢ listof(T) Γ⊢ listof(S) Dict Union
Γ⊢ dictof(unionof(T1,S1),unionof(T2,S2))Γ⊢ dictof(T1,T2) Γ⊢ dictof(S1,S2) Struct Union
给定两个结构体 structof(K1:T1,...,Kn:Tn),structof(H1:S1,...,Hm:Sn)
定义他们的 union 类型:
structof(J1:U1,...,Jp:Un)=structof(K1:T1,...,Kn:Tn)⋃structof(H1:S1,...,Hm:Sn) 例如:
structof() ⋃ structof(H1:T1,...,Hm:Tn)=structof(H1:T1,...,Hm:Tn) structof(K1:T1,...,Kn:Tn) ⋃ structof(H1:S1,...,Hm:Sn)=structof(K1:T1)::(structof(K2:T2,...,Kn:Tn) ⋃ structof(H1:S1,...,Hm:Sn)) 其中把 "::" 表示把一个对偶加入到一个结构的操作,定义如下:
structof(K1:T1)::structof()=structof(K1:T1) structof(K1:T1)::structof(K1:T1′,...,Kn:Tn)=structof(K1:union_op(T1,T1′),...,Kn:Tn) structof(K1:T1)::structof(K2:T2,...,Kn:Tn)=structof(K2:T2)::structof(K1:T1)::structof(K3:T3,...,Kn:Tn) 基于此,两个 Struct 的 union 定义为:
Γ⊢structof(J1:U1,...,Jp:Un))Γ⊢structof(K1:T1,...,Kn:Tn) Γ⊢structof(H1:S1,...,Hm:Sn) structof(J1:U1,...,Jp:Un)=structof(K1:T1,...,Kn:Tn)⋃structof(H1:S1,...,Hm:Sn) 其中 union_op(T1,T2) 表示对相同 Ki 的不同类型的判断操作:
- 当 T1 与 T2 有偏序关系时, 如果 T1⊑T2 时,返回 T2,否则返回 T1,即取最小上界
- 当 T1 与 T2 不存在偏序关系时,有三种可选的处理逻辑:
- 结构体 union 失败,返回 type_error
- 返回后者的类型,此处为 T2
- 返回类型 unionof(T1,T2)
此处需要根据实际需求选择适当的处理方式。
结构体继承可以看做一种特殊的 union,整体逻辑与 union 相似,但在 union_op(T1,T2) 中对相同 Ki 的不同类型的判断操作如下:
- 当 T1 与 T2 有偏序关系且 T1⊑T2 时,返回 T1,即仅当 T1 是 T2 的下界时以下界 T1 为准
- 否则返回 type_error
通过这样的继承设计可以实现分层的、自下而上逐层收缩的类型定义。
Operation
KCL 支持对结构体属性进行如 p op E
形式的操作。 即对给定结构体 A:structof(K1:T1,...,Kn:Tn), 对结构体中的路径 p
以 E
的值进行指定的操作(如 union,assign,insert 等)。
定义如下更新操作:
A{p op e}:{K1:T1,...,Kn:Tn}∪{p:T}Γ⊢A:structof(K1:T1,...,Kn:Tn) Γ⊢p∈(K1,...,Kn) Γ⊢e:T k=k1,...,k=kn 即对路径 p 进行操作本质上是对两个结构体的一种 union,对同名属性类型 union 时的规则根据情况而定。例如路径 p 是一个可用作字段名的标识符 p=k1,并且结构体 A 中字段名也是 k1,它的类型为 T1,并且表达式 e 的类型也为 T1 ,那么
A{p op e}:{K1:T1,...,Kn:Tn}Γ⊢A:structof(K1:T1,...,Kn:Tn) Γ⊢p=K1 Γ⊢e:T1 k=k1,...,k=kn 注意:
- 此处表达式 e 的类型 T1 同原先同名属性 K1 的具有相同的类型。可根据实际情况需要适当放松,如 e 的类型 ⊑T1 即可。
- 对于多层结构体嵌套的操作,递归的使用以上规则即可。
类型偏序
基础类型
Type T⊑Type Any Type Nothing⊑Type T Type Nothing⊑Type Bool⊑Type Any Type Nothing⊑Type Int⊑Type Any Type Nothing⊑Type Float⊑Type Any Type Int⊑Type Float Type Nothing⊑Type String⊑Type Any Type Nothing⊑Type Literal⊑Type Any Type Nothing⊑Type List⊑Type Any Type Nothing⊑Type Dict⊑Type Any Type Nothing⊑Type Struct⊑Type Any Type Nothing⊑Type None⊑Type Any Type Nothing⊑Type Void⊑Type Any Type Nothing⊑Type Any 字面值类型
Type Literal(Bool)⊑Type Bool Type Literal(Int)⊑Type Int Type Literal(Float)⊑Type Float Type Literal(String)⊑Type String 联合类型
Type X⊑Type Union(X,Y) Type X⊑Type X 示例
Type Bool⊑Type Bool Type Int⊑Type Int Type Float⊑Type Float Type String⊑Type String Type List⊑Type List Type Dict⊑Type Dict Type Struct⊑Type Struct Type Nothing⊑Type Nothing Type Any⊑Type Any Type Union(TypeInt,TypeBool)⊑Type Union(TypeInt,TypeBool) Type X⊑Type Z if Type X⊑Type Y and Type Y⊑ Type Z Type List(T1)⊑Type List(T2) if T1⊑T2 Type Dict(Tk1,Tv1)⊑Type Dict(Tk2,Tv2) if Tk1⊑Tk2 and Tv1⊑Tv1 Type Structure(K1:Ta1,K2:Ta2,...,Kn:Tan)⊑Type Structure(K1:Tb1,K2:Tb2,...,Kn:Tbn) if Ta1⊑Tb1 and Ta2⊑Tb2 and ... and Tan⊑Tbn Type Struct A⊑Type Struct B if A inherits B None
Type None⊑Type X,X∈/{Type Nothing, Type Void} Undefined
Type Undefined⊑Type X,X∈/{Type Nothing, Type Void} 相等性
交换律
Type Union(X,Y)==Type Union(Y,X) 示例
Type Union(Int,Bool)==Type Union(Bool,Int) 结合律
Type Union(Union(X,Y),Z)==Type Union(X,Union(Y,Z)) 示例
Type Union(Union(Int,String),Bool)==Type Union(Int,Union(String,Bool)) 幂等性
Type Union(X,X)==Type X 示例
Type Union(Int,Int)==Type Int 偏序推导
Type Union(X,Y)==Type Y if X⊑Y 示例
假设 Struct A 继承 Struct B
Type Union(A,B)==Type B 幂等性是偏序自反的一个特例
List
Type List(X)==Type List(Y) if X==Y Dict
Type Dict(Tk,Tv)==Type Dict(Sk,Sv) if Tk==Sk and Tv==Sv Struct
Type Struct(K1:T1,K2:T2,...,Kn:Tn)==Type Struct(K1:S1,K2:S2,...,Kn:Sn) if T1==S1 and ... and Tn==Sn 偏序检查
Type X==Type Y if Type X⊑Type Y and Type Y⊑ Type X 基础方法
- sup(t1: T, t2: T) -> T: 根据类型偏序计算两类型 t1, t2 的最小上界。需要动态创建 union type。
- typeEqual(t1: T, t2: T) -> bool: 比较两类型 t1, t2 是否相等。
- typeToString(t: T) -> string: 自顶向下递归解析并转化类型成对应的字符串类型。
Sup Function
- 暂不考虑类型参数,条件类型等特性
- 使用一个有序集合存储 UnionType 的所有类型
- 使用一个全局的 Map 根据 UnionType 的名称存储产生的所有 UnionType
- 根据偏序关系计算类型之间的包含关系
func Sup(types: T[]) -> T {
typeOf(types, removeSubTypes=true)
}
func typeOf(types: T[], removeSubTypes: bool = false) -> T {
assert isNotNullOrEmpty(types)
typeSet: Set[T] = {}
addTypesToTypeSet(typeSet, types)
if removeSubTypes {
removeSubTypes(typeSet)
}
if len(typeSet) == 1 {
return typeSet[0]
}
id := getIdentifierFromTypeSet(typeSet)
unionType := globalUnionTypeMap.get(id)
if !unionType {
unionType = createUnionType(typeSet)
globalUnionTypeMap.set(id, unionType)
}
return unionType
}
func addTypesToTypeSet(typeSet: Set[T], types: T[]) -> void {
for type in types {
addTypeToTypeSet(typeSet, type)
}
}
func addTypeToTypeSet(typeSet: Set[T], type: T) -> void {
if isUnion(type) {
return addTypesToTypeSet(typeSet, toUnionOf(type).types)
}
if !isVoid(type) {
typeSet.add(type)
}
}
func removeSubTypes(types: Set[T]) -> void {
for source in types {
for target in types {
if !typeEqual(source, target) {
if (isPartialOrderRelatedTo(source, target)) {
types.remove(source)
}
}
}
}
}
func isPartialOrderRelatedTo(source: T, target: T) -> bool {
assert isNotNullOrEmpty(source)
assert isNotNullOrEmpty(target)
if isNoneOrUndefined(source) and !isNothing(target) and !isVoid(target) {
return true
}
if isAny(target) {
return true
}
if typeEqual(source, target) {
return true
}
if isUnion(target) and source in target.types {
return true
}
if (isStringLiteral(source) and isString(target)) or \
(isBooleanLiteral(source) and isBool(target)) or \
(isIntLiteral(source) and isInt(target)) or \
(isFloatLiteral(source) and isFloat(target)) {
return true
}
if isInt(source) and isFloat(target) {
return true
}
if isList(source) and isList(target) {
return isPartialOrderRelatedTo(toListOf(source).eleType, toListOf(target).eleType
}
if isDict(source) and isDict(target) {
return isPartialOrderRelatedTo(toDictOf(source).keyType, toDictOf(target).keyType) and isPartialOrderRelatedTo(toDictOf(source).valueType, toDictOf(target).valueType)
}
if isStruct(source) and isStruct(target) {
if isTypeDerivedFrom(source, target) {
return true
}
if len(target.keys) == 0 {
return true
}
if any([key Not in source.keys for key in target.keys]) {
return false
}
for key, sourceType in (source.keys, source.types) {
targetType = getKeyType(target, key) ? getKeyType(target, key) : anyTypeOf()
if !isPartialOrderRelatedTo(sourceType, targetType) {
return false
}
}
return true
}
return false
}
类型检查
类型检查器
类型检查器通过语法制导翻译的方式,自顶向下遍历语法树,并根据上下文有关的定型规则来判定程序构造是否为良类型程序。
类型检查器依赖类型规则,类型环境 Γ 的信息记入符号表。对类型表达式采用抽象语法,如 listof(T)。类型检查失败时产生 type_error,并根据语法上下文产生错误信息。
基础方法
- isUpperBound(t1, t2): supUnify(t1, t2) == t2
- supUnify(t1, t2):
- 对于基础类型,根据偏序关系计算 sup(t1, t2)
- 对于 list、 dict、 Struct, 递归地对其中元素的类型进行 supUnify
- 不存在偏序关系时,返回 Nothing
检查逻辑
Operand Expr
D→id:T
env.addtype(id.entry, T.type)
T→boolean
T→integer
T→float
T→string
T→c, c∈{boolean,integer,float,string}
T→None
T→Undefined
T→ [T1]
T.type = listof (T1.type)
T→{T1:T2}
T.type = dictof (T1.type: T2.type)
T→{N1:T1,N2:T2,...,Nn:Tn}
T.type = structof (N1: T1.type, N2: T2.type, ..., Nn: Tn.type)
E→id
E.type = env.lookup(id.entry)
E→[E1,E2,...,En]
func listExpr(E) {
supe = sup([e.type for e in E]])
E.type = listof(type)
}
E→[E1 for E2 in E3 if E4]
func listComp(E) {
if !typeEqual(E4.type, boolean) {
raise type_error
}
if !isUpperBound(listof(Any), E3.type) {
raise type_error(E)
}
if !isUpperBound(E3.type, E2.type) {
raise type_error(E)
}
E.type = listof(E1.type)
}
E→{Ek1:Ev1,...,Ekn:Evn}
func dictExpr(E) {
supk := sup([e.type for e in E.keys()]])
supv := sup([e.type for e in E.values()]])
E.type = dictof(supk, supv)
}
E→{E1:E2 for (E3,E4) in E5 if E6}
func dictComp(E) {
if !typeEqual(E6.type, boolean) {
raise type_error(E)
}
if !isUpperBound(dictof(Any, Any), E5.type) {
raise type_error(E)
}
if !isUpperBound(E5.type, dictof(E3.type, E4.type)) {
raise type_error(E)
}
E.type = dictof(E1.type, E2.type)
}
E→{Ek1:Ev1,...,Ekn:Evn}
func dictExpr(E) {
supk := sup(Ek1, ..., Ekn)
supv = sup(Ev1, ..., Evn)
E.type = dictof(supk, supv)
}
E→{N1=E1,...,Nn=En}
func structExpr(E) {
Struct = structof()
for n, e in E {
Struct.add(n, e.type)
}
E.type = Struct
}
Primary Expr
E→E1[E2]
func sliceSuffix(E) {
if !isUpperBound(listof(Any), E.E1.type) {
raise type_error(E)
}
if typeEqual(E.E2.type, integer) {
raise type_error(E)
}
E.type = E.E1.type.eleType
}
E→E1(E2)
func callSuffix(E) {
if !typeEqual(E.E1.type, func) {
raise type_error(E)
}
if !isUpperBound(listof(E.E1.arguType), E.E2.type) {
raise type_error(E)
}
E.type = E.E1.returnType
}
Unary Expr
根据每条双目运算符的推理规则推导,以 '+' 为例
E→+E1
func Plus(E) {
if !typeEqual(E.E1.type, [integer, float]) {
raise type_error(E)
}
E.type = E.E1.type
}
Binary Expr
根据每条双目运算符的推理规则推导,以 '%' 为例
E→E1
func Mod(E) {
if !(typeEqual(E.E1.type, [integer, float]) && typeEqual(E.E2.type, [integer, float])) {
raise type_error(E)
}
E.type = E.E1.type
}
IF Binary Expr
E→ifE1 then E2else E3
func ifExpr(E) {
if !typeEqual(E.type, boolean) {
raise type_error(E)
}
if !typeEqual(E_2.type, E_3.type) {
raise type_error(E)
}
E.type = E_2.type
}
Stmt
S→if E then S1 else S2
func ifStmt(S) {
if !typeEqual(S.E.type, boolean) {
raise type_error(E)
}
if !typeEqual(S.S1.type, S.S2.type) {
raise type_error(E)
}
S.type = S.S1.type
}
S→id:T=E
S→id=TE
func assignStmt(S) {
tpe := env.lookup(id.entry)
if tpe != nil && tpe != S.T {
raise type_error(E)
}
if isUpperBound(tpe, E.type) {
raise type_error(E)
}
env.addtype(id.entry, T.type)
}
类型转换
基础定义
通过语法制导翻译的方式,根据运算符特征,对参与运算的值类型进行自动类型转换
转换规则
E→E1 op E2,,op∈{+,−,∗,/,%,∗∗,//}
func binOp(E) {
if E.E1.type == integer and E.E2.type == integer {
E.type = integer
} else if E.E1.type == integer and E.E2.type == float {
E.type = float
} else if E.E1.type == float and E.E2.type == integer {
E.type = float
} else if E.E1.type == float and E.E2.type == float {
E.type = float
}
}
类型推导
基础定义
- 在类型信息不完全的情况下类型规则推导、重建类型
- 自底向上推导并重建数程序中的数据结构类型,如基础类型,list, dict, Struct
基础方法
- typeOf(expr, subst): 输入为表达式和代换规则集合,返回 expr 的类型和新的代换规则集合
- unifier(t1, t2, subst, expr) 用 t1=t2 尝试代换,如果代换成功(未出现且无冲突),则将 t1=t2 加入 subst 并返回 subst。否则报错已出现或有冲突。
推导逻辑
E→id=E1
func assignExpr(E, subst) {
return unifier(E.id.type, E.E_1.type, subst, E)
}
unifier(t1,t2,subst,expr)→subst
func unifier(t1, t2, subst, expr) {
t1 = applySubstToTypeEquation(t1, subst)
t2 = applySubstToTypeEquation(t2, subst)
if t1 == t2 {
return subst
}
if isTypeVar(t1) {
if isNoOccur(t1, t2) {
addTypeEquationToSubst(subst, t1, t2)
return subst
} else {
raise occurrence_violation_error(t1, t2, expr)
}
}
if isTypeVar(t2) {
if isNoOccur(t2, t1) {
addTypeEquationToSubst(subst, t2, t1)
return subst
} else {
raise occurrence_violation_error(t2, t1, expr)
}
}
if isList(t1) and isList(t2) {
return unifier(toListOf(t1).eleType, toListOf(t2).eleType, subst, expr)
}
if isDict(t1) and isDict(t2) {
dict1of := toDictOf(t1)
dict2of := toDictOf(t2)
subst = unifier(dict1of.keyType, dict2of.keyType, subst, expr)
subst = unifier(dict1of.valueType, dict2of.valueType, subst, expr)
return subst
}
if isStruct(t1) and isStruct(t2) {
Struct1of := tostructof(t1)
Struct2of := tostructof(t2)
for key, _ in Struct1of {
subst = unifier(t1[key].type, t2[key].type, subst, expr)
}
return subst
}
raise unification_error(t1, t2, expr)
}
func applySubstToTypeEquation(t, subst) {
// walks through the type t, replacing each type variable by its binding in the substitution
σ. If a variable is Not bound in the substitution, then it is left unchanged.
if isBasicType(t) {
return t
}
if isList(t) {
return listOf(applySubstToTypeEquation(toListOf(t).eleType, subst))
}
if isDict(t) {
dictof := toDictOf(t)
kT := applySubstToTypeEquation(dictof.keyType, subst)
vT := applySubstToTypeEquation(dictof.valueType, subst)
return dictOf(kT, vT)
}
if isStruct(t) {
structof := tostructof(t)
s := structof()
for key, type in Struct1of {
kT := applySubstToTypeEquation(type, subst)
s.add(key, kT)
}
return s
}
if hasTypeVar(t) {
for tvar in t.vars {
if tvar in subst {
*tvar = subst[tvar]
}
}
}
return t
}
func addTypeEquationToSubst(subst, tvar, t) {
// takes the substitution σ and adds the equation tv = t to it
for _, t in subst {
for tvar in t.vars {
tmp := applyOneSubst(tsvar, tvar, t)
*tvar = tmp
}
}
subst.add(tvar, t)
}
func applyOneSubst(t0, tvar, t1) {
// substituting t1 for every occurrence of tv in t0.
if isBasicType(t0) {
return t0
}
if isList(t0) {
return listOf(applyOneSubst(toListOf(t).eleType, tvar, t1))
}
if isDict(t0) {
dictof := toDictOf(t)
kT := applyOneSubst(dictof.keyType, tvar, t1)
vT := applyOneSubst(dictof.valueType, tvar, t1)
return dictOf(kT, vT)
}
if isStruct(t0) {
structof := tostructof(t)
s := structof()
for key, type in Struct1of {
kT := applyOneSubst(type, tvar, t1)
s.add(key, kT)
}
return s
}
if t0 == tvar {
return t1
}
return t0
}
func isNoOccur(tvar, t) {
// No variable bound in the substitution occurs in any of the right-hand sides of the substitution.
if isBasicType(t) {
return true
}
if isList(t) {
return isNoOccur(tvar, toListOf(t).eleType)
}
if isDict(t) {
dictof := toDictOf(t)
return isNoOccur(tvar, dictof.keyType) and isNoOccur(tvar, dictof.valueType)
}
if isStruct(t) {
structof := tostructof(t)
noOccur := true
for _, type in structof {
noOccur = noOccur and isNoOccur(tvar, type)
}
return noOccur
}
return tvar != t
}
正常推导
T : {
a = 1
b = "2"
c = a * 2
d = {
d0 = [a, c]
}
}
x: T = {
a = 10
}
Occurrence Violation Error
Type Unification Error
T : {
a = 1
}
T : {
a = "1"
}
Reference