主页

索引

模块索引

搜索页面

语义分析

类型系统

类型系统的设计有很多需要取舍和权衡的方面,比如:

1. 面向对象的拥护者希望所有的类型都是对象,而重视数据计算性能的人认为应该支持非对象化的基础数据类型
2. 你想把字符串作为原生数据类型,还是像 Java 那样只是一个普通的类
3. 是静态类型语言好还是动态类型语言好

根据类型检查是在编译期还是在运行期进行的,我们可以把计算机语言分为两类:

1. 静态类型语言(全部或者几乎全部的类型检查是在编译期进行的)
    因为编译期做了类型检查,所以程序错误较少,运行期不用再检查类型,性能更高。
    像 C、Java 和 Go 语言,在编译时就对类型做很多处理,包括:
      检查类型是否匹配,以及进行缺省的类型转换
    大大降低了程序出错的可能性,还能让程序运行效率更高,因为不需要在运行时再去做类型检查和转换。
2. 动态类型语言(类型的检查是在运行期进行的)
    静态语言太严格,还要一遍遍编译,编程效率低,用动态类型语言方便进行快速开发。
    JavaScript、Python、PHP 等都是动态类型的。

目前的趋势:

1. 某些动态类型语言在想办法增加一些机制,在编译期就能做类型检查
  比如用 TypeScript 代替 JavaScript 编写程序,做完检查后再输出成 JavaScript
2. 某些静态语言呢,却又发明出一些办法,部分地绕过类型检查,从而提供动态类型语言的灵活性。

跟静态类型和动态类型概念相关联的,还有强类型和弱类型:

1. 强类型语言中,变量的类型一旦声明就不能改变
2. 弱类型语言中,变量类型在运行期时可以改变
二者的本质区别是:
  强类型语言不允许违法操作,因为能够被检查出来
  弱类型语言则从机制上就无法禁止违法操作,所以是不安全的

JavaScript是动态类型,也是弱类型;python是动态类型,却是强类型。

备注

静态类型和动态类型说的是什么时候检查的问题,强类型和弱类型说的是就算检查,也检查不出来,或者没法检查的问题

1. 类型检查: Type Checking
2. 类型推导: Type Inference
3. 类型转换: Type Conversion

类型推导:

S 属性(Synthesized Attribute),也就是综合属性
I 属性(Inherited Attribute),也就是继承属性
L 属性

类型检查主要出现在几个场景中:

1. 赋值语句(检查赋值操作左边和右边的类型是否匹配)。
2. 变量声明语句(因为变量声明语句中也会有初始化部分,所以也需要类型匹配)。
3. 函数传参(调用函数的时候,传入的参数要符合形参的要求)。
4. 函数返回值(从函数中返回一个值的时候,要符合函数返回值的规定)。

类型检查还有一个特点:
  以赋值语句为例,
  左边的类型,是 I 属性,是从声明中得到的;
  右边的类型是 S 属性,是自下而上综合出来的
1. 左值(L-value)  地址
2. 右值(R-value)  值

语义分析过程拆成了好几个任务,对 AST 做了多次遍历:

1. 类型和作用域解析(TypeAndScopeScanner.java)
2. 类型的消解(TypeResolver.java)
3. 引用的消解和 S 属性的类型的推导(RefResolver.java)
4. 做类型检查(TypeChecker.java)
5. 做一些语义合法性的检查(SematicValidator.java)

主页

索引

模块索引

搜索页面