github.com/ladydascalie/elvish@v0.0.0-20170703214355-2964dd3ece7f/eval/value.go (about)

     1  package eval
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  	"reflect"
     8  
     9  	"github.com/elves/elvish/util"
    10  )
    11  
    12  // Definitions for Value interfaces, some simple Value types and some common
    13  // Value helpers.
    14  
    15  const (
    16  	NoPretty = util.MinInt
    17  )
    18  
    19  // Value is an elvish value.
    20  type Value interface {
    21  	Kinder
    22  	Reprer
    23  }
    24  
    25  // Kinder is anything with kind string.
    26  type Kinder interface {
    27  	Kind() string
    28  }
    29  
    30  // Reprer is anything with a Repr method.
    31  type Reprer interface {
    32  	// Repr returns a string that represents a Value. The string either be a
    33  	// literal of that Value that is preferably deep-equal to it (like `[a b c]`
    34  	// for a list), or a string enclosed in "<>" containing the kind and
    35  	// identity of the Value(like `<fn 0xdeadcafe>`).
    36  	//
    37  	// If indent is at least 0, it should be pretty-printed with the current
    38  	// indentation level of indent; the indent of the first line has already
    39  	// been written and shall not be written in Repr. The returned string
    40  	// should never contain a trailing newline.
    41  	Repr(indent int) string
    42  }
    43  
    44  // Booler is anything that can be converted to a bool.
    45  type Booler interface {
    46  	Bool() bool
    47  }
    48  
    49  // Stringer is anything that can be converted to a string.
    50  type Stringer interface {
    51  	String() string
    52  }
    53  
    54  // Lener is anything with a length.
    55  type Lener interface {
    56  	Len() int
    57  }
    58  
    59  // Iterable is anything that can be iterated.
    60  type Iterable interface {
    61  	Iterate(func(Value) bool)
    62  }
    63  
    64  type IterableValue interface {
    65  	Iterable
    66  	Value
    67  }
    68  
    69  func collectFromIterable(it Iterable) []Value {
    70  	var vs []Value
    71  	if lener, ok := it.(Lener); ok {
    72  		vs = make([]Value, 0, lener.Len())
    73  	}
    74  	it.Iterate(func(v Value) bool {
    75  		vs = append(vs, v)
    76  		return true
    77  	})
    78  	return vs
    79  }
    80  
    81  // IterateKeyer is anything with keys that can be iterated.
    82  type IterateKeyer interface {
    83  	IterateKey(func(Value) bool)
    84  }
    85  
    86  var (
    87  	NoArgs = []Value{}
    88  	NoOpts = map[string]Value{}
    89  )
    90  
    91  // Callable is anything may be called on an evalCtx with a list of Value's.
    92  type Callable interface {
    93  	Call(ec *EvalCtx, args []Value, opts map[string]Value)
    94  }
    95  
    96  type CallableValue interface {
    97  	Value
    98  	Callable
    99  }
   100  
   101  func mustFn(v Value) Callable {
   102  	fn, ok := v.(Callable)
   103  	if !ok {
   104  		throw(fmt.Errorf("a %s is not callable", v.Kind()))
   105  	}
   106  	return fn
   107  }
   108  
   109  // Indexer is anything that can be indexed by Values and yields Values.
   110  type Indexer interface {
   111  	Index(idx []Value) []Value
   112  }
   113  
   114  // IndexOneer is anything that can be indexed by one Value and yields one Value.
   115  type IndexOneer interface {
   116  	IndexOne(idx Value) Value
   117  }
   118  
   119  // IndexSetter is a Value whose elements can be get as well as set.
   120  type IndexSetter interface {
   121  	IndexOneer
   122  	IndexSet(idx Value, v Value)
   123  }
   124  
   125  func mustIndexer(v Value, ec *EvalCtx) Indexer {
   126  	indexer, ok := getIndexer(v, ec)
   127  	if !ok {
   128  		throw(fmt.Errorf("a %s is not indexable", v.Kind()))
   129  	}
   130  	return indexer
   131  }
   132  
   133  // getIndexer adapts a Value to an Indexer if there is an adapter. It adapts a
   134  // Fn if ec is not nil.
   135  func getIndexer(v Value, ec *EvalCtx) (Indexer, bool) {
   136  	if indexer, ok := v.(Indexer); ok {
   137  		return indexer, true
   138  	}
   139  	if indexOneer, ok := v.(IndexOneer); ok {
   140  		return IndexOneerIndexer{indexOneer}, true
   141  	}
   142  	return nil, false
   143  }
   144  
   145  // IndexOneerIndexer adapts an IndexOneer to an Indexer by calling all the
   146  // indicies on the IndexOner and collect the results.
   147  type IndexOneerIndexer struct {
   148  	IndexOneer
   149  }
   150  
   151  func (ioi IndexOneerIndexer) Index(vs []Value) []Value {
   152  	results := make([]Value, len(vs))
   153  	for i, v := range vs {
   154  		results[i] = ioi.IndexOneer.IndexOne(v)
   155  	}
   156  	return results
   157  }
   158  
   159  // Error definitions.
   160  var (
   161  	ErrOnlyStrOrRat = errors.New("only str or rat may be converted to rat")
   162  )
   163  
   164  // Bool represents truthness.
   165  type Bool bool
   166  
   167  func (Bool) Kind() string {
   168  	return "bool"
   169  }
   170  
   171  func (b Bool) Repr(int) string {
   172  	if b {
   173  		return "$true"
   174  	}
   175  	return "$false"
   176  }
   177  
   178  func (b Bool) Bool() bool {
   179  	return bool(b)
   180  }
   181  
   182  // ToBool converts a Value to bool. When the Value type implements Bool(), it
   183  // is used. Otherwise it is considered true.
   184  func ToBool(v Value) bool {
   185  	if b, ok := v.(Booler); ok {
   186  		return b.Bool()
   187  	}
   188  	return true
   189  }
   190  
   191  // Rat is a rational number.
   192  type Rat struct {
   193  	b *big.Rat
   194  }
   195  
   196  func (Rat) Kind() string {
   197  	return "string"
   198  }
   199  
   200  func (r Rat) Repr(int) string {
   201  	return "(rat " + r.String() + ")"
   202  }
   203  
   204  func (r Rat) String() string {
   205  	if r.b.IsInt() {
   206  		return r.b.Num().String()
   207  	}
   208  	return r.b.String()
   209  }
   210  
   211  // ToRat converts a Value to rat. A str can be converted to a rat if it can be
   212  // parsed. A rat is returned as-is. Other types of values cannot be converted.
   213  func ToRat(v Value) (Rat, error) {
   214  	switch v := v.(type) {
   215  	case Rat:
   216  		return v, nil
   217  	case String:
   218  		r := big.Rat{}
   219  		_, err := fmt.Sscanln(string(v), &r)
   220  		if err != nil {
   221  			return Rat{}, fmt.Errorf("%s cannot be parsed as rat", v.Repr(NoPretty))
   222  		}
   223  		return Rat{&r}, nil
   224  	default:
   225  		return Rat{}, ErrOnlyStrOrRat
   226  	}
   227  }
   228  
   229  // FromJSONInterface converts a interface{} that results from json.Unmarshal to
   230  // a Value.
   231  func FromJSONInterface(v interface{}) Value {
   232  	if v == nil {
   233  		// TODO Use a more appropriate type
   234  		return String("")
   235  	}
   236  	switch v.(type) {
   237  	case bool:
   238  		return Bool(v.(bool))
   239  	case float64, string:
   240  		// TODO Use a numeric type for float64
   241  		return String(fmt.Sprint(v))
   242  	case []interface{}:
   243  		a := v.([]interface{})
   244  		vs := make([]Value, len(a))
   245  		for i, v := range a {
   246  			vs[i] = FromJSONInterface(v)
   247  		}
   248  		return NewList(vs...)
   249  	case map[string]interface{}:
   250  		m := v.(map[string]interface{})
   251  		mv := make(map[Value]Value)
   252  		for k, v := range m {
   253  			mv[String(k)] = FromJSONInterface(v)
   254  		}
   255  		return Map{&mv}
   256  	default:
   257  		throw(fmt.Errorf("unexpected json type: %T", v))
   258  		return nil // not reached
   259  	}
   260  }
   261  
   262  // DeepEq compares two Value's deeply.
   263  func DeepEq(a, b Value) bool {
   264  	return reflect.DeepEqual(a, b)
   265  }