当前位置:网站首页>Go compilation principle series 6 (type checking)
Go compilation principle series 6 (type checking)
2022-08-05 10:17:00 【InfoQ】
6. Go编译过程-类型检查
前言
- 常量、Type and function names and type validation
- 变量的赋值和初始化
- Computes compile-time constants、Bind declarations to identifiers
- Some built-in functions will be rewritten(It will be mentioned when the source code is introduced below)
- 哈希键值对的类型
- Do special syntactic or semantic checks(引用的结构体字段是否是大写可导出的?数组字面量的访问是否超过了其长度?数组的索引是不是正整数?)
Overall overview of type checking
var test int
test := 1
GoCompile entry file:src/cmd/compile/main.go -> gc.Main(archInit)
func Main(archInit func(*Arch)) {
......
lines := parseFiles(flag.Args())//词法分析、语法分析、The abstract syntax tree construction is all here
......
//Start traversing the abstract syntax tree,Type checking for each node
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()//Check the type of the keys in the hash
......
}
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:
......
}
......
}
Learn more about type checking
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
类型的结构体,The element's type information is also stored in the structure
- [...]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:If when declaring slice,with the size of the array,则直接调用
[types.NewArray](https://draveness.me/golang/tree/cmd/compile/internal/types.NewArray)
Initializes a structure that stores the type of elements in the array and the size of the array
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进行合法性校验.And rewrite the node type
- 如果第一个参数是map类型:获取make的第二个参数,如果没有,则默认设置为0(map的大小).And rewrite the node type
- 如果第一个参数是chan类型:获取make的第二个参数,如果没有,则默认设置为0(chan的缓冲区大小).And rewrite the node type
总结
参考
- go-ast-book
- 《Go语言底层原理剖析》
- 面向信仰编程-类型检查
边栏推荐
- 第九章:activit内置用户组设计与组任务分配和IdentityService接口的使用
- Qiu Jun, CEO of Eggplant Technology: Focus on users and make products that users really need
- egg框架使用(二)
- 微服务 技术栈
- Technical dry goods | Hausdorff distance for image segmentation based on MindSpore
- 如何选币与确定对应策略研究
- How does the official account operate and maintain?Public account operation and maintenance professional team
- 高质量 DeFi 应用构建指南,助力开发者玩转 DeFi Summer
- 使用工具类把对象中的null值转换为空字符串(集合也可以使用)
- PHP 操作mangoDb
猜你喜欢
Open Source Summer | How OpenHarmony Query Device Type (eTS)
茄子科技CEO仇俊:以用户为中心,做用户真正需要的产品
项目成本控制如何帮助项目成功?
NowCoderTOP35-40 - continuous update ing
three.js调试工具dat.gui使用
Custom filters and interceptors implement ThreadLocal thread closure
还在找网盘资源吗?快点收藏如下几个值得收藏的网盘资源搜索神器吧!
5. Deploy the web project to the cloud server
Meteorological data processing example - matlab string cutting matching and R language date matching (data splicing)
入门 Polkadot 平行链开发,看这一篇就够了
随机推荐
Oracle 19.3 restart 环境
MySQL事务
three objects are arranged in a spherical shape around the circumference
MySQL advanced (twenty-seven) database index principle
皕杰报表的下拉框联动
首次去中心化抢劫?近2亿美元损失:跨链桥Nomad 被攻击事件分析
JS逆向入门学习之回收商网,手机号码简易加密解析
入门 Polkadot 平行链开发,看这一篇就够了
Getting started with Polkadot parachain development, this article is enough
leetcode: 529. 扫雷游戏
After Keil upgrades to AC6, what changes?
Is digital transformation a business buy-in?
ffmpeg drawtext 添加文本水印
three.js debugging tool dat.gui use
仿SBUS与串口数据固定转换
【温度预警程序de开发】事件驱动模型实例运用
企业的数字化转型到底是否可以买来?
技术干货 | 基于 MindSpore 实现图像分割之豪斯多夫距离
2022 Huashu Cup Mathematical Modeling Ideas Analysis and Exchange
蚁剑webshell动态加密连接分析与实践