《Language Implementation Patterns》之 强类型规则

语句的语义取决于其语法结构和相关符号;前者说明了了要“做什么”,后者说明了操作“什么对象”。所以即使语法结构正确的,如果被操作的对象不合法,语句也是不合法的。语言一般有很多语义规则,有些是运行时的(dynamic semantics),比如“不能除以零”、“不能越界访问数组”;有些是编译时的(static semantics)。运行时&编译时的界限取决于具体的语言,python是动态类型的语言,所有的值编译时都不会指定类型,解释器在运行时检查类型和执行语义规则;C++则是另一个极端,所有的值必须有静态的类型,运行时不做检查;java既有静态类型检查,又在运行时检查类型。无论动态的或静态的类型检查,只要能阻止不相容的类型操作,语言就是“类型安全”的。

本章讲述了如何实施静态类型规则,将会讨论一下几种模式:

  • Pattern 20 Computing Static Expression Types,保证类型安全的第一步是计算表达式的类型;
  • Pattern 21 Automatic Type Promotion, 将操作数的类型提升至相同或相容的类型;
  • Pattern 22 Enforcing Static Type Safety,检查类型相容性,保证类型安全;
  • Pattern 23 Enforcing Polymorphic Type Safety, 面向对象类型语言里面的对象类型相容,多态的引用类型;
    下面分别讲述这些模式,以类c语言的规则为样例。

Pattern 20 Computing Static Expression Types

展示了在显示声明类型的语言,比如C,如何计算表达式的类型
下面的表格说明了类型计算规则。

SubexpressionResult Type
true,falseboolean
!«expr »boolean
f(«args»)函数f的返回类型
«expr» bop «expr»bop代表二元运算符,因为两侧的操作数的类型是一致的,所以可以选取左侧操作数的类型为表达式类型
«expr» relop «expr»boolean,relop是代表关系操作符

实现
假设我们已经构建了AST,和scope tree,进行类型计算就是另一轮AST遍历,可以通过Tree Pattern Matcher技术来寻找表达式节点并计算类型。
具体的实现代码请参考原书。

Pattern 21 Automatic Type Promotion

描述了如何自动、安全地提升数学运算操作数的类型
类型提升将单个运算符的所有操作数提升至相同类型或相容类型,这本质上是CPU对操作数的要求。编程语言能够自动地转换类型,只要“转换“不丢失信息;比如4可以安全地转换成4.0,而4.5不能转换成4;这种安全的类型转换被称之为”类型提升”,因为它拓宽了类型。
这里有一个简单的方式描述类型提升规则;首先将类型按最“窄”到最“宽”进行排序,然后如果i&ltj,我们可以进行从TYPEi到TYPEj的提升。

为了实现类型提升,需要两个函数,第一个是根据运算符和运算数类型返回结果类型;第二个从运算符和目标类型判断是否需要对操作数执行类型提升。

resultType(type1, op, type2)
resultType(char, "<", int) == boolean
resultType(char, "+", int) == int
resultType(boolean, "<", boolean) == void

promoteFromTo(type, op, destination-type)
promoteFromTo(char, "+", int) == int
promoteFromTo(int, "+", int) == null

结果void意味着该表达式不合法,null意味着不需要类型转换。按这个规则,表达式’a’+3+4.2的类型提升可以表示为(float)((int)’a’+3)+4.2,AST如图:
042147320818846.png
每个节点都知道自己的求值类型,提升类型。
具体的java实现代码,请参考原书。

Pattern 22 Enforcing Static Type Safety

通过静态检查,发现表达式或语句里面类型不相容的类型
概括起来,类型相容包含两个方面:

  • 对操作数类型,操作符是有定义的,即resultType(operandtype1, op, operandtype2) != void;
  • 如果我们需要一个类型T的值,那么提供的值必须是T或可以被提升为T。

在Pattern 21的基础上增加类型检查不是困难,只要出现void都意味着类型不相容;对于点操作符,函数调用,return语句等需要特殊处理。
具体的实现代码,请参考原书。

Pattern 23 Enforcing Polymorphic Type Safety

检查对象引用赋值的类型相容性
对象类型引用赋值的相容性判断如下:

public class PointerType extends Symbol implements Type {
    public boolean canAssignTo(Type destType) {
        // if not a pointer, return false
        if ( !(destType instanceof PointerType) ) return false;
        // What type is the target pointing at?
        Type destTargetType = ((PointerType)destType).targetType;
        Type srcTargetType = this.targetType;
        // if this and target are object pointers, check polymorphism
        if ( destTargetType instanceof ClassSymbol &&
             this.targetType instanceof ClassSymbol )
        {
            ClassSymbol thisClass   = (ClassSymbol)srcTargetType;
            ClassSymbol targetClass = (ClassSymbol)destTargetType;
            // Finally!  Here it is: the polymorphic type check :)
            return thisClass.isInstanceof(targetClass);
        }
        // not comparing object pointers; types we point at must be the same
        // For example: int *p; int *q; p = q;
        return srcTargetType == destTargetType;
    }
}
/** Return true if 'ancestor' is this class or above in hierarchy */
public boolean isInstanceof(ClassSymbol ancestor) { 
    ClassSymbol t = this;
    while ( t!=null ) {
        if ( t == ancestor ) return true;
        t = t.superClass;
    }
    return false; 
}

转载于:https://www.cnblogs.com/longhuihu/p/4006521.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值