-
Notifications
You must be signed in to change notification settings - Fork 79
/
vars.go
103 lines (91 loc) · 2.04 KB
/
vars.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package compiler
import (
"go/ast"
"strconv"
)
type varScope struct {
localsCnt int
arguments map[string]int
locals []map[string]varInfo
}
type varContext struct {
importMap map[string]string
expr ast.Expr
scope []map[string]varInfo
}
type varInfo struct {
refType varType
index int
// ctx is set for inline arguments and contains
// context for expression traversal.
ctx *varContext
}
const unspecifiedVarIndex = -1
func newVarScope() varScope {
return varScope{
arguments: make(map[string]int),
}
}
func (c *varScope) newScope() {
c.locals = append(c.locals, map[string]varInfo{})
}
func (c *varScope) dropScope() {
c.locals = c.locals[:len(c.locals)-1]
}
func (c *varScope) addAlias(name string, vt varType, index int, ctx *varContext) {
c.locals[len(c.locals)-1][name] = varInfo{
refType: vt,
index: index,
ctx: ctx,
}
}
func (c *varScope) getVarInfo(name string) *varInfo {
for i := len(c.locals) - 1; i >= 0; i-- {
if vi, ok := c.locals[i][name]; ok {
return &vi
}
}
if i, ok := c.arguments[name]; ok {
return &varInfo{
refType: varArgument,
index: i,
}
}
return nil
}
// newVariable creates a new local variable or argument in the scope of the function.
func (c *varScope) newVariable(t varType, name string) int {
var n int
switch t {
case varLocal:
return c.newLocal(name)
case varArgument:
if name == "_" {
// See #2204. This name won't actually be referenced.
// This approach simplifies argument allocation and
// makes debugging easier.
name = "%_" + strconv.FormatUint(uint64(len(c.arguments)), 10)
}
_, ok := c.arguments[name]
if ok {
panic("argument is already allocated")
}
n = len(c.arguments)
c.arguments[name] = n
default:
panic("invalid type")
}
return n
}
// newLocal creates a new local variable in the current scope.
func (c *varScope) newLocal(name string) int {
idx := len(c.locals) - 1
m := c.locals[idx]
m[name] = varInfo{
refType: varLocal,
index: c.localsCnt,
}
c.localsCnt++
c.locals[idx] = m
return c.localsCnt - 1
}