首页 > 编程语言 >程序语言中的类型检查

程序语言中的类型检查

时间:2022-11-14 18:23:16浏览次数:26  
标签:检查 ty ast param 程序语言 类型 Check

本文节选自https://mp.weixin.qq.com/s/wSRQ8QV4aS1cRDFAsLaijw

类型系统的根本目的是防止程序运行过程中出现执行错误,这个非正式的声明激发了对类型系统的研究, 在程序的执行过程中,一个程序变量可以承担一定的数值(数据范围),这种范围的上限被称之为该变量的类型。

什么是类型检查:

类型检查位于编译流程中的语义分析中, 下面是关于整个编译流程:

image

类型检查的主要作用就是找到程序中的类型错误, 我们来看两种简单而又典型的类型错误:

  1. 不兼容赋值:这个变量已经声明了int类型, 你确赋值上了bool类型
  2. 不兼容函数调用:在函数调用的时候, 形式参数和实参类型不匹配。
var a: i32 = true;

在swift中: 三元表达式的两个分支分别创建了 C 和 D 的实例。这里编译器也会报错,说 C 和 D 类型不匹配,mismatching。这是因为编译器无法找到 C 和 D 的公共父类型,即编译器尝试将 C 和 D 的所有父类找出来,发现它们没有交集,所以说没有公共父类型。(不过这样一类问题其实是通过类型推导发现的)。

class C {}
class D {}
let x = true ? C() : D()

类型推导:

类型推导找错误类型的方法是去看程序片能否有一个类型, 这个类型是不是事先标注好的, 除此之外,类型推导更大的好处是
可以让程序编码更加高效,比如类型推导可以省掉大量无聊的类型注解 type annotations,让程序员可以聚焦在代码的业务逻辑上;比如类型推导还可以友好地掩盖掉像泛型 generics 或者多态 polymorphisms 这样的类型复杂性。

const a = 12;
var b = a;

fn id(comptime T: type, a: T) T {
	return a;
}

编写一个类型检查器:

类型检查器一般是采取递归下降的, 我们首先创建一个Check: (AST, Type) -> Bool, 这个函数接收两个参数, 第一个参数是抽象语法树AST。

递归处理这棵AST树,先递归子树, 后递归右边的树, 然后取与

a <: b表示a是b的一个子类型subtype

Check :(AST, Type) -> Bool
check (ast, ty) = case ast of pattern match

将加法的左右子树分别绑定到新的变量 l 和 r, 分别递归检查左边的子树和右边的子树,检查的目标类型仍然是ty, 分别递归检查左边的子树和右边的子树,检查的目标类型仍然是ty

Check(ast, ty) =
	Add(l, r) ---->check(l, ty) and check(r, ty)

在刚才的例子中, 我们遇到了字面量, 那么我们可以检查字面量的类型是否为目标类型的子类型

Check(ast, ty) = case ast of pattern match
	Lit(n) ----> typeOf(n) <: ty

函数定义类型检查

接下来, 我们介绍两类比较有意思,即函数定义和函数调用时候的类型检查,先看看函数定义,如果我们的语法树是一个函数定义的节点,那么我们可以分别将函数名称,函数参数,函数体分别绑定到f, param, body上,

Check(ast, ty) =
	-->function definition
	FunAbs(f, param, body)

接下来我们来做类型检查,因为我们在做函数定义时候, 形参名pName后会跟上形参类型Pty,即fun(pname: Pty)
因此我们可以进一步用模式匹配将形参节点

Check(ast, ty) =
	FunAbs(f, param, body) 
	let Param(pName, Pty) = param

第二部我们将输入的目标类型也通过模式匹配来解构:这个目标类型一定要有一个函数类型才可以, 否则报错,那么函数类型可以解构为参数类型和返回类型。

Check(ast, ty) =
	FunAbs(f, param, body) 
	let Param(pName, Pty) = param
	Let FunTy(parTy, retTy) = ty

基于前述步骤解构出来的数据,我们可以用目标类型解构出的返回类型 retTy 来与函数体的类型 body 做检查,递归地检查函数体是否是 retTy 的子类型。此外,我们还需要检查函数声明处的形参类型 pTy,与目标类型解构出来的形参类型 parTy 是否形成了有效的子类型关系 (后面会展开解释什么是有效的子类型关系)

Check (ast, ty) =
  -- function definitions
  FunAbs(f, param, body) --->
    -- pattern match fun(pName : pTy)
    let Param(pName, pTy) = param
    let FunTy(parTy, retTy) = ty
    parTy <: pTy && Check(body, retTy) -- allow subtyping

类型检查的环境

标签:检查,ty,ast,param,程序语言,类型,Check
From: https://www.cnblogs.com/zhengel/p/16889913.html

相关文章

  • ts keys类型枚举
    //从DataView类型中取出keytypeget_set=keyofOmit<DataView,"buffer"|"byteLength"|"byteOffset">;typeFilterNotStartingWith<Set,Needleextendsstrin......
  • 5.golang变量的数据类型
    1.基本数据类型数值型 a.整数类型              A.各整数类型分“有符号和无符号,intun......
  • Arcgis mdb中的要素字段类型为浮点型,但是数据导入到SDE中则为双精度,导致符号化文件没
     Mdb中的要素数据字段类型为浮点型,并进行符号化之后,数据导入到SDE中,但是导入之后的要素字段类型为双精度,导致符号化文件不起作用,因为字段类型的问题,导致字段的数据值发生......
  • Canal安装配置(消息队列类型:RabbitMQ)
    1.Mysql配置canal支持源端MySQL版本包括5.1.x,5.5.x,5.6.x,5.7.x,8.0.x1.1.查看mysqlbinlog是否开启:SHOWVARIABLESLIKE'log_bin' ON标识开启,如果m......
  • SQL numeric数据类型
    作用:存储小数,但是和编程语言的float等不同,即使数据是3.00,存储时也会存储两位小数点后的数字。float类型当你给定的数据是整数的时候,那么它就以整数给你处理。0.00而实......
  • python3-基础篇-05-数据类型及类型转换
     一、数据类型python的数据类型分别有以下几类类型python3 python2说明Number(数字)int(整型)、float(浮点型)、complex(复数)lfloatong(长整型)在python3里,不区分整型与长整型,统......
  • python字典类型
    什么是字典字典是由多个键(key)及其对应的值(value)所组成的一种数据类型a=dict()a={}person={'name':'qjb','age':33}字典支持的数据类型key支持字符串......
  • 数据类型的转换
    在写程序时,我们经常会定义整型,浮点型,或者双精度型。在c语言中,经常会有输入一个整数,输出一个小数的情况。这时候我常用的有两种方法。一、在运算的表达式中,对整型的数据*1.......
  • JavaScriptの类型
    前言此篇小结来源与《你不知道的JavaScript》和《JavaScript高级程序设计》的结合??或许是的,龟速总结中...七种内置类型nullundefinedbooleannumberstringobjectsy......
  • C/C++中声明指针变量时星号是靠近变量名还是靠近数据类型?
    摘自<<C和指针>>3.23  int*a;int*a;两者意思相同且后者看上去更为清楚:a被声明为类型为int*的指针.但是,这并不是一个好技巧,原因如下:int*b,c,d;人们很......