neo-go/pkg/vm/compiler/struct_scope.go

90 lines
2 KiB
Go
Raw Normal View History

package compiler
import (
"go/constant"
"go/types"
"log"
)
// A structScope holds the positions for it's fields. Struct fields have different
// positions then local variables in any scope.
type structScope struct {
// A pointer to the underlying type.
t *types.Struct
// A mapping of fieldnames identifier and its position.
fields map[string]int
// A mapping of fieldnames and with type and value.
// This will be populated in "initFields" to initialize all
// structs fields to their zero value.
// strings: "" (just a pushf 0x00)
// int: 0
// bool: false
typeAndValues map[string]types.TypeAndValue
}
// newStructScope will create a new structScope with all fields initialized.
func newStructScope(t *types.Struct) *structScope {
s := &structScope{
fields: map[string]int{},
typeAndValues: make(map[string]types.TypeAndValue, t.NumFields()),
t: t,
}
s.initFields()
return s
}
func (s *structScope) initFields() {
var tv types.TypeAndValue
for i := 0; i < s.t.NumFields(); i++ {
f := s.t.Field(i)
s.newField(f.Name())
switch t := f.Type().(type) {
case *types.Basic:
switch t.Kind() {
case types.Int:
tv = types.TypeAndValue{
Type: t,
Value: constant.MakeInt64(0),
}
case types.String:
tv = types.TypeAndValue{
Type: t,
Value: constant.MakeString(""),
}
case types.Bool, types.UntypedBool:
tv = types.TypeAndValue{
Type: t,
Value: constant.MakeBool(false),
}
default:
log.Fatalf("could not initialize struct field %s to zero, type: %s", f.Name(), t)
}
}
s.typeAndValues[f.Name()] = tv
}
}
func (s *structScope) newField(name string) int {
i := len(s.fields)
s.fields[name] = i
return i
}
func (s *structScope) loadField(name string) int {
i, ok := s.fields[name]
if !ok {
log.Fatalf("could not resolve field %s for struct %v", name, s)
}
return i
}
func (s *structScope) initialize(t *types.Struct) {
s.t = t
for i := 0; i < t.NumFields(); i++ {
s.newField(t.Field(i).Name())
}
}