mirror of
https://github.com/golang/go
synced 2024-10-04 22:31:22 -06:00
c7122a3c58
R=r CC=golang-dev https://golang.org/cl/833044
599 lines
12 KiB
Go
599 lines
12 KiB
Go
// 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 Interface struct {
|
|
Type Type
|
|
Value Value
|
|
}
|
|
|
|
type InterfaceValue interface {
|
|
Value
|
|
Get(*Thread) Interface
|
|
Set(*Thread, Interface)
|
|
}
|
|
|
|
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 }
|
|
|
|
/*
|
|
* Interfaces
|
|
*/
|
|
|
|
type interfaceV struct {
|
|
Interface
|
|
}
|
|
|
|
func (v *interfaceV) String() string {
|
|
if v.Type == nil || v.Value == nil {
|
|
return "<nil>"
|
|
}
|
|
return v.Value.String()
|
|
}
|
|
|
|
func (v *interfaceV) Assign(t *Thread, o Value) {
|
|
v.Interface = o.(InterfaceValue).Get(t)
|
|
}
|
|
|
|
func (v *interfaceV) Get(*Thread) Interface { return v.Interface }
|
|
|
|
func (v *interfaceV) Set(t *Thread, x Interface) {
|
|
v.Interface = 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 {
|
|
return m[key]
|
|
}
|
|
|
|
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)
|
|
}
|