| // 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(o Value); |
| } |
| |
| type BoolValue interface { |
| Value; |
| Get() bool; |
| Set(bool); |
| } |
| |
| type UintValue interface { |
| Value; |
| Get() uint64; |
| Set(uint64); |
| } |
| |
| type IntValue interface { |
| Value; |
| Get() int64; |
| Set(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() float64; |
| Set(float64); |
| } |
| |
| type IdealFloatValue interface { |
| Value; |
| Get() *bignum.Rational; |
| } |
| |
| type StringValue interface { |
| Value; |
| Get() string; |
| Set(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() ArrayValue; |
| Elem(i int64) Value; |
| // From returns an ArrayValue backed by the same array that |
| // starts from element i. |
| From(i int64) ArrayValue; |
| } |
| |
| type StructValue interface { |
| Value; |
| // TODO(austin) This is another useless Get() |
| Get() StructValue; |
| Field(i int) Value; |
| } |
| |
| type PtrValue interface { |
| Value; |
| Get() Value; |
| Set(Value); |
| } |
| |
| type Func interface { |
| NewFrame() *Frame; |
| Call(*Frame); |
| } |
| |
| type FuncValue interface { |
| Value; |
| Get() Func; |
| Set(Func); |
| } |
| |
| type Slice struct { |
| Base ArrayValue; |
| Len, Cap int64; |
| } |
| |
| type SliceValue interface { |
| Value; |
| Get() Slice; |
| Set(Slice); |
| } |
| |
| type Map interface { |
| Len() int64; |
| // Retrieve an element from the map, returning nil if it does |
| // not exist. |
| Elem(key interface{}) Value; |
| // Set an entry in the map. If val is nil, delete the entry. |
| SetElem(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() Map; |
| Set(Map); |
| } |
| |
| /* |
| * Bool |
| */ |
| |
| type boolV bool |
| |
| func (v *boolV) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *boolV) Assign(o Value) { |
| *v = boolV(o.(BoolValue).Get()); |
| } |
| |
| func (v *boolV) Get() bool { |
| return bool(*v); |
| } |
| |
| func (v *boolV) Set(x bool) { |
| *v = boolV(x); |
| } |
| |
| /* |
| * Uint |
| */ |
| |
| type uint8V uint8 |
| |
| func (v *uint8V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *uint8V) Assign(o Value) { |
| *v = uint8V(o.(UintValue).Get()); |
| } |
| |
| func (v *uint8V) Get() uint64 { |
| return uint64(*v); |
| } |
| |
| func (v *uint8V) Set(x uint64) { |
| *v = uint8V(x); |
| } |
| |
| type uint16V uint16 |
| |
| func (v *uint16V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *uint16V) Assign(o Value) { |
| *v = uint16V(o.(UintValue).Get()); |
| } |
| |
| func (v *uint16V) Get() uint64 { |
| return uint64(*v); |
| } |
| |
| func (v *uint16V) Set(x uint64) { |
| *v = uint16V(x); |
| } |
| |
| type uint32V uint32 |
| |
| func (v *uint32V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *uint32V) Assign(o Value) { |
| *v = uint32V(o.(UintValue).Get()); |
| } |
| |
| func (v *uint32V) Get() uint64 { |
| return uint64(*v); |
| } |
| |
| func (v *uint32V) Set(x uint64) { |
| *v = uint32V(x); |
| } |
| |
| type uint64V uint64 |
| |
| func (v *uint64V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *uint64V) Assign(o Value) { |
| *v = uint64V(o.(UintValue).Get()); |
| } |
| |
| func (v *uint64V) Get() uint64 { |
| return uint64(*v); |
| } |
| |
| func (v *uint64V) Set(x uint64) { |
| *v = uint64V(x); |
| } |
| |
| type uintV uint |
| |
| func (v *uintV) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *uintV) Assign(o Value) { |
| *v = uintV(o.(UintValue).Get()); |
| } |
| |
| func (v *uintV) Get() uint64 { |
| return uint64(*v); |
| } |
| |
| func (v *uintV) Set(x uint64) { |
| *v = uintV(x); |
| } |
| |
| type uintptrV uintptr |
| |
| func (v *uintptrV) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *uintptrV) Assign(o Value) { |
| *v = uintptrV(o.(UintValue).Get()); |
| } |
| |
| func (v *uintptrV) Get() uint64 { |
| return uint64(*v); |
| } |
| |
| func (v *uintptrV) Set(x uint64) { |
| *v = uintptrV(x); |
| } |
| |
| /* |
| * Int |
| */ |
| |
| type int8V int8 |
| |
| func (v *int8V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *int8V) Assign(o Value) { |
| *v = int8V(o.(IntValue).Get()); |
| } |
| |
| func (v *int8V) Get() int64 { |
| return int64(*v); |
| } |
| |
| func (v *int8V) Set(x int64) { |
| *v = int8V(x); |
| } |
| |
| type int16V int16 |
| |
| func (v *int16V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *int16V) Assign(o Value) { |
| *v = int16V(o.(IntValue).Get()); |
| } |
| |
| func (v *int16V) Get() int64 { |
| return int64(*v); |
| } |
| |
| func (v *int16V) Set(x int64) { |
| *v = int16V(x); |
| } |
| |
| type int32V int32 |
| |
| func (v *int32V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *int32V) Assign(o Value) { |
| *v = int32V(o.(IntValue).Get()); |
| } |
| |
| func (v *int32V) Get() int64 { |
| return int64(*v); |
| } |
| |
| func (v *int32V) Set(x int64) { |
| *v = int32V(x); |
| } |
| |
| type int64V int64 |
| |
| func (v *int64V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *int64V) Assign(o Value) { |
| *v = int64V(o.(IntValue).Get()); |
| } |
| |
| func (v *int64V) Get() int64 { |
| return int64(*v); |
| } |
| |
| func (v *int64V) Set(x int64) { |
| *v = int64V(x); |
| } |
| |
| type intV int |
| |
| func (v *intV) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *intV) Assign(o Value) { |
| *v = intV(o.(IntValue).Get()); |
| } |
| |
| func (v *intV) Get() int64 { |
| return int64(*v); |
| } |
| |
| func (v *intV) Set(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(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(o Value) { |
| *v = float32V(o.(FloatValue).Get()); |
| } |
| |
| func (v *float32V) Get() float64 { |
| return float64(*v); |
| } |
| |
| func (v *float32V) Set(x float64) { |
| *v = float32V(x); |
| } |
| |
| type float64V float64 |
| |
| func (v *float64V) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *float64V) Assign(o Value) { |
| *v = float64V(o.(FloatValue).Get()); |
| } |
| |
| func (v *float64V) Get() float64 { |
| return float64(*v); |
| } |
| |
| func (v *float64V) Set(x float64) { |
| *v = float64V(x); |
| } |
| |
| type floatV float |
| |
| func (v *floatV) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *floatV) Assign(o Value) { |
| *v = floatV(o.(FloatValue).Get()); |
| } |
| |
| func (v *floatV) Get() float64 { |
| return float64(*v); |
| } |
| |
| func (v *floatV) Set(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(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(o Value) { |
| *v = stringV(o.(StringValue).Get()); |
| } |
| |
| func (v *stringV) Get() string { |
| return string(*v); |
| } |
| |
| func (v *stringV) Set(x string) { |
| *v = stringV(x); |
| } |
| |
| /* |
| * Array |
| */ |
| |
| type arrayV []Value |
| |
| func (v *arrayV) String() string { |
| return fmt.Sprint(*v); |
| } |
| |
| func (v *arrayV) Assign(o Value) { |
| oa := o.(ArrayValue); |
| l := int64(len(*v)); |
| for i := int64(0); i < l; i++ { |
| (*v)[i].Assign(oa.Elem(i)); |
| } |
| } |
| |
| func (v *arrayV) Get() ArrayValue { |
| return v; |
| } |
| |
| func (v *arrayV) Elem(i int64) Value { |
| return (*v)[i]; |
| } |
| |
| func (v *arrayV) From(i int64) ArrayValue { |
| res := (*v)[i:len(*v)]; |
| 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(o Value) { |
| oa := o.(StructValue); |
| l := len(*v); |
| for i := 0; i < l; i++ { |
| (*v)[i].Assign(oa.Field(i)); |
| } |
| } |
| |
| func (v *structV) Get() StructValue { |
| return v; |
| } |
| |
| func (v *structV) Field(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(o Value) { |
| v.target = o.(PtrValue).Get(); |
| } |
| |
| func (v *ptrV) Get() Value { |
| return v.target; |
| } |
| |
| func (v *ptrV) Set(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(o Value) { |
| v.target = o.(FuncValue).Get(); |
| } |
| |
| func (v *funcV) Get() Func { |
| return v.target; |
| } |
| |
| func (v *funcV) Set(x Func) { |
| v.target = x; |
| } |
| |
| /* |
| * Slices |
| */ |
| |
| type sliceV struct { |
| Slice; |
| } |
| |
| func (v *sliceV) String() string { |
| if v.Base == nil { |
| return "<nil>"; |
| } |
| res := "{"; |
| for i := int64(0); i < v.Len; i++ { |
| if i > 0 { |
| res += ", "; |
| } |
| res += v.Base.Elem(i).String(); |
| } |
| return res + "}"; |
| } |
| |
| func (v *sliceV) Assign(o Value) { |
| v.Slice = o.(SliceValue).Get(); |
| } |
| |
| func (v *sliceV) Get() Slice { |
| return v.Slice; |
| } |
| |
| func (v *sliceV) Set(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(o Value) { |
| v.target = o.(MapValue).Get(); |
| } |
| |
| func (v *mapV) Get() Map { |
| return v.target; |
| } |
| |
| func (v *mapV) Set(x Map) { |
| v.target = x; |
| } |
| |
| type evalMap map[interface{}] Value |
| |
| func (m evalMap) Len() int64 { |
| return int64(len(m)); |
| } |
| |
| func (m evalMap) Elem(key interface{}) Value { |
| if v, ok := m[key]; ok { |
| return v; |
| } |
| return nil; |
| } |
| |
| func (m evalMap) SetElem(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(o Value) { |
| omv := o.(multiV); |
| for i := range v { |
| v[i].Assign(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); |
| } |