diff options
Diffstat (limited to 'src/pkg/exp/eval/value.go')
-rw-r--r-- | src/pkg/exp/eval/value.go | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/src/pkg/exp/eval/value.go b/src/pkg/exp/eval/value.go new file mode 100644 index 000000000..1a64a6d96 --- /dev/null +++ b/src/pkg/exp/eval/value.go @@ -0,0 +1,731 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package eval + +import ( + "bignum"; + "fmt"; +) + +type Value interface { + String() string; + // Assign copies another value into this one. It should + // assume that the other value satisfies the same specific + // value interface (BoolValue, etc.), but must not assume + // anything about its specific type. + Assign(t *Thread, o Value); +} + +type BoolValue interface { + Value; + Get(*Thread) bool; + Set(*Thread, bool); +} + +type UintValue interface { + Value; + Get(*Thread) uint64; + Set(*Thread, uint64); +} + +type IntValue interface { + Value; + Get(*Thread) int64; + Set(*Thread, int64); +} + +// TODO(austin) IdealIntValue and IdealFloatValue should not exist +// because ideals are not l-values. +type IdealIntValue interface { + Value; + Get() *bignum.Integer; +} + +type FloatValue interface { + Value; + Get(*Thread) float64; + Set(*Thread, float64); +} + +type IdealFloatValue interface { + Value; + Get() *bignum.Rational; +} + +type StringValue interface { + Value; + Get(*Thread) string; + Set(*Thread, string); +} + +type ArrayValue interface { + Value; + // TODO(austin) Get() is here for uniformity, but is + // completely useless. If a lot of other types have similarly + // useless Get methods, just special-case these uses. + Get(*Thread) ArrayValue; + Elem(*Thread, int64) Value; + // Sub returns an ArrayValue backed by the same array that + // starts from element i and has length len. + Sub(i int64, len int64) ArrayValue; +} + +type StructValue interface { + Value; + // TODO(austin) This is another useless Get() + Get(*Thread) StructValue; + Field(*Thread, int) Value; +} + +type PtrValue interface { + Value; + Get(*Thread) Value; + Set(*Thread, Value); +} + +type Func interface { + NewFrame() *Frame; + Call(*Thread); +} + +type FuncValue interface { + Value; + Get(*Thread) Func; + Set(*Thread, Func); +} + +type Slice struct { + Base ArrayValue; + Len, Cap int64; +} + +type SliceValue interface { + Value; + Get(*Thread) Slice; + Set(*Thread, Slice); +} + +type Map interface { + Len(*Thread) int64; + // Retrieve an element from the map, returning nil if it does + // not exist. + Elem(t *Thread, key interface{}) Value; + // Set an entry in the map. If val is nil, delete the entry. + SetElem(t *Thread, key interface{}, val Value); + // TODO(austin) Perhaps there should be an iterator interface instead. + Iter(func(key interface{}, val Value) bool); +} + +type MapValue interface { + Value; + Get(*Thread) Map; + Set(*Thread, Map); +} + +/* + * Bool + */ + +type boolV bool + +func (v *boolV) String() string { + return fmt.Sprint(*v); +} + +func (v *boolV) Assign(t *Thread, o Value) { + *v = boolV(o.(BoolValue).Get(t)); +} + +func (v *boolV) Get(*Thread) bool { + return bool(*v); +} + +func (v *boolV) Set(t *Thread, x bool) { + *v = boolV(x); +} + +/* + * Uint + */ + +type uint8V uint8 + +func (v *uint8V) String() string { + return fmt.Sprint(*v); +} + +func (v *uint8V) Assign(t *Thread, o Value) { + *v = uint8V(o.(UintValue).Get(t)); +} + +func (v *uint8V) Get(*Thread) uint64 { + return uint64(*v); +} + +func (v *uint8V) Set(t *Thread, x uint64) { + *v = uint8V(x); +} + +type uint16V uint16 + +func (v *uint16V) String() string { + return fmt.Sprint(*v); +} + +func (v *uint16V) Assign(t *Thread, o Value) { + *v = uint16V(o.(UintValue).Get(t)); +} + +func (v *uint16V) Get(*Thread) uint64 { + return uint64(*v); +} + +func (v *uint16V) Set(t *Thread, x uint64) { + *v = uint16V(x); +} + +type uint32V uint32 + +func (v *uint32V) String() string { + return fmt.Sprint(*v); +} + +func (v *uint32V) Assign(t *Thread, o Value) { + *v = uint32V(o.(UintValue).Get(t)); +} + +func (v *uint32V) Get(*Thread) uint64 { + return uint64(*v); +} + +func (v *uint32V) Set(t *Thread, x uint64) { + *v = uint32V(x); +} + +type uint64V uint64 + +func (v *uint64V) String() string { + return fmt.Sprint(*v); +} + +func (v *uint64V) Assign(t *Thread, o Value) { + *v = uint64V(o.(UintValue).Get(t)); +} + +func (v *uint64V) Get(*Thread) uint64 { + return uint64(*v); +} + +func (v *uint64V) Set(t *Thread, x uint64) { + *v = uint64V(x); +} + +type uintV uint + +func (v *uintV) String() string { + return fmt.Sprint(*v); +} + +func (v *uintV) Assign(t *Thread, o Value) { + *v = uintV(o.(UintValue).Get(t)); +} + +func (v *uintV) Get(*Thread) uint64 { + return uint64(*v); +} + +func (v *uintV) Set(t *Thread, x uint64) { + *v = uintV(x); +} + +type uintptrV uintptr + +func (v *uintptrV) String() string { + return fmt.Sprint(*v); +} + +func (v *uintptrV) Assign(t *Thread, o Value) { + *v = uintptrV(o.(UintValue).Get(t)); +} + +func (v *uintptrV) Get(*Thread) uint64 { + return uint64(*v); +} + +func (v *uintptrV) Set(t *Thread, x uint64) { + *v = uintptrV(x); +} + +/* + * Int + */ + +type int8V int8 + +func (v *int8V) String() string { + return fmt.Sprint(*v); +} + +func (v *int8V) Assign(t *Thread, o Value) { + *v = int8V(o.(IntValue).Get(t)); +} + +func (v *int8V) Get(*Thread) int64 { + return int64(*v); +} + +func (v *int8V) Set(t *Thread, x int64) { + *v = int8V(x); +} + +type int16V int16 + +func (v *int16V) String() string { + return fmt.Sprint(*v); +} + +func (v *int16V) Assign(t *Thread, o Value) { + *v = int16V(o.(IntValue).Get(t)); +} + +func (v *int16V) Get(*Thread) int64 { + return int64(*v); +} + +func (v *int16V) Set(t *Thread, x int64) { + *v = int16V(x); +} + +type int32V int32 + +func (v *int32V) String() string { + return fmt.Sprint(*v); +} + +func (v *int32V) Assign(t *Thread, o Value) { + *v = int32V(o.(IntValue).Get(t)); +} + +func (v *int32V) Get(*Thread) int64 { + return int64(*v); +} + +func (v *int32V) Set(t *Thread, x int64) { + *v = int32V(x); +} + +type int64V int64 + +func (v *int64V) String() string { + return fmt.Sprint(*v); +} + +func (v *int64V) Assign(t *Thread, o Value) { + *v = int64V(o.(IntValue).Get(t)); +} + +func (v *int64V) Get(*Thread) int64 { + return int64(*v); +} + +func (v *int64V) Set(t *Thread, x int64) { + *v = int64V(x); +} + +type intV int + +func (v *intV) String() string { + return fmt.Sprint(*v); +} + +func (v *intV) Assign(t *Thread, o Value) { + *v = intV(o.(IntValue).Get(t)); +} + +func (v *intV) Get(*Thread) int64 { + return int64(*v); +} + +func (v *intV) Set(t *Thread, x int64) { + *v = intV(x); +} + +/* + * Ideal int + */ + +type idealIntV struct { + V *bignum.Integer; +} + +func (v *idealIntV) String() string { + return v.V.String(); +} + +func (v *idealIntV) Assign(t *Thread, o Value) { + v.V = o.(IdealIntValue).Get(); +} + +func (v *idealIntV) Get() *bignum.Integer { + return v.V; +} + +/* + * Float + */ + +type float32V float32 + +func (v *float32V) String() string { + return fmt.Sprint(*v); +} + +func (v *float32V) Assign(t *Thread, o Value) { + *v = float32V(o.(FloatValue).Get(t)); +} + +func (v *float32V) Get(*Thread) float64 { + return float64(*v); +} + +func (v *float32V) Set(t *Thread, x float64) { + *v = float32V(x); +} + +type float64V float64 + +func (v *float64V) String() string { + return fmt.Sprint(*v); +} + +func (v *float64V) Assign(t *Thread, o Value) { + *v = float64V(o.(FloatValue).Get(t)); +} + +func (v *float64V) Get(*Thread) float64 { + return float64(*v); +} + +func (v *float64V) Set(t *Thread, x float64) { + *v = float64V(x); +} + +type floatV float + +func (v *floatV) String() string { + return fmt.Sprint(*v); +} + +func (v *floatV) Assign(t *Thread, o Value) { + *v = floatV(o.(FloatValue).Get(t)); +} + +func (v *floatV) Get(*Thread) float64 { + return float64(*v); +} + +func (v *floatV) Set(t *Thread, x float64) { + *v = floatV(x); +} + +/* + * Ideal float + */ + +type idealFloatV struct { + V *bignum.Rational; +} + +func (v *idealFloatV) String() string { + return ratToString(v.V); +} + +func (v *idealFloatV) Assign(t *Thread, o Value) { + v.V = o.(IdealFloatValue).Get(); +} + +func (v *idealFloatV) Get() *bignum.Rational { + return v.V; +} + +/* + * String + */ + +type stringV string + +func (v *stringV) String() string { + return fmt.Sprint(*v); +} + +func (v *stringV) Assign(t *Thread, o Value) { + *v = stringV(o.(StringValue).Get(t)); +} + +func (v *stringV) Get(*Thread) string { + return string(*v); +} + +func (v *stringV) Set(t *Thread, x string) { + *v = stringV(x); +} + +/* + * Array + */ + +type arrayV []Value + +func (v *arrayV) String() string { + res := "{"; + for i, e := range *v { + if i > 0 { + res += ", "; + } + res += e.String(); + } + return res + "}"; +} + +func (v *arrayV) Assign(t *Thread, o Value) { + oa := o.(ArrayValue); + l := int64(len(*v)); + for i := int64(0); i < l; i++ { + (*v)[i].Assign(t, oa.Elem(t, i)); + } +} + +func (v *arrayV) Get(*Thread) ArrayValue { + return v; +} + +func (v *arrayV) Elem(t *Thread, i int64) Value { + return (*v)[i]; +} + +func (v *arrayV) Sub(i int64, len int64) ArrayValue { + res := (*v)[i:i+len]; + return &res; +} + +/* + * Struct + */ + +type structV []Value + +// TODO(austin) Should these methods (and arrayV's) be on structV +// instead of *structV? +func (v *structV) String() string { + res := "{"; + for i, v := range *v { + if i > 0 { + res += ", "; + } + res += v.String(); + } + return res + "}"; +} + +func (v *structV) Assign(t *Thread, o Value) { + oa := o.(StructValue); + l := len(*v); + for i := 0; i < l; i++ { + (*v)[i].Assign(t, oa.Field(t, i)); + } +} + +func (v *structV) Get(*Thread) StructValue { + return v; +} + +func (v *structV) Field(t *Thread, i int) Value { + return (*v)[i]; +} + +/* + * Pointer + */ + +type ptrV struct { + // nil if the pointer is nil + target Value; +} + +func (v *ptrV) String() string { + if v.target == nil { + return "<nil>"; + } + return "&" + v.target.String(); +} + +func (v *ptrV) Assign(t *Thread, o Value) { + v.target = o.(PtrValue).Get(t); +} + +func (v *ptrV) Get(*Thread) Value { + return v.target; +} + +func (v *ptrV) Set(t *Thread, x Value) { + v.target = x; +} + +/* + * Functions + */ + +type funcV struct { + target Func; +} + +func (v *funcV) String() string { + // TODO(austin) Rob wants to see the definition + return "func {...}"; +} + +func (v *funcV) Assign(t *Thread, o Value) { + v.target = o.(FuncValue).Get(t); +} + +func (v *funcV) Get(*Thread) Func { + return v.target; +} + +func (v *funcV) Set(t *Thread, x Func) { + v.target = x; +} + +/* + * Slices + */ + +type sliceV struct { + Slice; +} + +func (v *sliceV) String() string { + if v.Base == nil { + return "<nil>"; + } + return v.Base.Sub(0, v.Len).String(); +} + +func (v *sliceV) Assign(t *Thread, o Value) { + v.Slice = o.(SliceValue).Get(t); +} + +func (v *sliceV) Get(*Thread) Slice { + return v.Slice; +} + +func (v *sliceV) Set(t *Thread, x Slice) { + v.Slice = x; +} + +/* + * Maps + */ + +type mapV struct { + target Map; +} + +func (v *mapV) String() string { + if v.target == nil { + return "<nil>"; + } + res := "map["; + i := 0; + v.target.Iter(func(key interface{}, val Value) bool { + if i > 0 { + res += ", "; + } + i++; + res += fmt.Sprint(key) + ":" + val.String(); + return true; + }); + return res + "]"; +} + +func (v *mapV) Assign(t *Thread, o Value) { + v.target = o.(MapValue).Get(t); +} + +func (v *mapV) Get(*Thread) Map { + return v.target; +} + +func (v *mapV) Set(t *Thread, x Map) { + v.target = x; +} + +type evalMap map[interface{}] Value + +func (m evalMap) Len(t *Thread) int64 { + return int64(len(m)); +} + +func (m evalMap) Elem(t *Thread, key interface{}) Value { + if v, ok := m[key]; ok { + return v; + } + return nil; +} + +func (m evalMap) SetElem(t *Thread, key interface{}, val Value) { + if val == nil { + m[key] = nil, false; + } else { + m[key] = val; + } +} + +func (m evalMap) Iter(cb func(key interface{}, val Value) bool) { + for k, v := range m { + if !cb(k, v) { + break; + } + } +} + +/* + * Multi-values + */ + +type multiV []Value + +func (v multiV) String() string { + res := "("; + for i, v := range v { + if i > 0 { + res += ", "; + } + res += v.String(); + } + return res + ")"; +} + +func (v multiV) Assign(t *Thread, o Value) { + omv := o.(multiV); + for i := range v { + v[i].Assign(t, omv[i]); + } +} + +/* + * Universal constants + */ + +// TODO(austin) Nothing complains if I accidentally define init with +// arguments. Is this intentional? +func init() { + s := universe; + + true := boolV(true); + s.DefineConst("true", universePos, BoolType, &true); + false := boolV(false); + s.DefineConst("false", universePos, BoolType, &false); +} |