当前位置:网站首页>Go编译原理系列6(类型检查)
Go编译原理系列6(类型检查)
2022-08-05 10:09:00 【InfoQ】
6. Go编译过程-类型检查
前言
- 常量、类型和函数名及类型验证
- 变量的赋值和初始化
- 计算编译时的常量、将声明与标识符绑定
- 会对一些内置函数进行改写(下边介绍源码时会提到)
- 哈希键值对的类型
- 做特别的语法或语义检查(引用的结构体字段是否是大写可导出的?数组字面量的访问是否超过了其长度?数组的索引是不是正整数?)
类型检查整体概览
var test int
test := 1
Go的编译入口文件:src/cmd/compile/main.go -> gc.Main(archInit)
func Main(archInit func(*Arch)) {
......
lines := parseFiles(flag.Args())//词法分析、语法分析、抽象语法树构建都在这里
......
//开始遍历抽象语法树,对每个结点进行类型检查
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias()) {
xtop[i] = typecheck(n, ctxStmt)
}
}
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias() {
xtop[i] = typecheck(n, ctxStmt)
}
}
......
checkMapKeys()//对哈希中键的类型进行检查
......
}
typechecktypechecktypecheck1func typecheck1(n *Node, top int) (res *Node) {
......
switch n.Op {
// until typecheck is complete, do nothing.
default:
Dump("typecheck", n)
Fatalf("typecheck %v", n.Op)
// names
case OLITERAL:
ok |= ctxExpr
if n.Type == nil && n.Val().Ctype() == CTSTR {
n.Type = types.UntypedString
}
case ONONAME:
ok |= ctxExpr
case ONAME:
......
case OTARRAY:
......
case OTMAP:
......
}
......
}
深入了解类型检查
OAS:赋值语句
// Left = Right or (if Colas=true) Left := Right
// If Colas, then Ninit includes a DCL node for Left.
OAS
typecheckascase OAS:
ok |= ctxStmt
typecheckas(n)
// Code that creates temps does not bother to set defn, so do it here.
if n.Left.Op == ONAME && n.Left.IsAutoTmp() {
n.Left.Name.Defn = n
}
typecheckasfunc typecheckas(n *Node) {
......
if n.Left.Name != nil && n.Left.Name.Defn == n && n.Left.Name.Param.Ntype == nil {
n.Right = defaultlit(n.Right, nil)
n.Left.Type = n.Right.Type
}
......
}
OTARRAY:切片
OTARRAY // []int, [8]int, [N]int or [...]int
case OTARRAY:
ok |= ctxType
r := typecheck(n.Right, ctxType)
if r.Type == nil {
n.Type = nil
return n
}
- []int:直接调用
t = types.NewSlice(r.Type),返回了一个 TSLICE 类型的结构体,元素的类型信息也会存储在结构体中
- [...]int:交由
typecheckcomplit方法处理,
func typecheckcomplit(n *Node) (res *Node) {
......
// Need to handle [...]T arrays specially.
if n.Right.Op == OTARRAY && n.Right.Left != nil && n.Right.Left.Op == ODDD {
n.Right.Right = typecheck(n.Right.Right, ctxType)
if n.Right.Right.Type == nil {
n.Type = nil
return n
}
elemType := n.Right.Right.Type
length := typecheckarraylit(elemType, -1, n.List.Slice(), "array literal")
n.Op = OARRAYLIT
n.Type = types.NewArray(elemType, length)
n.Right = nil
return n
}
......
}
[types.NewArray](https://draveness.me/golang/tree/cmd/compile/internal/types.NewArray)- [6]int:如果在声明切片时,带了数组的大小,则直接调用
[types.NewArray](https://draveness.me/golang/tree/cmd/compile/internal/types.NewArray) 初始化一个存储着数组中元素类型和数组大小的结构体
setTypeNode(n, t)
n.Left = nil
n.Right = nil
checkwidth(t)
OTMAP:map(哈希)
OTMAP // map[string]int
TMAPcase OTMAP:
ok |= ctxType
n.Left = typecheck(n.Left, ctxType)
n.Right = typecheck(n.Right, ctxType)
l := n.Left
r := n.Right
if l.Type == nil || r.Type == nil {
n.Type = nil
return n
}
if l.Type.NotInHeap() {
yyerror("incomplete (or unallocatable) map key not allowed")
}
if r.Type.NotInHeap() {
yyerror("incomplete (or unallocatable) map value not allowed")
}
setTypeNode(n, types.NewMap(l.Type, r.Type))
mapqueue = append(mapqueue, n) // check map keys when all types are settled
n.Left = nil
n.Right = nil
......
func NewMap(k, v *Type) *Type {
t := New(TMAP)
mt := t.MapType()
mt.Key = k
mt.Elem = v
return t
}
func checkMapKeys() {
for _, n := range mapqueue {
k := n.Type.MapType().Key
if !k.Broke() && !IsComparable(k) {
yyerrorl(n.Pos, "invalid map key type %v", k)
}
}
mapqueue = nil
}
OMAKE:make
OMAKE // make(List) (before type checking converts to one of the following)
OMAKECHAN // make(Type, Left) (type is chan)
OMAKEMAP // make(Type, Left) (type is map)
OMAKESLICE // make(Type, Left, Right) (type is slice)
make slice:OMAKESLICE
make map:OMAKEMAP
make chan:OMAKECHAN
case OMAKE:
ok |= ctxExpr
args := n.List.Slice()
......
l := args[0]
l = typecheck(l, ctxType)
t := l.Type
......
i := 1
switch t.Etype {
default:
yyerror("cannot make type %v", t)
n.Type = nil
return n
case TSLICE:
......
n.Left = l
n.Right = r
n.Op = OMAKESLICE
case TMAP:
......
n.Op = OMAKEMAP
case TCHAN:
......
n.Op = OMAKECHAN
}
n.Type = t
- 如果第一个参数是切片类型:获取切片的长度(len)和容量(cap),然后对len和cap进行合法性校验。并且改写了节点的类型
- 如果第一个参数是map类型:获取make的第二个参数,如果没有,则默认设置为0(map的大小)。并且改写节点的类型
- 如果第一个参数是chan类型:获取make的第二个参数,如果没有,则默认设置为0(chan的缓冲区大小)。并且改写节点的类型
总结
参考
- go-ast-book
- 《Go语言底层原理剖析》
- 面向信仰编程-类型检查
边栏推荐
- 5. Deploy the web project to the cloud server
- 5.部署web项目到云服务器
- MySQL之数据视图
- After Keil upgrades to AC6, what changes?
- 什么是CRM决策分析管理?
- 手写柯里化 - toString 理解
- [Android]如何使用RecycleView in Kotlin project
- 为什么sys_class 里显示的很多表的 RELTABLESPACE 值为 0 ?
- Still looking for a network backup resources?Hurry up to collect the following network backup resource search artifact it is worth collecting!
- 阿里顶级架构师多年总结的JVM宝典,哪里不会查哪里!
猜你喜欢

Which big guy has the 11G GI and ojvm patches in April or January 2020, please help?

mysql索引

Complete image segmentation efficiently based on MindSpore and realize Dice!

皕杰报表的下拉框联动

three objects are arranged in a spherical shape around the circumference

STM32+ULN2003驱动28BYJ4步进电机(根据圈数正转、反转)

Jenkins使用手册(2) —— 软件配置

Advanced usage of C language

C语言的高级用法

JS introduction to reverse the recycling business network of learning, simple encryption mobile phone number
随机推荐
5.部署web项目到云服务器
高质量 DeFi 应用构建指南,助力开发者玩转 DeFi Summer
MySQL transactions
Oracle 19.3 restart 环境
2022 Huashu Cup Mathematical Modeling Ideas Analysis and Exchange
IDEA performs the Test operation, resulting in duplicate data when data is inserted
19.服务器端会话技术Session
仿SBUS与串口数据固定转换
项目成本控制如何帮助项目成功?
【MindSpore Easy-Diantong Robot-01】You may have seen many knowledge quiz robots, but this one is a bit different
What is the function of the regular expression replaceFirst() method?
First Decentralized Heist?Loss of nearly 200 million US dollars: analysis of the attack on the cross-chain bridge Nomad
NowCoderTOP35-40——持续更新ing
The century-old Nordic luxury home appliance brand ASKO smart wine cabinet in the three-temperature area presents the Chinese Valentine’s Day, and tastes the love of the delicacy
Jenkins manual (2) - software configuration
第五章:redis持久化,包括rdb和aof两种方式[通俗易懂]
Imitation SBUS fixed with serial data conversion
公众号如何运维?公众号运维专业团队
[Unity] [UGUI] [Display text on the screen]
What is CRM Decision Analysis Management?