summaryrefslogtreecommitdiff
path: root/src/pkg/exp/eval/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/exp/eval/value.go')
-rw-r--r--src/pkg/exp/eval/value.go731
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);
+}