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
|
package parser
import (
"reflect"
"strings"
)
type symKind int
const (
symValue symKind = iota // a Go value defined in the runtime
symType // a Go type
symLabel // a label indication a position in the VM code
symConst // a Go constant
symVar // a Go variable, located in the VM memory
symFunc // a Go function, located in the VM code
)
type symbol struct {
kind symKind
index int // address of symbol in frame
value any
Type reflect.Type
local bool // if true address is relative to local frame, otherwise global
used bool
}
func (p *Parser) AddSym(i int, name string, v any) { p.addSym(i, name, v, symValue, nil, false) }
func (p *Parser) addSym(i int, name string, v any, k symKind, t reflect.Type, local bool) {
p.symbols[name] = &symbol{kind: k, index: i, local: local, value: v, Type: t, used: true}
}
// getSym searches for an existing symbol starting from the deepest scope.
func (p *Parser) getSym(name, scope string) (sym *symbol, sc string, ok bool) {
for {
if sym, ok = p.symbols[scope+"/"+name]; ok {
return sym, scope, ok
}
i := strings.LastIndex(scope, "/")
if i == -1 {
i = 0
}
if scope = scope[:i]; scope == "" {
break
}
}
sym, ok = p.symbols[name]
return sym, scope, ok
}
func initUniverse() map[string]*symbol {
return map[string]*symbol{
"any": {kind: symType, Type: reflect.TypeOf((*any)(nil)).Elem()},
"bool": {kind: symType, Type: reflect.TypeOf((*bool)(nil)).Elem()},
"error": {kind: symType, Type: reflect.TypeOf((*error)(nil)).Elem()},
"int": {kind: symType, Type: reflect.TypeOf((*int)(nil)).Elem()},
"string": {kind: symType, Type: reflect.TypeOf((*string)(nil)).Elem()},
"nil": {},
"iota": {value: 0},
"true": {value: true},
"false": {value: false},
}
}
|