elvish/eval/value.go

268 lines
5.5 KiB
Go
Raw Normal View History

package eval
import (
2015-02-05 20:22:23 +08:00
"errors"
2014-01-16 09:24:14 +08:00
"fmt"
2015-02-05 17:52:57 +08:00
"math/big"
"reflect"
2016-02-20 03:31:54 +08:00
"github.com/elves/elvish/util"
)
2016-02-19 05:52:05 +08:00
// Definitions for Value interfaces, some simple Value types and some common
// Value helpers.
const (
2016-02-20 03:31:54 +08:00
NoPretty = util.MinInt
)
2016-02-08 06:23:16 +08:00
// Value is an elvish value.
2014-03-30 15:06:56 +08:00
type Value interface {
2016-02-20 01:59:32 +08:00
Kinder
Reprer
}
2016-02-20 01:59:32 +08:00
// Kinder is anything with kind string.
type Kinder interface {
Kind() string
}
2016-02-08 06:23:16 +08:00
// Reprer is anything with a Repr method.
type Reprer interface {
// Repr returns a string that represents a Value. The string either be a
// literal of that Value that is preferably deep-equal to it (like `[a b c]`
// for a list), or a string enclosed in "<>" containing the kind and
// identity of the Value(like `<fn 0xdeadcafe>`).
//
// If indent is at least 0, it should be pretty-printed with the current
// indentation level of indent; the indent of the first line has already
// been written and shall not be written in Repr. The returned string
// should never contain a trailing newline.
Repr(indent int) string
}
func IncIndent(indent, inc int) int {
if indent < 0 {
return indent
}
return indent + inc
2015-01-26 23:16:18 +08:00
}
2016-02-08 06:23:16 +08:00
// Booler is anything that can be converted to a bool.
2016-01-29 20:55:14 +08:00
type Booler interface {
Bool() bool
2014-03-30 15:06:56 +08:00
}
2016-02-08 06:23:16 +08:00
// Stringer is anything that can be converted to a string.
2016-01-29 20:55:14 +08:00
type Stringer interface {
String() string
}
2016-02-19 18:49:19 +08:00
// Lener is anything with a length.
type Lener interface {
Len() int
}
// Iterator is anything that can be iterated.
type Iterator interface {
Iterate(func(Value) bool)
2016-02-19 19:07:38 +08:00
}
type IteratorValue interface {
Iterator
Value
}
func collectFromIterator(it Iterator) []Value {
2016-02-19 19:07:38 +08:00
var vs []Value
if lener, ok := it.(Lener); ok {
vs = make([]Value, 0, lener.Len())
2016-02-19 19:07:38 +08:00
}
it.Iterate(func(v Value) bool {
vs = append(vs, v)
return true
})
2016-02-19 19:07:38 +08:00
return vs
}
2016-10-14 18:22:30 +08:00
var (
NoArgs = []Value{}
NoOpts = map[string]Value{}
)
2016-03-02 08:35:13 +08:00
// Fn is anything may be called on an evalCtx with a list of Value's.
type Fn interface {
Call(ec *EvalCtx, args []Value, opts map[string]Value)
2014-03-30 15:06:56 +08:00
}
2016-03-02 08:35:13 +08:00
type FnValue interface {
Value
2016-03-02 08:35:13 +08:00
Fn
}
2016-03-02 08:35:13 +08:00
func mustFn(v Value) Fn {
fn, ok := v.(Fn)
2016-02-19 05:52:05 +08:00
if !ok {
throw(fmt.Errorf("a %s is not callable", v.Kind()))
}
return fn
}
// Indexer is anything that can be indexed by Values and yields Values.
2016-02-19 05:52:05 +08:00
type Indexer interface {
Index(idx []Value) []Value
2016-01-29 06:39:20 +08:00
}
// IndexOneer is anything that can be indexed by one Value and yields one Value.
2016-02-19 05:52:05 +08:00
type IndexOneer interface {
IndexOne(idx Value) Value
2016-01-31 08:07:35 +08:00
}
2014-01-16 09:24:14 +08:00
2016-02-19 05:52:05 +08:00
// IndexSetter is a Value whose elements can be get as well as set.
type IndexSetter interface {
IndexOneer
IndexSet(idx Value, v Value)
2014-03-30 16:02:56 +08:00
}
2016-02-19 05:52:05 +08:00
func mustIndexer(v Value, ec *EvalCtx) Indexer {
indexer, ok := getIndexer(v, ec)
if !ok {
throw(fmt.Errorf("a %s is not indexable", v.Kind()))
2016-01-28 03:16:41 +08:00
}
2016-02-19 05:52:05 +08:00
return indexer
2016-01-28 03:16:41 +08:00
}
2016-02-19 05:52:05 +08:00
// getIndexer adapts a Value to an Indexer if there is an adapter. It adapts a
2016-03-02 08:35:13 +08:00
// Fn if ec is not nil.
2016-02-19 05:52:05 +08:00
func getIndexer(v Value, ec *EvalCtx) (Indexer, bool) {
if indexer, ok := v.(Indexer); ok {
return indexer, true
}
2016-02-19 05:52:05 +08:00
if indexOneer, ok := v.(IndexOneer); ok {
return IndexOneerIndexer{indexOneer}, true
}
2016-02-19 05:52:05 +08:00
return nil, false
}
2013-10-16 21:27:16 +08:00
2016-02-19 05:52:05 +08:00
// IndexOneerIndexer adapts an IndexOneer to an Indexer by calling all the
// indicies on the IndexOner and collect the results.
type IndexOneerIndexer struct {
IndexOneer
}
2016-02-19 05:52:05 +08:00
func (ioi IndexOneerIndexer) Index(vs []Value) []Value {
results := make([]Value, len(vs))
for i, v := range vs {
results[i] = ioi.IndexOneer.IndexOne(v)
}
2016-02-19 05:52:05 +08:00
return results
}
2016-02-19 05:52:05 +08:00
// Error definitions.
var (
ErrOnlyStrOrRat = errors.New("only str or rat may be converted to rat")
)
2015-01-26 22:59:25 +08:00
2016-02-19 05:52:05 +08:00
// Bool represents truthness.
type Bool bool
2015-01-26 22:59:25 +08:00
2016-02-19 05:52:05 +08:00
func (Bool) Kind() string {
return "bool"
2015-01-26 22:59:25 +08:00
}
func (b Bool) Repr(int) string {
2016-02-19 05:52:05 +08:00
if b {
return "$true"
}
return "$false"
2015-01-26 23:06:50 +08:00
}
2016-02-19 05:52:05 +08:00
func (b Bool) Bool() bool {
return bool(b)
2015-01-26 23:06:50 +08:00
}
2016-02-19 05:52:05 +08:00
// ToBool converts a Value to bool. When the Value type implements Bool(), it
// is used. Otherwise it is considered true.
func ToBool(v Value) bool {
if b, ok := v.(Booler); ok {
return b.Bool()
}
return true
2015-01-26 23:06:50 +08:00
}
2016-02-01 15:10:20 +08:00
// Rat is a rational number.
2016-01-29 20:55:14 +08:00
type Rat struct {
2015-02-05 20:31:22 +08:00
b *big.Rat
}
2015-02-05 17:52:57 +08:00
func (Rat) Kind() string {
return "string"
2015-02-05 20:33:42 +08:00
}
func (r Rat) Repr(int) string {
2015-02-05 17:52:57 +08:00
return "(rat " + r.String() + ")"
}
2016-01-29 20:55:14 +08:00
func (r Rat) String() string {
2015-02-05 20:31:22 +08:00
if r.b.IsInt() {
return r.b.Num().String()
2015-02-05 17:52:57 +08:00
}
2015-02-05 20:31:22 +08:00
return r.b.String()
2015-02-05 17:52:57 +08:00
}
2016-02-19 05:52:05 +08:00
// ToRat converts a Value to rat. A str can be converted to a rat if it can be
// parsed. A rat is returned as-is. Other types of values cannot be converted.
func ToRat(v Value) (Rat, error) {
switch v := v.(type) {
case Rat:
return v, nil
case String:
r := big.Rat{}
_, err := fmt.Sscanln(string(v), &r)
if err != nil {
2016-02-20 03:31:54 +08:00
return Rat{}, fmt.Errorf("%s cannot be parsed as rat", v.Repr(NoPretty))
}
2016-02-19 05:52:05 +08:00
return Rat{&r}, nil
default:
return Rat{}, ErrOnlyStrOrRat
}
2016-02-07 21:44:08 +08:00
}
2016-01-29 20:55:14 +08:00
// FromJSONInterface converts a interface{} that results from json.Unmarshal to
// a Value.
2016-01-29 20:55:14 +08:00
func FromJSONInterface(v interface{}) Value {
if v == nil {
// TODO Use a more appropriate type
2016-01-29 20:55:14 +08:00
return String("")
}
switch v.(type) {
case bool:
2016-01-29 20:55:14 +08:00
return Bool(v.(bool))
case float64, string:
// TODO Use a numeric type for float64
2016-01-29 20:55:14 +08:00
return String(fmt.Sprint(v))
case []interface{}:
a := v.([]interface{})
2016-01-31 08:07:35 +08:00
vs := make([]Value, len(a))
for i, v := range a {
2016-01-29 20:55:14 +08:00
vs[i] = FromJSONInterface(v)
}
2016-01-31 08:07:35 +08:00
return List{&vs}
case map[string]interface{}:
m := v.(map[string]interface{})
m_ := make(map[Value]Value)
for k, v := range m {
m_[String(k)] = FromJSONInterface(v)
}
return Map{&m_}
default:
throw(fmt.Errorf("unexpected json type: %T", v))
2016-02-01 15:10:20 +08:00
return nil // not reached
}
}
// DeepEq compares two Value's deeply.
func DeepEq(a, b Value) bool {
return reflect.DeepEqual(a, b)
}