类型检查
为了进行类型检查(type checking),编译器要给源程序的每一个组成部分赋予一个类型表达式。然后编译器要确定这些类型表达式是否满足一组逻辑规则。这些规则称为源语言的类型系统。
类型检查具有发现程序中错误的潜能。原则上,如果目标代码在保存元素的同时保存了元素的类型信息,那么任何检查都可以动态地进行。
一个健全(sound)的类型系统可以消除对动态类型错误检查的需要,因为它可以帮助我们静态地确定这些错误不会在目标代码运行的时候发生。
如果编译器可以保证它接受的程序在运行时刻不会发生类型错误,那么该语言的这个实现就被称为强类型的。
类型检查规则
类型检查有两种形式:综合和推导。
类型综合(type synthesis)根据子表达式的类型构造出表达式类型。他要求名字先声明再使用。
类型推导(type inference)根据一个语言结构的使用方式来确定该结构的类型。
类型转换
不同的语言具有不同的类型转换规则。比如Java的转换规则区分了拓宽(widen)和窄化(narrowing)。拓宽转换可以保持原有的信息,而窄化转换可能会丢失信息。
如果类型转换由编译器自动完成,这样的转换称为隐式转换,或称自动类型转换(coercion)。很多语言中自动类型转换仅限于拓宽转换。
如果程序员必须写出某些代码来引发类型转换运算,那么这样的转换就称为显式转换,或称为强制类型转换(cast)。
E -> E1 + E2 {
E.type = max(E1.type, E2.type);//返回拓 宽层次结构中的大者
a1 = widen(E1.addr, E1.type, E.type);//如果E1和E类型不一样就生成类型转换代码并返回新的临时变量,否则直接返回E1.addr
a2 = widen(E2.addr, E2.type, E.type);
E.addr = new Temp();
gen(E.addr '=' a1 '+' a2);//生成加法运算的三地址码
}
运算符和函数重载
依据符号所在上下文的不同,被重载(overloaded)的符号会有不同的含义。如果能够为每次出现确定唯一的含义,该名字的重载问题就得到了解决。
类型推导、多态函数、合一
术语“多态”指的是可以在不同的参数类型上运行的代码片段。本节中我们考虑参数多态(paramtric polymorphism)。
GPT:对于含有类型变量的类型表达式:合一算法这种情况非常有用。例如,合一类型表达式
T
和int
可以通过将类型变量T
替换为int
来成功合一。
GPT:对于不含类型变量的类型表达式:这些表达式和合一比较直接。主要是检查它们是否完全相同。
(详见《编译原理p251-p256》)
(END)