当前位置:网站首页>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()//对哈希中键的类型进行检查
......
}
typecheck
typecheck
typecheck1
func 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
typecheckas
case 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
}
typecheckas
func 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
TMAP
case 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语言底层原理剖析》
- 面向信仰编程-类型检查
边栏推荐
- 【MindSpore易点通机器人-01】你也许见过很多知识问答机器人,但这个有点不一样
- 正则表达式replaceAll()方法具有什么功能呢?
- 攻防世界-PWN-new_easypwn
- ffmpeg drawtext 添加文本水印
- Microservice Technology Stack
- What is the function of the regular expression replaceFirst() method?
- 数据中台建设(十):数据安全管理
- ffmpeg drawtext add text watermark
- 第四章:redis 数组结构的set和一些通用命令「建议收藏」
- IDEA performs the Test operation, resulting in duplicate data when data is inserted
猜你喜欢
hcip BGP 增强实验
JS逆向入门学习之回收商网,手机号码简易加密解析
three.js debugging tool dat.gui use
First Decentralized Heist?Loss of nearly 200 million US dollars: analysis of the attack on the cross-chain bridge Nomad
我们的Web3创业项目,黄了
数据中台建设(十):数据安全管理
多线程(进阶) - 2.5w字总结
Pycharm 常用外部工具
Our Web3 Entrepreneurship Project, Yellow
Analysis and practice of antjian webshell dynamic encrypted connection
随机推荐
Our Web3 Entrepreneurship Project, Yellow
【 temperature warning program DE development 】 event driven model instance
第五章:activiti流程分流判断,判断走不同的任务节点
创建一个 Dapp,为什么要选择波卡?
PHP operation mangoDb
QSS 选择器
egg框架使用(二)
Why are RELTABLESPACE values 0 for many tables displayed in sys_class?
Complete image segmentation efficiently based on MindSpore and realize Dice!
JS introduction to reverse the recycling business network of learning, simple encryption mobile phone number
正则表达式replaceAll()方法具有什么功能呢?
three.js debugging tool dat.gui use
Tanabata romantic date without overtime, RPA robot helps you get the job done
three物体围绕一周呈球形排列
多线程(进阶) - 2.5w字总结
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
无题七
19. Server-side session technology Session
第六章:activiti流程分流判断之排它网关和并行网关
Egg framework usage (2)