《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,如何计算表达式的类型
下面的表格说明了类型计算规则。
| Subexpression | Result Type |
| true,false | boolean |
| !«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<j,我们可以进行从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如图:

每个节点都知道自己的求值类型,提升类型。
具体的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;
}
《Language Implementation Patterns》之 强类型规则的更多相关文章
- 《Language Implementation Patterns》之 解释器
前面讲述了如何验证语句,这章讲述如何构建一个解释器来执行语句,解释器有两种,高级解释器直接执行语句源码或AST这样的中间结构,低级解释器执行执行字节码(更接近机器指令的形式). 高级解释器比较适合DS ...
- 《Language Implementation Patterns》之 数据聚合符号表
本章学习一种新的作用域,叫做数据聚合作用域(data aggregate scope),和其他作用域一样包含符号,并在scope tree里面占据一个位置. 区别在于:作用域之外的代码能够通过一种特殊 ...
- 《Language Implementation Patterns》之访问&重写语法树
每个编程的人都学习过树遍历算法,但是AST的遍历并不是开始想象的那么简单.有几个因素会影响遍历算法:1)是否拥有节点的源码:2)是否子节点的访问方式是统一的:3)ast是homogeneous或het ...
- 《Language Implementation Patterns》之 构建语法树
如果要解释执行或转换一段语言,那么就无法在识别语法规则的同时达到目标,只有那些简单的,比如将wiki markup转换成html的功能,可以通过一遍解析来完成,这种应用叫做 syntax-direct ...
- 《Language Implementation Patterns》之 增强解析模式
上一章节讲述了基本的语言解析模式,LL(k)足以应付大多数的任务,但是对一些复杂的语言仍然显得不足,已付出更多的复杂度.和运行时效率为代价,我们可以得到能力更强的Parser. Pattern 5 : ...
- 《Language Implementation Patterns》之 语言翻译器
语言翻译器可以从一种计算机语言翻译成另外一种语言,比如一种DSL的标量乘法axb翻译成java就变成a*b:如果DSL里面有矩阵运算,就需要翻译成for循环.翻译器需要完全理解输入语言的所有结构,并选 ...
- 《Language Implementation Patterns》之 符号表
前面的章节我们学会了如何解析语言.构建AST,如何访问重写AST,有了这些基础,我们可以开始进行"语义分析"了. 在分析语义的一个基本方面是要追踪"符号",符号 ...
- Saga的实现模式——进化(Saga implementation patterns – variations)
在之前的几个博客中,我主要讲了两个saga的实现模式: 基于command的控制者模式 基于事件的观察者模式 当然,这些都不是实现saga的唯一方式.我们甚至可以将这些结合起来. 发布者——收集者 回 ...
- Saga的实现模式——观察者(Saga implementation patterns – Observer)
https://lostechies.com/jimmybogard/2013/03/11/saga-implementation-patterns-observer/ 侵删. NServiceBus ...
随机推荐
- div里面的图片垂直居中
外面一个div, 里面是一张大小不固定的图片, 或者span,div都行, 要实现里面元素水平垂直居中对齐 其实有很多实现的方法, 比如用js去计算每一个子元素的高度, 通过js去动态设置magin值 ...
- 护航者,腾讯云: 2017年度游戏行业DDoS态势报告—回溯与前瞻
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯游戏云 前言 自14年开始,全球DDoS攻击持续爆发,攻击峰值不断创记录.2017年,这种依靠超大流量不断冲击服务器和带宽造成业务 ...
- WRT 版本说明
std_generic 标准通用版nokaid 是不带XBOX支持的(Kai代表连接游戏平台到网络上.)virtual** 表示支持虚拟专用网络的版本VOIP 带VOIP表示支持网络电话的版本.meg ...
- Keras官方中文文档:Keras安装和配置指南(Linux)
关于计算机的硬件配置说明 推荐配置 如果您是高校学生或者高级研究人员,并且实验室或者个人资金充沛,建议您采用如下配置: 主板:X299型号或Z270型号 CPU: i7-6950X或i7-7700K ...
- 凸包--Graham扫描法
一直听大佬们说:凸包.凸包.凸包 一直不会..... 然后.... 今天考试,考了一道计算几何的简单题.... 这,,,还是学一下吧.. 然后考试现场学习一下凸包算法. 先理解一下凸包是啥东西. 看看 ...
- 【BZOJ1008】【HNOI2008】越狱(组合数学)
题面 题目描述 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 输入输出格式 ...
- 【THUWC 2017】在美妙的数学王国中畅游
数学王国里有n座城市,每座城市有三个参数\(f\),\(a\),\(b\),一个智商为\(x\)的人经过一座城市的获益\(f(x)\)是 若\(f=1\),则\(f(x)=\sin(ax+b)\): ...
- mybatise插入返回主键ID
之前遇到过一次解决了,结果这次又搞了半天,在这里记录一下吧. <insert id="insertUser" useGeneratedKeys="true" ...
- JavaScript方面的书籍
我要向大家推荐两本js方面的书: <JavaScript权威指南> <JavaScript高级程序设计>适合想在js方面有所提高的开发人员 我们读书是为了什么? 有的人可能是兴 ...
- 2018 年 3 月 iOS 面试总结(上市公司,BAT)
序言: 今年2月中下旬因为个人原因,换了一份工作,3月初期间面试了有3,4家,基本都是D轮或者刚刚上市的公司,也有上榜的BAT,也从他们的面试笔试中看到了自己的一些不足,于是就想写出来和大家分享一下, ...