This repository has been archived by the owner on Mar 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 361
/
environ.go
74 lines (64 loc) · 1.61 KB
/
environ.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
package compiler
import "fmt"
// name-binding environment
type environ struct {
entries map[string]*envEntry
parent *environ
}
type envEntry struct {
t typeDesc
r role
c *Contract // if t == contractType
}
type role int
const (
roleKeyword role = 1 + iota
roleBuiltin
roleContract
roleContractParam
roleContractValue
roleClause
roleClauseParam
roleClauseValue
roleClauseVariable
)
var roleDesc = map[role]string{
roleKeyword: "keyword",
roleBuiltin: "built-in function",
roleContract: "contract",
roleContractParam: "contract parameter",
roleContractValue: "contract value",
roleClause: "clause",
roleClauseParam: "clause parameter",
roleClauseValue: "clause value",
roleClauseVariable: "clause variable",
}
func newEnviron(parent *environ) *environ {
return &environ{
entries: make(map[string]*envEntry),
parent: parent,
}
}
func (e *environ) add(name string, t typeDesc, r role) error {
if entry := e.lookup(name); entry != nil {
return fmt.Errorf("%s \"%s\" conflicts with %s", roleDesc[r], name, roleDesc[entry.r])
}
e.entries[name] = &envEntry{t: t, r: r}
return nil
}
func (e *environ) addContract(contract *Contract) error {
if entry := e.lookup(contract.Name); entry != nil {
return fmt.Errorf("%s \"%s\" conflicts with %s", roleDesc[roleContract], contract.Name, roleDesc[entry.r])
}
e.entries[contract.Name] = &envEntry{t: contractType, r: roleContract, c: contract}
return nil
}
func (e environ) lookup(name string) *envEntry {
if res, ok := e.entries[name]; ok {
return res
}
if e.parent != nil {
return e.parent.lookup(name)
}
return nil
}