xref: /aosp_15_r20/external/starlark-go/starlark/value.go (revision 4947cdc739c985f6d86941e22894f5cefe7c9e9a)
1*4947cdc7SCole Faust// Copyright 2017 The Bazel Authors. All rights reserved.
2*4947cdc7SCole Faust// Use of this source code is governed by a BSD-style
3*4947cdc7SCole Faust// license that can be found in the LICENSE file.
4*4947cdc7SCole Faust
5*4947cdc7SCole Faust// Package starlark provides a Starlark interpreter.
6*4947cdc7SCole Faust//
7*4947cdc7SCole Faust// Starlark values are represented by the Value interface.
8*4947cdc7SCole Faust// The following built-in Value types are known to the evaluator:
9*4947cdc7SCole Faust//
10*4947cdc7SCole Faust//      NoneType        -- NoneType
11*4947cdc7SCole Faust//      Bool            -- bool
12*4947cdc7SCole Faust//      Int             -- int
13*4947cdc7SCole Faust//      Float           -- float
14*4947cdc7SCole Faust//      String          -- string
15*4947cdc7SCole Faust//      *List           -- list
16*4947cdc7SCole Faust//      Tuple           -- tuple
17*4947cdc7SCole Faust//      *Dict           -- dict
18*4947cdc7SCole Faust//      *Set            -- set
19*4947cdc7SCole Faust//      *Function       -- function (implemented in Starlark)
20*4947cdc7SCole Faust//      *Builtin        -- builtin_function_or_method (function or method implemented in Go)
21*4947cdc7SCole Faust//
22*4947cdc7SCole Faust// Client applications may define new data types that satisfy at least
23*4947cdc7SCole Faust// the Value interface.  Such types may provide additional operations by
24*4947cdc7SCole Faust// implementing any of these optional interfaces:
25*4947cdc7SCole Faust//
26*4947cdc7SCole Faust//      Callable        -- value is callable like a function
27*4947cdc7SCole Faust//      Comparable      -- value defines its own comparison operations
28*4947cdc7SCole Faust//      Iterable        -- value is iterable using 'for' loops
29*4947cdc7SCole Faust//      Sequence        -- value is iterable sequence of known length
30*4947cdc7SCole Faust//      Indexable       -- value is sequence with efficient random access
31*4947cdc7SCole Faust//      Mapping         -- value maps from keys to values, like a dictionary
32*4947cdc7SCole Faust//      HasBinary       -- value defines binary operations such as * and +
33*4947cdc7SCole Faust//      HasAttrs        -- value has readable fields or methods x.f
34*4947cdc7SCole Faust//      HasSetField     -- value has settable fields x.f
35*4947cdc7SCole Faust//      HasSetIndex     -- value supports element update using x[i]=y
36*4947cdc7SCole Faust//      HasSetKey       -- value supports map update using x[k]=v
37*4947cdc7SCole Faust//      HasUnary        -- value defines unary operations such as + and -
38*4947cdc7SCole Faust//
39*4947cdc7SCole Faust// Client applications may also define domain-specific functions in Go
40*4947cdc7SCole Faust// and make them available to Starlark programs.  Use NewBuiltin to
41*4947cdc7SCole Faust// construct a built-in value that wraps a Go function.  The
42*4947cdc7SCole Faust// implementation of the Go function may use UnpackArgs to make sense of
43*4947cdc7SCole Faust// the positional and keyword arguments provided by the caller.
44*4947cdc7SCole Faust//
45*4947cdc7SCole Faust// Starlark's None value is not equal to Go's nil. Go's nil is not a legal
46*4947cdc7SCole Faust// Starlark value, but the compiler will not stop you from converting nil
47*4947cdc7SCole Faust// to Value. Be careful to avoid allowing Go nil values to leak into
48*4947cdc7SCole Faust// Starlark data structures.
49*4947cdc7SCole Faust//
50*4947cdc7SCole Faust// The Compare operation requires two arguments of the same
51*4947cdc7SCole Faust// type, but this constraint cannot be expressed in Go's type system.
52*4947cdc7SCole Faust// (This is the classic "binary method problem".)
53*4947cdc7SCole Faust// So, each Value type's CompareSameType method is a partial function
54*4947cdc7SCole Faust// that compares a value only against others of the same type.
55*4947cdc7SCole Faust// Use the package's standalone Compare (or Equal) function to compare
56*4947cdc7SCole Faust// an arbitrary pair of values.
57*4947cdc7SCole Faust//
58*4947cdc7SCole Faust// To parse and evaluate a Starlark source file, use ExecFile.  The Eval
59*4947cdc7SCole Faust// function evaluates a single expression.  All evaluator functions
60*4947cdc7SCole Faust// require a Thread parameter which defines the "thread-local storage"
61*4947cdc7SCole Faust// of a Starlark thread and may be used to plumb application state
62*4947cdc7SCole Faust// through Starlark code and into callbacks.  When evaluation fails it
63*4947cdc7SCole Faust// returns an EvalError from which the application may obtain a
64*4947cdc7SCole Faust// backtrace of active Starlark calls.
65*4947cdc7SCole Faust//
66*4947cdc7SCole Faustpackage starlark // import "go.starlark.net/starlark"
67*4947cdc7SCole Faust
68*4947cdc7SCole Faust// This file defines the data types of Starlark and their basic operations.
69*4947cdc7SCole Faust
70*4947cdc7SCole Faustimport (
71*4947cdc7SCole Faust	"fmt"
72*4947cdc7SCole Faust	"math"
73*4947cdc7SCole Faust	"math/big"
74*4947cdc7SCole Faust	"reflect"
75*4947cdc7SCole Faust	"strconv"
76*4947cdc7SCole Faust	"strings"
77*4947cdc7SCole Faust	"unicode/utf8"
78*4947cdc7SCole Faust
79*4947cdc7SCole Faust	"go.starlark.net/internal/compile"
80*4947cdc7SCole Faust	"go.starlark.net/syntax"
81*4947cdc7SCole Faust)
82*4947cdc7SCole Faust
83*4947cdc7SCole Faust// Value is a value in the Starlark interpreter.
84*4947cdc7SCole Fausttype Value interface {
85*4947cdc7SCole Faust	// String returns the string representation of the value.
86*4947cdc7SCole Faust	// Starlark string values are quoted as if by Python's repr.
87*4947cdc7SCole Faust	String() string
88*4947cdc7SCole Faust
89*4947cdc7SCole Faust	// Type returns a short string describing the value's type.
90*4947cdc7SCole Faust	Type() string
91*4947cdc7SCole Faust
92*4947cdc7SCole Faust	// Freeze causes the value, and all values transitively
93*4947cdc7SCole Faust	// reachable from it through collections and closures, to be
94*4947cdc7SCole Faust	// marked as frozen.  All subsequent mutations to the data
95*4947cdc7SCole Faust	// structure through this API will fail dynamically, making the
96*4947cdc7SCole Faust	// data structure immutable and safe for publishing to other
97*4947cdc7SCole Faust	// Starlark interpreters running concurrently.
98*4947cdc7SCole Faust	Freeze()
99*4947cdc7SCole Faust
100*4947cdc7SCole Faust	// Truth returns the truth value of an object.
101*4947cdc7SCole Faust	Truth() Bool
102*4947cdc7SCole Faust
103*4947cdc7SCole Faust	// Hash returns a function of x such that Equals(x, y) => Hash(x) == Hash(y).
104*4947cdc7SCole Faust	// Hash may fail if the value's type is not hashable, or if the value
105*4947cdc7SCole Faust	// contains a non-hashable value. The hash is used only by dictionaries and
106*4947cdc7SCole Faust	// is not exposed to the Starlark program.
107*4947cdc7SCole Faust	Hash() (uint32, error)
108*4947cdc7SCole Faust}
109*4947cdc7SCole Faust
110*4947cdc7SCole Faust// A Comparable is a value that defines its own equivalence relation and
111*4947cdc7SCole Faust// perhaps ordered comparisons.
112*4947cdc7SCole Fausttype Comparable interface {
113*4947cdc7SCole Faust	Value
114*4947cdc7SCole Faust	// CompareSameType compares one value to another of the same Type().
115*4947cdc7SCole Faust	// The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE.
116*4947cdc7SCole Faust	// CompareSameType returns an error if an ordered comparison was
117*4947cdc7SCole Faust	// requested for a type that does not support it.
118*4947cdc7SCole Faust	//
119*4947cdc7SCole Faust	// Implementations that recursively compare subcomponents of
120*4947cdc7SCole Faust	// the value should use the CompareDepth function, not Compare, to
121*4947cdc7SCole Faust	// avoid infinite recursion on cyclic structures.
122*4947cdc7SCole Faust	//
123*4947cdc7SCole Faust	// The depth parameter is used to bound comparisons of cyclic
124*4947cdc7SCole Faust	// data structures.  Implementations should decrement depth
125*4947cdc7SCole Faust	// before calling CompareDepth and should return an error if depth
126*4947cdc7SCole Faust	// < 1.
127*4947cdc7SCole Faust	//
128*4947cdc7SCole Faust	// Client code should not call this method.  Instead, use the
129*4947cdc7SCole Faust	// standalone Compare or Equals functions, which are defined for
130*4947cdc7SCole Faust	// all pairs of operands.
131*4947cdc7SCole Faust	CompareSameType(op syntax.Token, y Value, depth int) (bool, error)
132*4947cdc7SCole Faust}
133*4947cdc7SCole Faust
134*4947cdc7SCole Faustvar (
135*4947cdc7SCole Faust	_ Comparable = Int{}
136*4947cdc7SCole Faust	_ Comparable = False
137*4947cdc7SCole Faust	_ Comparable = Float(0)
138*4947cdc7SCole Faust	_ Comparable = String("")
139*4947cdc7SCole Faust	_ Comparable = (*Dict)(nil)
140*4947cdc7SCole Faust	_ Comparable = (*List)(nil)
141*4947cdc7SCole Faust	_ Comparable = Tuple(nil)
142*4947cdc7SCole Faust	_ Comparable = (*Set)(nil)
143*4947cdc7SCole Faust)
144*4947cdc7SCole Faust
145*4947cdc7SCole Faust// A Callable value f may be the operand of a function call, f(x).
146*4947cdc7SCole Faust//
147*4947cdc7SCole Faust// Clients should use the Call function, never the CallInternal method.
148*4947cdc7SCole Fausttype Callable interface {
149*4947cdc7SCole Faust	Value
150*4947cdc7SCole Faust	Name() string
151*4947cdc7SCole Faust	CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error)
152*4947cdc7SCole Faust}
153*4947cdc7SCole Faust
154*4947cdc7SCole Fausttype callableWithPosition interface {
155*4947cdc7SCole Faust	Callable
156*4947cdc7SCole Faust	Position() syntax.Position
157*4947cdc7SCole Faust}
158*4947cdc7SCole Faust
159*4947cdc7SCole Faustvar (
160*4947cdc7SCole Faust	_ Callable             = (*Builtin)(nil)
161*4947cdc7SCole Faust	_ Callable             = (*Function)(nil)
162*4947cdc7SCole Faust	_ callableWithPosition = (*Function)(nil)
163*4947cdc7SCole Faust)
164*4947cdc7SCole Faust
165*4947cdc7SCole Faust// An Iterable abstracts a sequence of values.
166*4947cdc7SCole Faust// An iterable value may be iterated over by a 'for' loop or used where
167*4947cdc7SCole Faust// any other Starlark iterable is allowed.  Unlike a Sequence, the length
168*4947cdc7SCole Faust// of an Iterable is not necessarily known in advance of iteration.
169*4947cdc7SCole Fausttype Iterable interface {
170*4947cdc7SCole Faust	Value
171*4947cdc7SCole Faust	Iterate() Iterator // must be followed by call to Iterator.Done
172*4947cdc7SCole Faust}
173*4947cdc7SCole Faust
174*4947cdc7SCole Faust// A Sequence is a sequence of values of known length.
175*4947cdc7SCole Fausttype Sequence interface {
176*4947cdc7SCole Faust	Iterable
177*4947cdc7SCole Faust	Len() int
178*4947cdc7SCole Faust}
179*4947cdc7SCole Faust
180*4947cdc7SCole Faustvar (
181*4947cdc7SCole Faust	_ Sequence = (*Dict)(nil)
182*4947cdc7SCole Faust	_ Sequence = (*Set)(nil)
183*4947cdc7SCole Faust)
184*4947cdc7SCole Faust
185*4947cdc7SCole Faust// An Indexable is a sequence of known length that supports efficient random access.
186*4947cdc7SCole Faust// It is not necessarily iterable.
187*4947cdc7SCole Fausttype Indexable interface {
188*4947cdc7SCole Faust	Value
189*4947cdc7SCole Faust	Index(i int) Value // requires 0 <= i < Len()
190*4947cdc7SCole Faust	Len() int
191*4947cdc7SCole Faust}
192*4947cdc7SCole Faust
193*4947cdc7SCole Faust// A Sliceable is a sequence that can be cut into pieces with the slice operator (x[i:j:step]).
194*4947cdc7SCole Faust//
195*4947cdc7SCole Faust// All native indexable objects are sliceable.
196*4947cdc7SCole Faust// This is a separate interface for backwards-compatibility.
197*4947cdc7SCole Fausttype Sliceable interface {
198*4947cdc7SCole Faust	Indexable
199*4947cdc7SCole Faust	// For positive strides (step > 0), 0 <= start <= end <= n.
200*4947cdc7SCole Faust	// For negative strides (step < 0), -1 <= end <= start < n.
201*4947cdc7SCole Faust	// The caller must ensure that the start and end indices are valid
202*4947cdc7SCole Faust	// and that step is non-zero.
203*4947cdc7SCole Faust	Slice(start, end, step int) Value
204*4947cdc7SCole Faust}
205*4947cdc7SCole Faust
206*4947cdc7SCole Faust// A HasSetIndex is an Indexable value whose elements may be assigned (x[i] = y).
207*4947cdc7SCole Faust//
208*4947cdc7SCole Faust// The implementation should not add Len to a negative index as the
209*4947cdc7SCole Faust// evaluator does this before the call.
210*4947cdc7SCole Fausttype HasSetIndex interface {
211*4947cdc7SCole Faust	Indexable
212*4947cdc7SCole Faust	SetIndex(index int, v Value) error
213*4947cdc7SCole Faust}
214*4947cdc7SCole Faust
215*4947cdc7SCole Faustvar (
216*4947cdc7SCole Faust	_ HasSetIndex = (*List)(nil)
217*4947cdc7SCole Faust	_ Indexable   = Tuple(nil)
218*4947cdc7SCole Faust	_ Indexable   = String("")
219*4947cdc7SCole Faust	_ Sliceable   = Tuple(nil)
220*4947cdc7SCole Faust	_ Sliceable   = String("")
221*4947cdc7SCole Faust	_ Sliceable   = (*List)(nil)
222*4947cdc7SCole Faust)
223*4947cdc7SCole Faust
224*4947cdc7SCole Faust// An Iterator provides a sequence of values to the caller.
225*4947cdc7SCole Faust//
226*4947cdc7SCole Faust// The caller must call Done when the iterator is no longer needed.
227*4947cdc7SCole Faust// Operations that modify a sequence will fail if it has active iterators.
228*4947cdc7SCole Faust//
229*4947cdc7SCole Faust// Example usage:
230*4947cdc7SCole Faust//
231*4947cdc7SCole Faust// 	iter := iterable.Iterator()
232*4947cdc7SCole Faust//	defer iter.Done()
233*4947cdc7SCole Faust//	var x Value
234*4947cdc7SCole Faust//	for iter.Next(&x) {
235*4947cdc7SCole Faust//		...
236*4947cdc7SCole Faust//	}
237*4947cdc7SCole Faust//
238*4947cdc7SCole Fausttype Iterator interface {
239*4947cdc7SCole Faust	// If the iterator is exhausted, Next returns false.
240*4947cdc7SCole Faust	// Otherwise it sets *p to the current element of the sequence,
241*4947cdc7SCole Faust	// advances the iterator, and returns true.
242*4947cdc7SCole Faust	Next(p *Value) bool
243*4947cdc7SCole Faust	Done()
244*4947cdc7SCole Faust}
245*4947cdc7SCole Faust
246*4947cdc7SCole Faust// A Mapping is a mapping from keys to values, such as a dictionary.
247*4947cdc7SCole Faust//
248*4947cdc7SCole Faust// If a type satisfies both Mapping and Iterable, the iterator yields
249*4947cdc7SCole Faust// the keys of the mapping.
250*4947cdc7SCole Fausttype Mapping interface {
251*4947cdc7SCole Faust	Value
252*4947cdc7SCole Faust	// Get returns the value corresponding to the specified key,
253*4947cdc7SCole Faust	// or !found if the mapping does not contain the key.
254*4947cdc7SCole Faust	//
255*4947cdc7SCole Faust	// Get also defines the behavior of "v in mapping".
256*4947cdc7SCole Faust	// The 'in' operator reports the 'found' component, ignoring errors.
257*4947cdc7SCole Faust	Get(Value) (v Value, found bool, err error)
258*4947cdc7SCole Faust}
259*4947cdc7SCole Faust
260*4947cdc7SCole Faust// An IterableMapping is a mapping that supports key enumeration.
261*4947cdc7SCole Fausttype IterableMapping interface {
262*4947cdc7SCole Faust	Mapping
263*4947cdc7SCole Faust	Iterate() Iterator // see Iterable interface
264*4947cdc7SCole Faust	Items() []Tuple    // a new slice containing all key/value pairs
265*4947cdc7SCole Faust}
266*4947cdc7SCole Faust
267*4947cdc7SCole Faustvar _ IterableMapping = (*Dict)(nil)
268*4947cdc7SCole Faust
269*4947cdc7SCole Faust// A HasSetKey supports map update using x[k]=v syntax, like a dictionary.
270*4947cdc7SCole Fausttype HasSetKey interface {
271*4947cdc7SCole Faust	Mapping
272*4947cdc7SCole Faust	SetKey(k, v Value) error
273*4947cdc7SCole Faust}
274*4947cdc7SCole Faust
275*4947cdc7SCole Faustvar _ HasSetKey = (*Dict)(nil)
276*4947cdc7SCole Faust
277*4947cdc7SCole Faust// A HasBinary value may be used as either operand of these binary operators:
278*4947cdc7SCole Faust//     +   -   *   /   //   %   in   not in   |   &   ^   <<   >>
279*4947cdc7SCole Faust//
280*4947cdc7SCole Faust// The Side argument indicates whether the receiver is the left or right operand.
281*4947cdc7SCole Faust//
282*4947cdc7SCole Faust// An implementation may decline to handle an operation by returning (nil, nil).
283*4947cdc7SCole Faust// For this reason, clients should always call the standalone Binary(op, x, y)
284*4947cdc7SCole Faust// function rather than calling the method directly.
285*4947cdc7SCole Fausttype HasBinary interface {
286*4947cdc7SCole Faust	Value
287*4947cdc7SCole Faust	Binary(op syntax.Token, y Value, side Side) (Value, error)
288*4947cdc7SCole Faust}
289*4947cdc7SCole Faust
290*4947cdc7SCole Fausttype Side bool
291*4947cdc7SCole Faust
292*4947cdc7SCole Faustconst (
293*4947cdc7SCole Faust	Left  Side = false
294*4947cdc7SCole Faust	Right Side = true
295*4947cdc7SCole Faust)
296*4947cdc7SCole Faust
297*4947cdc7SCole Faust// A HasUnary value may be used as the operand of these unary operators:
298*4947cdc7SCole Faust//     +   -   ~
299*4947cdc7SCole Faust//
300*4947cdc7SCole Faust// An implementation may decline to handle an operation by returning (nil, nil).
301*4947cdc7SCole Faust// For this reason, clients should always call the standalone Unary(op, x)
302*4947cdc7SCole Faust// function rather than calling the method directly.
303*4947cdc7SCole Fausttype HasUnary interface {
304*4947cdc7SCole Faust	Value
305*4947cdc7SCole Faust	Unary(op syntax.Token) (Value, error)
306*4947cdc7SCole Faust}
307*4947cdc7SCole Faust
308*4947cdc7SCole Faust// A HasAttrs value has fields or methods that may be read by a dot expression (y = x.f).
309*4947cdc7SCole Faust// Attribute names may be listed using the built-in 'dir' function.
310*4947cdc7SCole Faust//
311*4947cdc7SCole Faust// For implementation convenience, a result of (nil, nil) from Attr is
312*4947cdc7SCole Faust// interpreted as a "no such field or method" error. Implementations are
313*4947cdc7SCole Faust// free to return a more precise error.
314*4947cdc7SCole Fausttype HasAttrs interface {
315*4947cdc7SCole Faust	Value
316*4947cdc7SCole Faust	Attr(name string) (Value, error) // returns (nil, nil) if attribute not present
317*4947cdc7SCole Faust	AttrNames() []string             // callers must not modify the result.
318*4947cdc7SCole Faust}
319*4947cdc7SCole Faust
320*4947cdc7SCole Faustvar (
321*4947cdc7SCole Faust	_ HasAttrs = String("")
322*4947cdc7SCole Faust	_ HasAttrs = new(List)
323*4947cdc7SCole Faust	_ HasAttrs = new(Dict)
324*4947cdc7SCole Faust	_ HasAttrs = new(Set)
325*4947cdc7SCole Faust)
326*4947cdc7SCole Faust
327*4947cdc7SCole Faust// A HasSetField value has fields that may be written by a dot expression (x.f = y).
328*4947cdc7SCole Faust//
329*4947cdc7SCole Faust// An implementation of SetField may return a NoSuchAttrError,
330*4947cdc7SCole Faust// in which case the runtime may augment the error message to
331*4947cdc7SCole Faust// warn of possible misspelling.
332*4947cdc7SCole Fausttype HasSetField interface {
333*4947cdc7SCole Faust	HasAttrs
334*4947cdc7SCole Faust	SetField(name string, val Value) error
335*4947cdc7SCole Faust}
336*4947cdc7SCole Faust
337*4947cdc7SCole Faust// A NoSuchAttrError may be returned by an implementation of
338*4947cdc7SCole Faust// HasAttrs.Attr or HasSetField.SetField to indicate that no such field
339*4947cdc7SCole Faust// exists. In that case the runtime may augment the error message to
340*4947cdc7SCole Faust// warn of possible misspelling.
341*4947cdc7SCole Fausttype NoSuchAttrError string
342*4947cdc7SCole Faust
343*4947cdc7SCole Faustfunc (e NoSuchAttrError) Error() string { return string(e) }
344*4947cdc7SCole Faust
345*4947cdc7SCole Faust// NoneType is the type of None.  Its only legal value is None.
346*4947cdc7SCole Faust// (We represent it as a number, not struct{}, so that None may be constant.)
347*4947cdc7SCole Fausttype NoneType byte
348*4947cdc7SCole Faust
349*4947cdc7SCole Faustconst None = NoneType(0)
350*4947cdc7SCole Faust
351*4947cdc7SCole Faustfunc (NoneType) String() string        { return "None" }
352*4947cdc7SCole Faustfunc (NoneType) Type() string          { return "NoneType" }
353*4947cdc7SCole Faustfunc (NoneType) Freeze()               {} // immutable
354*4947cdc7SCole Faustfunc (NoneType) Truth() Bool           { return False }
355*4947cdc7SCole Faustfunc (NoneType) Hash() (uint32, error) { return 0, nil }
356*4947cdc7SCole Faust
357*4947cdc7SCole Faust// Bool is the type of a Starlark bool.
358*4947cdc7SCole Fausttype Bool bool
359*4947cdc7SCole Faust
360*4947cdc7SCole Faustconst (
361*4947cdc7SCole Faust	False Bool = false
362*4947cdc7SCole Faust	True  Bool = true
363*4947cdc7SCole Faust)
364*4947cdc7SCole Faust
365*4947cdc7SCole Faustfunc (b Bool) String() string {
366*4947cdc7SCole Faust	if b {
367*4947cdc7SCole Faust		return "True"
368*4947cdc7SCole Faust	} else {
369*4947cdc7SCole Faust		return "False"
370*4947cdc7SCole Faust	}
371*4947cdc7SCole Faust}
372*4947cdc7SCole Faustfunc (b Bool) Type() string          { return "bool" }
373*4947cdc7SCole Faustfunc (b Bool) Freeze()               {} // immutable
374*4947cdc7SCole Faustfunc (b Bool) Truth() Bool           { return b }
375*4947cdc7SCole Faustfunc (b Bool) Hash() (uint32, error) { return uint32(b2i(bool(b))), nil }
376*4947cdc7SCole Faustfunc (x Bool) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
377*4947cdc7SCole Faust	y := y_.(Bool)
378*4947cdc7SCole Faust	return threeway(op, b2i(bool(x))-b2i(bool(y))), nil
379*4947cdc7SCole Faust}
380*4947cdc7SCole Faust
381*4947cdc7SCole Faust// Float is the type of a Starlark float.
382*4947cdc7SCole Fausttype Float float64
383*4947cdc7SCole Faust
384*4947cdc7SCole Faustfunc (f Float) String() string {
385*4947cdc7SCole Faust	var buf strings.Builder
386*4947cdc7SCole Faust	f.format(&buf, 'g')
387*4947cdc7SCole Faust	return buf.String()
388*4947cdc7SCole Faust}
389*4947cdc7SCole Faust
390*4947cdc7SCole Faustfunc (f Float) format(buf *strings.Builder, conv byte) {
391*4947cdc7SCole Faust	ff := float64(f)
392*4947cdc7SCole Faust	if !isFinite(ff) {
393*4947cdc7SCole Faust		if math.IsInf(ff, +1) {
394*4947cdc7SCole Faust			buf.WriteString("+inf")
395*4947cdc7SCole Faust		} else if math.IsInf(ff, -1) {
396*4947cdc7SCole Faust			buf.WriteString("-inf")
397*4947cdc7SCole Faust		} else {
398*4947cdc7SCole Faust			buf.WriteString("nan")
399*4947cdc7SCole Faust		}
400*4947cdc7SCole Faust		return
401*4947cdc7SCole Faust	}
402*4947cdc7SCole Faust
403*4947cdc7SCole Faust	// %g is the default format used by str.
404*4947cdc7SCole Faust	// It uses the minimum precision to avoid ambiguity,
405*4947cdc7SCole Faust	// and always includes a '.' or an 'e' so that the value
406*4947cdc7SCole Faust	// is self-evidently a float, not an int.
407*4947cdc7SCole Faust	if conv == 'g' || conv == 'G' {
408*4947cdc7SCole Faust		s := strconv.FormatFloat(ff, conv, -1, 64)
409*4947cdc7SCole Faust		buf.WriteString(s)
410*4947cdc7SCole Faust		// Ensure result always has a decimal point if no exponent.
411*4947cdc7SCole Faust		// "123" -> "123.0"
412*4947cdc7SCole Faust		if strings.IndexByte(s, conv-'g'+'e') < 0 && strings.IndexByte(s, '.') < 0 {
413*4947cdc7SCole Faust			buf.WriteString(".0")
414*4947cdc7SCole Faust		}
415*4947cdc7SCole Faust		return
416*4947cdc7SCole Faust	}
417*4947cdc7SCole Faust
418*4947cdc7SCole Faust	// %[eEfF] use 6-digit precision
419*4947cdc7SCole Faust	buf.WriteString(strconv.FormatFloat(ff, conv, 6, 64))
420*4947cdc7SCole Faust}
421*4947cdc7SCole Faust
422*4947cdc7SCole Faustfunc (f Float) Type() string { return "float" }
423*4947cdc7SCole Faustfunc (f Float) Freeze()      {} // immutable
424*4947cdc7SCole Faustfunc (f Float) Truth() Bool  { return f != 0.0 }
425*4947cdc7SCole Faustfunc (f Float) Hash() (uint32, error) {
426*4947cdc7SCole Faust	// Equal float and int values must yield the same hash.
427*4947cdc7SCole Faust	// TODO(adonovan): opt: if f is non-integral, and thus not equal
428*4947cdc7SCole Faust	// to any Int, we can avoid the Int conversion and use a cheaper hash.
429*4947cdc7SCole Faust	if isFinite(float64(f)) {
430*4947cdc7SCole Faust		return finiteFloatToInt(f).Hash()
431*4947cdc7SCole Faust	}
432*4947cdc7SCole Faust	return 1618033, nil // NaN, +/-Inf
433*4947cdc7SCole Faust}
434*4947cdc7SCole Faust
435*4947cdc7SCole Faustfunc floor(f Float) Float { return Float(math.Floor(float64(f))) }
436*4947cdc7SCole Faust
437*4947cdc7SCole Faust// isFinite reports whether f represents a finite rational value.
438*4947cdc7SCole Faust// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
439*4947cdc7SCole Faustfunc isFinite(f float64) bool {
440*4947cdc7SCole Faust	return math.Abs(f) <= math.MaxFloat64
441*4947cdc7SCole Faust}
442*4947cdc7SCole Faust
443*4947cdc7SCole Faustfunc (x Float) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
444*4947cdc7SCole Faust	y := y_.(Float)
445*4947cdc7SCole Faust	return threeway(op, floatCmp(x, y)), nil
446*4947cdc7SCole Faust}
447*4947cdc7SCole Faust
448*4947cdc7SCole Faust// floatCmp performs a three-valued comparison on floats,
449*4947cdc7SCole Faust// which are totally ordered with NaN > +Inf.
450*4947cdc7SCole Faustfunc floatCmp(x, y Float) int {
451*4947cdc7SCole Faust	if x > y {
452*4947cdc7SCole Faust		return +1
453*4947cdc7SCole Faust	} else if x < y {
454*4947cdc7SCole Faust		return -1
455*4947cdc7SCole Faust	} else if x == y {
456*4947cdc7SCole Faust		return 0
457*4947cdc7SCole Faust	}
458*4947cdc7SCole Faust
459*4947cdc7SCole Faust	// At least one operand is NaN.
460*4947cdc7SCole Faust	if x == x {
461*4947cdc7SCole Faust		return -1 // y is NaN
462*4947cdc7SCole Faust	} else if y == y {
463*4947cdc7SCole Faust		return +1 // x is NaN
464*4947cdc7SCole Faust	}
465*4947cdc7SCole Faust	return 0 // both NaN
466*4947cdc7SCole Faust}
467*4947cdc7SCole Faust
468*4947cdc7SCole Faustfunc (f Float) rational() *big.Rat { return new(big.Rat).SetFloat64(float64(f)) }
469*4947cdc7SCole Faust
470*4947cdc7SCole Faust// AsFloat returns the float64 value closest to x.
471*4947cdc7SCole Faust// The f result is undefined if x is not a float or Int.
472*4947cdc7SCole Faust// The result may be infinite if x is a very large Int.
473*4947cdc7SCole Faustfunc AsFloat(x Value) (f float64, ok bool) {
474*4947cdc7SCole Faust	switch x := x.(type) {
475*4947cdc7SCole Faust	case Float:
476*4947cdc7SCole Faust		return float64(x), true
477*4947cdc7SCole Faust	case Int:
478*4947cdc7SCole Faust		return float64(x.Float()), true
479*4947cdc7SCole Faust	}
480*4947cdc7SCole Faust	return 0, false
481*4947cdc7SCole Faust}
482*4947cdc7SCole Faust
483*4947cdc7SCole Faustfunc (x Float) Mod(y Float) Float {
484*4947cdc7SCole Faust	z := Float(math.Mod(float64(x), float64(y)))
485*4947cdc7SCole Faust	if (x < 0) != (y < 0) && z != 0 {
486*4947cdc7SCole Faust		z += y
487*4947cdc7SCole Faust	}
488*4947cdc7SCole Faust	return z
489*4947cdc7SCole Faust}
490*4947cdc7SCole Faust
491*4947cdc7SCole Faust// Unary implements the operations +float and -float.
492*4947cdc7SCole Faustfunc (f Float) Unary(op syntax.Token) (Value, error) {
493*4947cdc7SCole Faust	switch op {
494*4947cdc7SCole Faust	case syntax.MINUS:
495*4947cdc7SCole Faust		return -f, nil
496*4947cdc7SCole Faust	case syntax.PLUS:
497*4947cdc7SCole Faust		return +f, nil
498*4947cdc7SCole Faust	}
499*4947cdc7SCole Faust	return nil, nil
500*4947cdc7SCole Faust}
501*4947cdc7SCole Faust
502*4947cdc7SCole Faust// String is the type of a Starlark text string.
503*4947cdc7SCole Faust//
504*4947cdc7SCole Faust// A String encapsulates an an immutable sequence of bytes,
505*4947cdc7SCole Faust// but strings are not directly iterable. Instead, iterate
506*4947cdc7SCole Faust// over the result of calling one of these four methods:
507*4947cdc7SCole Faust// codepoints, codepoint_ords, elems, elem_ords.
508*4947cdc7SCole Faust//
509*4947cdc7SCole Faust// Strings typically contain text; use Bytes for binary strings.
510*4947cdc7SCole Faust// The Starlark spec defines text strings as sequences of UTF-k
511*4947cdc7SCole Faust// codes that encode Unicode code points. In this Go implementation,
512*4947cdc7SCole Faust// k=8, whereas in a Java implementation, k=16. For portability,
513*4947cdc7SCole Faust// operations on strings should aim to avoid assumptions about
514*4947cdc7SCole Faust// the value of k.
515*4947cdc7SCole Faust//
516*4947cdc7SCole Faust// Warning: the contract of the Value interface's String method is that
517*4947cdc7SCole Faust// it returns the value printed in Starlark notation,
518*4947cdc7SCole Faust// so s.String() or fmt.Sprintf("%s", s) returns a quoted string.
519*4947cdc7SCole Faust// Use string(s) or s.GoString() or fmt.Sprintf("%#v", s) to obtain the raw contents
520*4947cdc7SCole Faust// of a Starlark string as a Go string.
521*4947cdc7SCole Fausttype String string
522*4947cdc7SCole Faust
523*4947cdc7SCole Faustfunc (s String) String() string        { return syntax.Quote(string(s), false) }
524*4947cdc7SCole Faustfunc (s String) GoString() string      { return string(s) }
525*4947cdc7SCole Faustfunc (s String) Type() string          { return "string" }
526*4947cdc7SCole Faustfunc (s String) Freeze()               {} // immutable
527*4947cdc7SCole Faustfunc (s String) Truth() Bool           { return len(s) > 0 }
528*4947cdc7SCole Faustfunc (s String) Hash() (uint32, error) { return hashString(string(s)), nil }
529*4947cdc7SCole Faustfunc (s String) Len() int              { return len(s) } // bytes
530*4947cdc7SCole Faustfunc (s String) Index(i int) Value     { return s[i : i+1] }
531*4947cdc7SCole Faust
532*4947cdc7SCole Faustfunc (s String) Slice(start, end, step int) Value {
533*4947cdc7SCole Faust	if step == 1 {
534*4947cdc7SCole Faust		return s[start:end]
535*4947cdc7SCole Faust	}
536*4947cdc7SCole Faust
537*4947cdc7SCole Faust	sign := signum(step)
538*4947cdc7SCole Faust	var str []byte
539*4947cdc7SCole Faust	for i := start; signum(end-i) == sign; i += step {
540*4947cdc7SCole Faust		str = append(str, s[i])
541*4947cdc7SCole Faust	}
542*4947cdc7SCole Faust	return String(str)
543*4947cdc7SCole Faust}
544*4947cdc7SCole Faust
545*4947cdc7SCole Faustfunc (s String) Attr(name string) (Value, error) { return builtinAttr(s, name, stringMethods) }
546*4947cdc7SCole Faustfunc (s String) AttrNames() []string             { return builtinAttrNames(stringMethods) }
547*4947cdc7SCole Faust
548*4947cdc7SCole Faustfunc (x String) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
549*4947cdc7SCole Faust	y := y_.(String)
550*4947cdc7SCole Faust	return threeway(op, strings.Compare(string(x), string(y))), nil
551*4947cdc7SCole Faust}
552*4947cdc7SCole Faust
553*4947cdc7SCole Faustfunc AsString(x Value) (string, bool) { v, ok := x.(String); return string(v), ok }
554*4947cdc7SCole Faust
555*4947cdc7SCole Faust// A stringElems is an iterable whose iterator yields a sequence of
556*4947cdc7SCole Faust// elements (bytes), either numerically or as successive substrings.
557*4947cdc7SCole Faust// It is an indexable sequence.
558*4947cdc7SCole Fausttype stringElems struct {
559*4947cdc7SCole Faust	s    String
560*4947cdc7SCole Faust	ords bool
561*4947cdc7SCole Faust}
562*4947cdc7SCole Faust
563*4947cdc7SCole Faustvar (
564*4947cdc7SCole Faust	_ Iterable  = (*stringElems)(nil)
565*4947cdc7SCole Faust	_ Indexable = (*stringElems)(nil)
566*4947cdc7SCole Faust)
567*4947cdc7SCole Faust
568*4947cdc7SCole Faustfunc (si stringElems) String() string {
569*4947cdc7SCole Faust	if si.ords {
570*4947cdc7SCole Faust		return si.s.String() + ".elem_ords()"
571*4947cdc7SCole Faust	} else {
572*4947cdc7SCole Faust		return si.s.String() + ".elems()"
573*4947cdc7SCole Faust	}
574*4947cdc7SCole Faust}
575*4947cdc7SCole Faustfunc (si stringElems) Type() string          { return "string.elems" }
576*4947cdc7SCole Faustfunc (si stringElems) Freeze()               {} // immutable
577*4947cdc7SCole Faustfunc (si stringElems) Truth() Bool           { return True }
578*4947cdc7SCole Faustfunc (si stringElems) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", si.Type()) }
579*4947cdc7SCole Faustfunc (si stringElems) Iterate() Iterator     { return &stringElemsIterator{si, 0} }
580*4947cdc7SCole Faustfunc (si stringElems) Len() int              { return len(si.s) }
581*4947cdc7SCole Faustfunc (si stringElems) Index(i int) Value {
582*4947cdc7SCole Faust	if si.ords {
583*4947cdc7SCole Faust		return MakeInt(int(si.s[i]))
584*4947cdc7SCole Faust	} else {
585*4947cdc7SCole Faust		// TODO(adonovan): opt: preallocate canonical 1-byte strings
586*4947cdc7SCole Faust		// to avoid interface allocation.
587*4947cdc7SCole Faust		return si.s[i : i+1]
588*4947cdc7SCole Faust	}
589*4947cdc7SCole Faust}
590*4947cdc7SCole Faust
591*4947cdc7SCole Fausttype stringElemsIterator struct {
592*4947cdc7SCole Faust	si stringElems
593*4947cdc7SCole Faust	i  int
594*4947cdc7SCole Faust}
595*4947cdc7SCole Faust
596*4947cdc7SCole Faustfunc (it *stringElemsIterator) Next(p *Value) bool {
597*4947cdc7SCole Faust	if it.i == len(it.si.s) {
598*4947cdc7SCole Faust		return false
599*4947cdc7SCole Faust	}
600*4947cdc7SCole Faust	*p = it.si.Index(it.i)
601*4947cdc7SCole Faust	it.i++
602*4947cdc7SCole Faust	return true
603*4947cdc7SCole Faust}
604*4947cdc7SCole Faust
605*4947cdc7SCole Faustfunc (*stringElemsIterator) Done() {}
606*4947cdc7SCole Faust
607*4947cdc7SCole Faust// A stringCodepoints is an iterable whose iterator yields a sequence of
608*4947cdc7SCole Faust// Unicode code points, either numerically or as successive substrings.
609*4947cdc7SCole Faust// It is not indexable.
610*4947cdc7SCole Fausttype stringCodepoints struct {
611*4947cdc7SCole Faust	s    String
612*4947cdc7SCole Faust	ords bool
613*4947cdc7SCole Faust}
614*4947cdc7SCole Faust
615*4947cdc7SCole Faustvar _ Iterable = (*stringCodepoints)(nil)
616*4947cdc7SCole Faust
617*4947cdc7SCole Faustfunc (si stringCodepoints) String() string {
618*4947cdc7SCole Faust	if si.ords {
619*4947cdc7SCole Faust		return si.s.String() + ".codepoint_ords()"
620*4947cdc7SCole Faust	} else {
621*4947cdc7SCole Faust		return si.s.String() + ".codepoints()"
622*4947cdc7SCole Faust	}
623*4947cdc7SCole Faust}
624*4947cdc7SCole Faustfunc (si stringCodepoints) Type() string          { return "string.codepoints" }
625*4947cdc7SCole Faustfunc (si stringCodepoints) Freeze()               {} // immutable
626*4947cdc7SCole Faustfunc (si stringCodepoints) Truth() Bool           { return True }
627*4947cdc7SCole Faustfunc (si stringCodepoints) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", si.Type()) }
628*4947cdc7SCole Faustfunc (si stringCodepoints) Iterate() Iterator     { return &stringCodepointsIterator{si, 0} }
629*4947cdc7SCole Faust
630*4947cdc7SCole Fausttype stringCodepointsIterator struct {
631*4947cdc7SCole Faust	si stringCodepoints
632*4947cdc7SCole Faust	i  int
633*4947cdc7SCole Faust}
634*4947cdc7SCole Faust
635*4947cdc7SCole Faustfunc (it *stringCodepointsIterator) Next(p *Value) bool {
636*4947cdc7SCole Faust	s := it.si.s[it.i:]
637*4947cdc7SCole Faust	if s == "" {
638*4947cdc7SCole Faust		return false
639*4947cdc7SCole Faust	}
640*4947cdc7SCole Faust	r, sz := utf8.DecodeRuneInString(string(s))
641*4947cdc7SCole Faust	if !it.si.ords {
642*4947cdc7SCole Faust		if r == utf8.RuneError {
643*4947cdc7SCole Faust			*p = String(r)
644*4947cdc7SCole Faust		} else {
645*4947cdc7SCole Faust			*p = s[:sz]
646*4947cdc7SCole Faust		}
647*4947cdc7SCole Faust	} else {
648*4947cdc7SCole Faust		*p = MakeInt(int(r))
649*4947cdc7SCole Faust	}
650*4947cdc7SCole Faust	it.i += sz
651*4947cdc7SCole Faust	return true
652*4947cdc7SCole Faust}
653*4947cdc7SCole Faust
654*4947cdc7SCole Faustfunc (*stringCodepointsIterator) Done() {}
655*4947cdc7SCole Faust
656*4947cdc7SCole Faust// A Function is a function defined by a Starlark def statement or lambda expression.
657*4947cdc7SCole Faust// The initialization behavior of a Starlark module is also represented by a Function.
658*4947cdc7SCole Fausttype Function struct {
659*4947cdc7SCole Faust	funcode  *compile.Funcode
660*4947cdc7SCole Faust	module   *module
661*4947cdc7SCole Faust	defaults Tuple
662*4947cdc7SCole Faust	freevars Tuple
663*4947cdc7SCole Faust}
664*4947cdc7SCole Faust
665*4947cdc7SCole Faust// A module is the dynamic counterpart to a Program.
666*4947cdc7SCole Faust// All functions in the same program share a module.
667*4947cdc7SCole Fausttype module struct {
668*4947cdc7SCole Faust	program     *compile.Program
669*4947cdc7SCole Faust	predeclared StringDict
670*4947cdc7SCole Faust	globals     []Value
671*4947cdc7SCole Faust	constants   []Value
672*4947cdc7SCole Faust}
673*4947cdc7SCole Faust
674*4947cdc7SCole Faust// makeGlobalDict returns a new, unfrozen StringDict containing all global
675*4947cdc7SCole Faust// variables so far defined in the module.
676*4947cdc7SCole Faustfunc (m *module) makeGlobalDict() StringDict {
677*4947cdc7SCole Faust	r := make(StringDict, len(m.program.Globals))
678*4947cdc7SCole Faust	for i, id := range m.program.Globals {
679*4947cdc7SCole Faust		if v := m.globals[i]; v != nil {
680*4947cdc7SCole Faust			r[id.Name] = v
681*4947cdc7SCole Faust		}
682*4947cdc7SCole Faust	}
683*4947cdc7SCole Faust	return r
684*4947cdc7SCole Faust}
685*4947cdc7SCole Faust
686*4947cdc7SCole Faustfunc (fn *Function) Name() string          { return fn.funcode.Name } // "lambda" for anonymous functions
687*4947cdc7SCole Faustfunc (fn *Function) Doc() string           { return fn.funcode.Doc }
688*4947cdc7SCole Faustfunc (fn *Function) Hash() (uint32, error) { return hashString(fn.funcode.Name), nil }
689*4947cdc7SCole Faustfunc (fn *Function) Freeze()               { fn.defaults.Freeze(); fn.freevars.Freeze() }
690*4947cdc7SCole Faustfunc (fn *Function) String() string        { return toString(fn) }
691*4947cdc7SCole Faustfunc (fn *Function) Type() string          { return "function" }
692*4947cdc7SCole Faustfunc (fn *Function) Truth() Bool           { return true }
693*4947cdc7SCole Faust
694*4947cdc7SCole Faust// Globals returns a new, unfrozen StringDict containing all global
695*4947cdc7SCole Faust// variables so far defined in the function's module.
696*4947cdc7SCole Faustfunc (fn *Function) Globals() StringDict { return fn.module.makeGlobalDict() }
697*4947cdc7SCole Faust
698*4947cdc7SCole Faustfunc (fn *Function) Position() syntax.Position { return fn.funcode.Pos }
699*4947cdc7SCole Faustfunc (fn *Function) NumParams() int            { return fn.funcode.NumParams }
700*4947cdc7SCole Faustfunc (fn *Function) NumKwonlyParams() int      { return fn.funcode.NumKwonlyParams }
701*4947cdc7SCole Faust
702*4947cdc7SCole Faust// Param returns the name and position of the ith parameter,
703*4947cdc7SCole Faust// where 0 <= i < NumParams().
704*4947cdc7SCole Faust// The *args and **kwargs parameters are at the end
705*4947cdc7SCole Faust// even if there were optional parameters after *args.
706*4947cdc7SCole Faustfunc (fn *Function) Param(i int) (string, syntax.Position) {
707*4947cdc7SCole Faust	if i >= fn.NumParams() {
708*4947cdc7SCole Faust		panic(i)
709*4947cdc7SCole Faust	}
710*4947cdc7SCole Faust	id := fn.funcode.Locals[i]
711*4947cdc7SCole Faust	return id.Name, id.Pos
712*4947cdc7SCole Faust}
713*4947cdc7SCole Faustfunc (fn *Function) HasVarargs() bool { return fn.funcode.HasVarargs }
714*4947cdc7SCole Faustfunc (fn *Function) HasKwargs() bool  { return fn.funcode.HasKwargs }
715*4947cdc7SCole Faust
716*4947cdc7SCole Faust// A Builtin is a function implemented in Go.
717*4947cdc7SCole Fausttype Builtin struct {
718*4947cdc7SCole Faust	name string
719*4947cdc7SCole Faust	fn   func(thread *Thread, fn *Builtin, args Tuple, kwargs []Tuple) (Value, error)
720*4947cdc7SCole Faust	recv Value // for bound methods (e.g. "".startswith)
721*4947cdc7SCole Faust}
722*4947cdc7SCole Faust
723*4947cdc7SCole Faustfunc (b *Builtin) Name() string { return b.name }
724*4947cdc7SCole Faustfunc (b *Builtin) Freeze() {
725*4947cdc7SCole Faust	if b.recv != nil {
726*4947cdc7SCole Faust		b.recv.Freeze()
727*4947cdc7SCole Faust	}
728*4947cdc7SCole Faust}
729*4947cdc7SCole Faustfunc (b *Builtin) Hash() (uint32, error) {
730*4947cdc7SCole Faust	h := hashString(b.name)
731*4947cdc7SCole Faust	if b.recv != nil {
732*4947cdc7SCole Faust		h ^= 5521
733*4947cdc7SCole Faust	}
734*4947cdc7SCole Faust	return h, nil
735*4947cdc7SCole Faust}
736*4947cdc7SCole Faustfunc (b *Builtin) Receiver() Value { return b.recv }
737*4947cdc7SCole Faustfunc (b *Builtin) String() string  { return toString(b) }
738*4947cdc7SCole Faustfunc (b *Builtin) Type() string    { return "builtin_function_or_method" }
739*4947cdc7SCole Faustfunc (b *Builtin) CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error) {
740*4947cdc7SCole Faust	return b.fn(thread, b, args, kwargs)
741*4947cdc7SCole Faust}
742*4947cdc7SCole Faustfunc (b *Builtin) Truth() Bool { return true }
743*4947cdc7SCole Faust
744*4947cdc7SCole Faust// NewBuiltin returns a new 'builtin_function_or_method' value with the specified name
745*4947cdc7SCole Faust// and implementation.  It compares unequal with all other values.
746*4947cdc7SCole Faustfunc NewBuiltin(name string, fn func(thread *Thread, fn *Builtin, args Tuple, kwargs []Tuple) (Value, error)) *Builtin {
747*4947cdc7SCole Faust	return &Builtin{name: name, fn: fn}
748*4947cdc7SCole Faust}
749*4947cdc7SCole Faust
750*4947cdc7SCole Faust// BindReceiver returns a new Builtin value representing a method
751*4947cdc7SCole Faust// closure, that is, a built-in function bound to a receiver value.
752*4947cdc7SCole Faust//
753*4947cdc7SCole Faust// In the example below, the value of f is the string.index
754*4947cdc7SCole Faust// built-in method bound to the receiver value "abc":
755*4947cdc7SCole Faust//
756*4947cdc7SCole Faust//     f = "abc".index; f("a"); f("b")
757*4947cdc7SCole Faust//
758*4947cdc7SCole Faust// In the common case, the receiver is bound only during the call,
759*4947cdc7SCole Faust// but this still results in the creation of a temporary method closure:
760*4947cdc7SCole Faust//
761*4947cdc7SCole Faust//     "abc".index("a")
762*4947cdc7SCole Faust//
763*4947cdc7SCole Faustfunc (b *Builtin) BindReceiver(recv Value) *Builtin {
764*4947cdc7SCole Faust	return &Builtin{name: b.name, fn: b.fn, recv: recv}
765*4947cdc7SCole Faust}
766*4947cdc7SCole Faust
767*4947cdc7SCole Faust// A *Dict represents a Starlark dictionary.
768*4947cdc7SCole Faust// The zero value of Dict is a valid empty dictionary.
769*4947cdc7SCole Faust// If you know the exact final number of entries,
770*4947cdc7SCole Faust// it is more efficient to call NewDict.
771*4947cdc7SCole Fausttype Dict struct {
772*4947cdc7SCole Faust	ht hashtable
773*4947cdc7SCole Faust}
774*4947cdc7SCole Faust
775*4947cdc7SCole Faust// NewDict returns a set with initial space for
776*4947cdc7SCole Faust// at least size insertions before rehashing.
777*4947cdc7SCole Faustfunc NewDict(size int) *Dict {
778*4947cdc7SCole Faust	dict := new(Dict)
779*4947cdc7SCole Faust	dict.ht.init(size)
780*4947cdc7SCole Faust	return dict
781*4947cdc7SCole Faust}
782*4947cdc7SCole Faust
783*4947cdc7SCole Faustfunc (d *Dict) Clear() error                                    { return d.ht.clear() }
784*4947cdc7SCole Faustfunc (d *Dict) Delete(k Value) (v Value, found bool, err error) { return d.ht.delete(k) }
785*4947cdc7SCole Faustfunc (d *Dict) Get(k Value) (v Value, found bool, err error)    { return d.ht.lookup(k) }
786*4947cdc7SCole Faustfunc (d *Dict) Items() []Tuple                                  { return d.ht.items() }
787*4947cdc7SCole Faustfunc (d *Dict) Keys() []Value                                   { return d.ht.keys() }
788*4947cdc7SCole Faustfunc (d *Dict) Len() int                                        { return int(d.ht.len) }
789*4947cdc7SCole Faustfunc (d *Dict) Iterate() Iterator                               { return d.ht.iterate() }
790*4947cdc7SCole Faustfunc (d *Dict) SetKey(k, v Value) error                         { return d.ht.insert(k, v) }
791*4947cdc7SCole Faustfunc (d *Dict) String() string                                  { return toString(d) }
792*4947cdc7SCole Faustfunc (d *Dict) Type() string                                    { return "dict" }
793*4947cdc7SCole Faustfunc (d *Dict) Freeze()                                         { d.ht.freeze() }
794*4947cdc7SCole Faustfunc (d *Dict) Truth() Bool                                     { return d.Len() > 0 }
795*4947cdc7SCole Faustfunc (d *Dict) Hash() (uint32, error)                           { return 0, fmt.Errorf("unhashable type: dict") }
796*4947cdc7SCole Faust
797*4947cdc7SCole Faustfunc (d *Dict) Attr(name string) (Value, error) { return builtinAttr(d, name, dictMethods) }
798*4947cdc7SCole Faustfunc (d *Dict) AttrNames() []string             { return builtinAttrNames(dictMethods) }
799*4947cdc7SCole Faust
800*4947cdc7SCole Faustfunc (x *Dict) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
801*4947cdc7SCole Faust	y := y_.(*Dict)
802*4947cdc7SCole Faust	switch op {
803*4947cdc7SCole Faust	case syntax.EQL:
804*4947cdc7SCole Faust		ok, err := dictsEqual(x, y, depth)
805*4947cdc7SCole Faust		return ok, err
806*4947cdc7SCole Faust	case syntax.NEQ:
807*4947cdc7SCole Faust		ok, err := dictsEqual(x, y, depth)
808*4947cdc7SCole Faust		return !ok, err
809*4947cdc7SCole Faust	default:
810*4947cdc7SCole Faust		return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
811*4947cdc7SCole Faust	}
812*4947cdc7SCole Faust}
813*4947cdc7SCole Faust
814*4947cdc7SCole Faustfunc dictsEqual(x, y *Dict, depth int) (bool, error) {
815*4947cdc7SCole Faust	if x.Len() != y.Len() {
816*4947cdc7SCole Faust		return false, nil
817*4947cdc7SCole Faust	}
818*4947cdc7SCole Faust	for _, xitem := range x.Items() {
819*4947cdc7SCole Faust		key, xval := xitem[0], xitem[1]
820*4947cdc7SCole Faust
821*4947cdc7SCole Faust		if yval, found, _ := y.Get(key); !found {
822*4947cdc7SCole Faust			return false, nil
823*4947cdc7SCole Faust		} else if eq, err := EqualDepth(xval, yval, depth-1); err != nil {
824*4947cdc7SCole Faust			return false, err
825*4947cdc7SCole Faust		} else if !eq {
826*4947cdc7SCole Faust			return false, nil
827*4947cdc7SCole Faust		}
828*4947cdc7SCole Faust	}
829*4947cdc7SCole Faust	return true, nil
830*4947cdc7SCole Faust}
831*4947cdc7SCole Faust
832*4947cdc7SCole Faust// A *List represents a Starlark list value.
833*4947cdc7SCole Fausttype List struct {
834*4947cdc7SCole Faust	elems     []Value
835*4947cdc7SCole Faust	frozen    bool
836*4947cdc7SCole Faust	itercount uint32 // number of active iterators (ignored if frozen)
837*4947cdc7SCole Faust}
838*4947cdc7SCole Faust
839*4947cdc7SCole Faust// NewList returns a list containing the specified elements.
840*4947cdc7SCole Faust// Callers should not subsequently modify elems.
841*4947cdc7SCole Faustfunc NewList(elems []Value) *List { return &List{elems: elems} }
842*4947cdc7SCole Faust
843*4947cdc7SCole Faustfunc (l *List) Freeze() {
844*4947cdc7SCole Faust	if !l.frozen {
845*4947cdc7SCole Faust		l.frozen = true
846*4947cdc7SCole Faust		for _, elem := range l.elems {
847*4947cdc7SCole Faust			elem.Freeze()
848*4947cdc7SCole Faust		}
849*4947cdc7SCole Faust	}
850*4947cdc7SCole Faust}
851*4947cdc7SCole Faust
852*4947cdc7SCole Faust// checkMutable reports an error if the list should not be mutated.
853*4947cdc7SCole Faust// verb+" list" should describe the operation.
854*4947cdc7SCole Faustfunc (l *List) checkMutable(verb string) error {
855*4947cdc7SCole Faust	if l.frozen {
856*4947cdc7SCole Faust		return fmt.Errorf("cannot %s frozen list", verb)
857*4947cdc7SCole Faust	}
858*4947cdc7SCole Faust	if l.itercount > 0 {
859*4947cdc7SCole Faust		return fmt.Errorf("cannot %s list during iteration", verb)
860*4947cdc7SCole Faust	}
861*4947cdc7SCole Faust	return nil
862*4947cdc7SCole Faust}
863*4947cdc7SCole Faust
864*4947cdc7SCole Faustfunc (l *List) String() string        { return toString(l) }
865*4947cdc7SCole Faustfunc (l *List) Type() string          { return "list" }
866*4947cdc7SCole Faustfunc (l *List) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable type: list") }
867*4947cdc7SCole Faustfunc (l *List) Truth() Bool           { return l.Len() > 0 }
868*4947cdc7SCole Faustfunc (l *List) Len() int              { return len(l.elems) }
869*4947cdc7SCole Faustfunc (l *List) Index(i int) Value     { return l.elems[i] }
870*4947cdc7SCole Faust
871*4947cdc7SCole Faustfunc (l *List) Slice(start, end, step int) Value {
872*4947cdc7SCole Faust	if step == 1 {
873*4947cdc7SCole Faust		elems := append([]Value{}, l.elems[start:end]...)
874*4947cdc7SCole Faust		return NewList(elems)
875*4947cdc7SCole Faust	}
876*4947cdc7SCole Faust
877*4947cdc7SCole Faust	sign := signum(step)
878*4947cdc7SCole Faust	var list []Value
879*4947cdc7SCole Faust	for i := start; signum(end-i) == sign; i += step {
880*4947cdc7SCole Faust		list = append(list, l.elems[i])
881*4947cdc7SCole Faust	}
882*4947cdc7SCole Faust	return NewList(list)
883*4947cdc7SCole Faust}
884*4947cdc7SCole Faust
885*4947cdc7SCole Faustfunc (l *List) Attr(name string) (Value, error) { return builtinAttr(l, name, listMethods) }
886*4947cdc7SCole Faustfunc (l *List) AttrNames() []string             { return builtinAttrNames(listMethods) }
887*4947cdc7SCole Faust
888*4947cdc7SCole Faustfunc (l *List) Iterate() Iterator {
889*4947cdc7SCole Faust	if !l.frozen {
890*4947cdc7SCole Faust		l.itercount++
891*4947cdc7SCole Faust	}
892*4947cdc7SCole Faust	return &listIterator{l: l}
893*4947cdc7SCole Faust}
894*4947cdc7SCole Faust
895*4947cdc7SCole Faustfunc (x *List) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
896*4947cdc7SCole Faust	y := y_.(*List)
897*4947cdc7SCole Faust	// It's tempting to check x == y as an optimization here,
898*4947cdc7SCole Faust	// but wrong because a list containing NaN is not equal to itself.
899*4947cdc7SCole Faust	return sliceCompare(op, x.elems, y.elems, depth)
900*4947cdc7SCole Faust}
901*4947cdc7SCole Faust
902*4947cdc7SCole Faustfunc sliceCompare(op syntax.Token, x, y []Value, depth int) (bool, error) {
903*4947cdc7SCole Faust	// Fast path: check length.
904*4947cdc7SCole Faust	if len(x) != len(y) && (op == syntax.EQL || op == syntax.NEQ) {
905*4947cdc7SCole Faust		return op == syntax.NEQ, nil
906*4947cdc7SCole Faust	}
907*4947cdc7SCole Faust
908*4947cdc7SCole Faust	// Find first element that is not equal in both lists.
909*4947cdc7SCole Faust	for i := 0; i < len(x) && i < len(y); i++ {
910*4947cdc7SCole Faust		if eq, err := EqualDepth(x[i], y[i], depth-1); err != nil {
911*4947cdc7SCole Faust			return false, err
912*4947cdc7SCole Faust		} else if !eq {
913*4947cdc7SCole Faust			switch op {
914*4947cdc7SCole Faust			case syntax.EQL:
915*4947cdc7SCole Faust				return false, nil
916*4947cdc7SCole Faust			case syntax.NEQ:
917*4947cdc7SCole Faust				return true, nil
918*4947cdc7SCole Faust			default:
919*4947cdc7SCole Faust				return CompareDepth(op, x[i], y[i], depth-1)
920*4947cdc7SCole Faust			}
921*4947cdc7SCole Faust		}
922*4947cdc7SCole Faust	}
923*4947cdc7SCole Faust
924*4947cdc7SCole Faust	return threeway(op, len(x)-len(y)), nil
925*4947cdc7SCole Faust}
926*4947cdc7SCole Faust
927*4947cdc7SCole Fausttype listIterator struct {
928*4947cdc7SCole Faust	l *List
929*4947cdc7SCole Faust	i int
930*4947cdc7SCole Faust}
931*4947cdc7SCole Faust
932*4947cdc7SCole Faustfunc (it *listIterator) Next(p *Value) bool {
933*4947cdc7SCole Faust	if it.i < it.l.Len() {
934*4947cdc7SCole Faust		*p = it.l.elems[it.i]
935*4947cdc7SCole Faust		it.i++
936*4947cdc7SCole Faust		return true
937*4947cdc7SCole Faust	}
938*4947cdc7SCole Faust	return false
939*4947cdc7SCole Faust}
940*4947cdc7SCole Faust
941*4947cdc7SCole Faustfunc (it *listIterator) Done() {
942*4947cdc7SCole Faust	if !it.l.frozen {
943*4947cdc7SCole Faust		it.l.itercount--
944*4947cdc7SCole Faust	}
945*4947cdc7SCole Faust}
946*4947cdc7SCole Faust
947*4947cdc7SCole Faustfunc (l *List) SetIndex(i int, v Value) error {
948*4947cdc7SCole Faust	if err := l.checkMutable("assign to element of"); err != nil {
949*4947cdc7SCole Faust		return err
950*4947cdc7SCole Faust	}
951*4947cdc7SCole Faust	l.elems[i] = v
952*4947cdc7SCole Faust	return nil
953*4947cdc7SCole Faust}
954*4947cdc7SCole Faust
955*4947cdc7SCole Faustfunc (l *List) Append(v Value) error {
956*4947cdc7SCole Faust	if err := l.checkMutable("append to"); err != nil {
957*4947cdc7SCole Faust		return err
958*4947cdc7SCole Faust	}
959*4947cdc7SCole Faust	l.elems = append(l.elems, v)
960*4947cdc7SCole Faust	return nil
961*4947cdc7SCole Faust}
962*4947cdc7SCole Faust
963*4947cdc7SCole Faustfunc (l *List) Clear() error {
964*4947cdc7SCole Faust	if err := l.checkMutable("clear"); err != nil {
965*4947cdc7SCole Faust		return err
966*4947cdc7SCole Faust	}
967*4947cdc7SCole Faust	for i := range l.elems {
968*4947cdc7SCole Faust		l.elems[i] = nil // aid GC
969*4947cdc7SCole Faust	}
970*4947cdc7SCole Faust	l.elems = l.elems[:0]
971*4947cdc7SCole Faust	return nil
972*4947cdc7SCole Faust}
973*4947cdc7SCole Faust
974*4947cdc7SCole Faust// A Tuple represents a Starlark tuple value.
975*4947cdc7SCole Fausttype Tuple []Value
976*4947cdc7SCole Faust
977*4947cdc7SCole Faustfunc (t Tuple) Len() int          { return len(t) }
978*4947cdc7SCole Faustfunc (t Tuple) Index(i int) Value { return t[i] }
979*4947cdc7SCole Faust
980*4947cdc7SCole Faustfunc (t Tuple) Slice(start, end, step int) Value {
981*4947cdc7SCole Faust	if step == 1 {
982*4947cdc7SCole Faust		return t[start:end]
983*4947cdc7SCole Faust	}
984*4947cdc7SCole Faust
985*4947cdc7SCole Faust	sign := signum(step)
986*4947cdc7SCole Faust	var tuple Tuple
987*4947cdc7SCole Faust	for i := start; signum(end-i) == sign; i += step {
988*4947cdc7SCole Faust		tuple = append(tuple, t[i])
989*4947cdc7SCole Faust	}
990*4947cdc7SCole Faust	return tuple
991*4947cdc7SCole Faust}
992*4947cdc7SCole Faust
993*4947cdc7SCole Faustfunc (t Tuple) Iterate() Iterator { return &tupleIterator{elems: t} }
994*4947cdc7SCole Faustfunc (t Tuple) Freeze() {
995*4947cdc7SCole Faust	for _, elem := range t {
996*4947cdc7SCole Faust		elem.Freeze()
997*4947cdc7SCole Faust	}
998*4947cdc7SCole Faust}
999*4947cdc7SCole Faustfunc (t Tuple) String() string { return toString(t) }
1000*4947cdc7SCole Faustfunc (t Tuple) Type() string   { return "tuple" }
1001*4947cdc7SCole Faustfunc (t Tuple) Truth() Bool    { return len(t) > 0 }
1002*4947cdc7SCole Faust
1003*4947cdc7SCole Faustfunc (x Tuple) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
1004*4947cdc7SCole Faust	y := y_.(Tuple)
1005*4947cdc7SCole Faust	return sliceCompare(op, x, y, depth)
1006*4947cdc7SCole Faust}
1007*4947cdc7SCole Faust
1008*4947cdc7SCole Faustfunc (t Tuple) Hash() (uint32, error) {
1009*4947cdc7SCole Faust	// Use same algorithm as Python.
1010*4947cdc7SCole Faust	var x, mult uint32 = 0x345678, 1000003
1011*4947cdc7SCole Faust	for _, elem := range t {
1012*4947cdc7SCole Faust		y, err := elem.Hash()
1013*4947cdc7SCole Faust		if err != nil {
1014*4947cdc7SCole Faust			return 0, err
1015*4947cdc7SCole Faust		}
1016*4947cdc7SCole Faust		x = x ^ y*mult
1017*4947cdc7SCole Faust		mult += 82520 + uint32(len(t)+len(t))
1018*4947cdc7SCole Faust	}
1019*4947cdc7SCole Faust	return x, nil
1020*4947cdc7SCole Faust}
1021*4947cdc7SCole Faust
1022*4947cdc7SCole Fausttype tupleIterator struct{ elems Tuple }
1023*4947cdc7SCole Faust
1024*4947cdc7SCole Faustfunc (it *tupleIterator) Next(p *Value) bool {
1025*4947cdc7SCole Faust	if len(it.elems) > 0 {
1026*4947cdc7SCole Faust		*p = it.elems[0]
1027*4947cdc7SCole Faust		it.elems = it.elems[1:]
1028*4947cdc7SCole Faust		return true
1029*4947cdc7SCole Faust	}
1030*4947cdc7SCole Faust	return false
1031*4947cdc7SCole Faust}
1032*4947cdc7SCole Faust
1033*4947cdc7SCole Faustfunc (it *tupleIterator) Done() {}
1034*4947cdc7SCole Faust
1035*4947cdc7SCole Faust// A Set represents a Starlark set value.
1036*4947cdc7SCole Faust// The zero value of Set is a valid empty set.
1037*4947cdc7SCole Faust// If you know the exact final number of elements,
1038*4947cdc7SCole Faust// it is more efficient to call NewSet.
1039*4947cdc7SCole Fausttype Set struct {
1040*4947cdc7SCole Faust	ht hashtable // values are all None
1041*4947cdc7SCole Faust}
1042*4947cdc7SCole Faust
1043*4947cdc7SCole Faust// NewSet returns a dictionary with initial space for
1044*4947cdc7SCole Faust// at least size insertions before rehashing.
1045*4947cdc7SCole Faustfunc NewSet(size int) *Set {
1046*4947cdc7SCole Faust	set := new(Set)
1047*4947cdc7SCole Faust	set.ht.init(size)
1048*4947cdc7SCole Faust	return set
1049*4947cdc7SCole Faust}
1050*4947cdc7SCole Faust
1051*4947cdc7SCole Faustfunc (s *Set) Delete(k Value) (found bool, err error) { _, found, err = s.ht.delete(k); return }
1052*4947cdc7SCole Faustfunc (s *Set) Clear() error                           { return s.ht.clear() }
1053*4947cdc7SCole Faustfunc (s *Set) Has(k Value) (found bool, err error)    { _, found, err = s.ht.lookup(k); return }
1054*4947cdc7SCole Faustfunc (s *Set) Insert(k Value) error                   { return s.ht.insert(k, None) }
1055*4947cdc7SCole Faustfunc (s *Set) Len() int                               { return int(s.ht.len) }
1056*4947cdc7SCole Faustfunc (s *Set) Iterate() Iterator                      { return s.ht.iterate() }
1057*4947cdc7SCole Faustfunc (s *Set) String() string                         { return toString(s) }
1058*4947cdc7SCole Faustfunc (s *Set) Type() string                           { return "set" }
1059*4947cdc7SCole Faustfunc (s *Set) elems() []Value                         { return s.ht.keys() }
1060*4947cdc7SCole Faustfunc (s *Set) Freeze()                                { s.ht.freeze() }
1061*4947cdc7SCole Faustfunc (s *Set) Hash() (uint32, error)                  { return 0, fmt.Errorf("unhashable type: set") }
1062*4947cdc7SCole Faustfunc (s *Set) Truth() Bool                            { return s.Len() > 0 }
1063*4947cdc7SCole Faust
1064*4947cdc7SCole Faustfunc (s *Set) Attr(name string) (Value, error) { return builtinAttr(s, name, setMethods) }
1065*4947cdc7SCole Faustfunc (s *Set) AttrNames() []string             { return builtinAttrNames(setMethods) }
1066*4947cdc7SCole Faust
1067*4947cdc7SCole Faustfunc (x *Set) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
1068*4947cdc7SCole Faust	y := y_.(*Set)
1069*4947cdc7SCole Faust	switch op {
1070*4947cdc7SCole Faust	case syntax.EQL:
1071*4947cdc7SCole Faust		ok, err := setsEqual(x, y, depth)
1072*4947cdc7SCole Faust		return ok, err
1073*4947cdc7SCole Faust	case syntax.NEQ:
1074*4947cdc7SCole Faust		ok, err := setsEqual(x, y, depth)
1075*4947cdc7SCole Faust		return !ok, err
1076*4947cdc7SCole Faust	default:
1077*4947cdc7SCole Faust		return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
1078*4947cdc7SCole Faust	}
1079*4947cdc7SCole Faust}
1080*4947cdc7SCole Faust
1081*4947cdc7SCole Faustfunc setsEqual(x, y *Set, depth int) (bool, error) {
1082*4947cdc7SCole Faust	if x.Len() != y.Len() {
1083*4947cdc7SCole Faust		return false, nil
1084*4947cdc7SCole Faust	}
1085*4947cdc7SCole Faust	for _, elem := range x.elems() {
1086*4947cdc7SCole Faust		if found, _ := y.Has(elem); !found {
1087*4947cdc7SCole Faust			return false, nil
1088*4947cdc7SCole Faust		}
1089*4947cdc7SCole Faust	}
1090*4947cdc7SCole Faust	return true, nil
1091*4947cdc7SCole Faust}
1092*4947cdc7SCole Faust
1093*4947cdc7SCole Faustfunc (s *Set) Union(iter Iterator) (Value, error) {
1094*4947cdc7SCole Faust	set := new(Set)
1095*4947cdc7SCole Faust	for _, elem := range s.elems() {
1096*4947cdc7SCole Faust		set.Insert(elem) // can't fail
1097*4947cdc7SCole Faust	}
1098*4947cdc7SCole Faust	var x Value
1099*4947cdc7SCole Faust	for iter.Next(&x) {
1100*4947cdc7SCole Faust		if err := set.Insert(x); err != nil {
1101*4947cdc7SCole Faust			return nil, err
1102*4947cdc7SCole Faust		}
1103*4947cdc7SCole Faust	}
1104*4947cdc7SCole Faust	return set, nil
1105*4947cdc7SCole Faust}
1106*4947cdc7SCole Faust
1107*4947cdc7SCole Faust// toString returns the string form of value v.
1108*4947cdc7SCole Faust// It may be more efficient than v.String() for larger values.
1109*4947cdc7SCole Faustfunc toString(v Value) string {
1110*4947cdc7SCole Faust	buf := new(strings.Builder)
1111*4947cdc7SCole Faust	writeValue(buf, v, nil)
1112*4947cdc7SCole Faust	return buf.String()
1113*4947cdc7SCole Faust}
1114*4947cdc7SCole Faust
1115*4947cdc7SCole Faust// writeValue writes x to out.
1116*4947cdc7SCole Faust//
1117*4947cdc7SCole Faust// path is used to detect cycles.
1118*4947cdc7SCole Faust// It contains the list of *List and *Dict values we're currently printing.
1119*4947cdc7SCole Faust// (These are the only potentially cyclic structures.)
1120*4947cdc7SCole Faust// Callers should generally pass nil for path.
1121*4947cdc7SCole Faust// It is safe to re-use the same path slice for multiple calls.
1122*4947cdc7SCole Faustfunc writeValue(out *strings.Builder, x Value, path []Value) {
1123*4947cdc7SCole Faust	switch x := x.(type) {
1124*4947cdc7SCole Faust	case nil:
1125*4947cdc7SCole Faust		out.WriteString("<nil>") // indicates a bug
1126*4947cdc7SCole Faust
1127*4947cdc7SCole Faust	// These four cases are duplicates of T.String(), for efficiency.
1128*4947cdc7SCole Faust	case NoneType:
1129*4947cdc7SCole Faust		out.WriteString("None")
1130*4947cdc7SCole Faust
1131*4947cdc7SCole Faust	case Int:
1132*4947cdc7SCole Faust		out.WriteString(x.String())
1133*4947cdc7SCole Faust
1134*4947cdc7SCole Faust	case Bool:
1135*4947cdc7SCole Faust		if x {
1136*4947cdc7SCole Faust			out.WriteString("True")
1137*4947cdc7SCole Faust		} else {
1138*4947cdc7SCole Faust			out.WriteString("False")
1139*4947cdc7SCole Faust		}
1140*4947cdc7SCole Faust
1141*4947cdc7SCole Faust	case String:
1142*4947cdc7SCole Faust		out.WriteString(syntax.Quote(string(x), false))
1143*4947cdc7SCole Faust
1144*4947cdc7SCole Faust	case *List:
1145*4947cdc7SCole Faust		out.WriteByte('[')
1146*4947cdc7SCole Faust		if pathContains(path, x) {
1147*4947cdc7SCole Faust			out.WriteString("...") // list contains itself
1148*4947cdc7SCole Faust		} else {
1149*4947cdc7SCole Faust			for i, elem := range x.elems {
1150*4947cdc7SCole Faust				if i > 0 {
1151*4947cdc7SCole Faust					out.WriteString(", ")
1152*4947cdc7SCole Faust				}
1153*4947cdc7SCole Faust				writeValue(out, elem, append(path, x))
1154*4947cdc7SCole Faust			}
1155*4947cdc7SCole Faust		}
1156*4947cdc7SCole Faust		out.WriteByte(']')
1157*4947cdc7SCole Faust
1158*4947cdc7SCole Faust	case Tuple:
1159*4947cdc7SCole Faust		out.WriteByte('(')
1160*4947cdc7SCole Faust		for i, elem := range x {
1161*4947cdc7SCole Faust			if i > 0 {
1162*4947cdc7SCole Faust				out.WriteString(", ")
1163*4947cdc7SCole Faust			}
1164*4947cdc7SCole Faust			writeValue(out, elem, path)
1165*4947cdc7SCole Faust		}
1166*4947cdc7SCole Faust		if len(x) == 1 {
1167*4947cdc7SCole Faust			out.WriteByte(',')
1168*4947cdc7SCole Faust		}
1169*4947cdc7SCole Faust		out.WriteByte(')')
1170*4947cdc7SCole Faust
1171*4947cdc7SCole Faust	case *Function:
1172*4947cdc7SCole Faust		fmt.Fprintf(out, "<function %s>", x.Name())
1173*4947cdc7SCole Faust
1174*4947cdc7SCole Faust	case *Builtin:
1175*4947cdc7SCole Faust		if x.recv != nil {
1176*4947cdc7SCole Faust			fmt.Fprintf(out, "<built-in method %s of %s value>", x.Name(), x.recv.Type())
1177*4947cdc7SCole Faust		} else {
1178*4947cdc7SCole Faust			fmt.Fprintf(out, "<built-in function %s>", x.Name())
1179*4947cdc7SCole Faust		}
1180*4947cdc7SCole Faust
1181*4947cdc7SCole Faust	case *Dict:
1182*4947cdc7SCole Faust		out.WriteByte('{')
1183*4947cdc7SCole Faust		if pathContains(path, x) {
1184*4947cdc7SCole Faust			out.WriteString("...") // dict contains itself
1185*4947cdc7SCole Faust		} else {
1186*4947cdc7SCole Faust			sep := ""
1187*4947cdc7SCole Faust			for _, item := range x.Items() {
1188*4947cdc7SCole Faust				k, v := item[0], item[1]
1189*4947cdc7SCole Faust				out.WriteString(sep)
1190*4947cdc7SCole Faust				writeValue(out, k, path)
1191*4947cdc7SCole Faust				out.WriteString(": ")
1192*4947cdc7SCole Faust				writeValue(out, v, append(path, x)) // cycle check
1193*4947cdc7SCole Faust				sep = ", "
1194*4947cdc7SCole Faust			}
1195*4947cdc7SCole Faust		}
1196*4947cdc7SCole Faust		out.WriteByte('}')
1197*4947cdc7SCole Faust
1198*4947cdc7SCole Faust	case *Set:
1199*4947cdc7SCole Faust		out.WriteString("set([")
1200*4947cdc7SCole Faust		for i, elem := range x.elems() {
1201*4947cdc7SCole Faust			if i > 0 {
1202*4947cdc7SCole Faust				out.WriteString(", ")
1203*4947cdc7SCole Faust			}
1204*4947cdc7SCole Faust			writeValue(out, elem, path)
1205*4947cdc7SCole Faust		}
1206*4947cdc7SCole Faust		out.WriteString("])")
1207*4947cdc7SCole Faust
1208*4947cdc7SCole Faust	default:
1209*4947cdc7SCole Faust		out.WriteString(x.String())
1210*4947cdc7SCole Faust	}
1211*4947cdc7SCole Faust}
1212*4947cdc7SCole Faust
1213*4947cdc7SCole Faustfunc pathContains(path []Value, x Value) bool {
1214*4947cdc7SCole Faust	for _, y := range path {
1215*4947cdc7SCole Faust		if x == y {
1216*4947cdc7SCole Faust			return true
1217*4947cdc7SCole Faust		}
1218*4947cdc7SCole Faust	}
1219*4947cdc7SCole Faust	return false
1220*4947cdc7SCole Faust}
1221*4947cdc7SCole Faust
1222*4947cdc7SCole Faustconst maxdepth = 10
1223*4947cdc7SCole Faust
1224*4947cdc7SCole Faust// Equal reports whether two Starlark values are equal.
1225*4947cdc7SCole Faustfunc Equal(x, y Value) (bool, error) {
1226*4947cdc7SCole Faust	if x, ok := x.(String); ok {
1227*4947cdc7SCole Faust		return x == y, nil // fast path for an important special case
1228*4947cdc7SCole Faust	}
1229*4947cdc7SCole Faust	return EqualDepth(x, y, maxdepth)
1230*4947cdc7SCole Faust}
1231*4947cdc7SCole Faust
1232*4947cdc7SCole Faust// EqualDepth reports whether two Starlark values are equal.
1233*4947cdc7SCole Faust//
1234*4947cdc7SCole Faust// Recursive comparisons by implementations of Value.CompareSameType
1235*4947cdc7SCole Faust// should use EqualDepth to prevent infinite recursion.
1236*4947cdc7SCole Faustfunc EqualDepth(x, y Value, depth int) (bool, error) {
1237*4947cdc7SCole Faust	return CompareDepth(syntax.EQL, x, y, depth)
1238*4947cdc7SCole Faust}
1239*4947cdc7SCole Faust
1240*4947cdc7SCole Faust// Compare compares two Starlark values.
1241*4947cdc7SCole Faust// The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE.
1242*4947cdc7SCole Faust// Compare returns an error if an ordered comparison was
1243*4947cdc7SCole Faust// requested for a type that does not support it.
1244*4947cdc7SCole Faust//
1245*4947cdc7SCole Faust// Recursive comparisons by implementations of Value.CompareSameType
1246*4947cdc7SCole Faust// should use CompareDepth to prevent infinite recursion.
1247*4947cdc7SCole Faustfunc Compare(op syntax.Token, x, y Value) (bool, error) {
1248*4947cdc7SCole Faust	return CompareDepth(op, x, y, maxdepth)
1249*4947cdc7SCole Faust}
1250*4947cdc7SCole Faust
1251*4947cdc7SCole Faust// CompareDepth compares two Starlark values.
1252*4947cdc7SCole Faust// The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE.
1253*4947cdc7SCole Faust// CompareDepth returns an error if an ordered comparison was
1254*4947cdc7SCole Faust// requested for a pair of values that do not support it.
1255*4947cdc7SCole Faust//
1256*4947cdc7SCole Faust// The depth parameter limits the maximum depth of recursion
1257*4947cdc7SCole Faust// in cyclic data structures.
1258*4947cdc7SCole Faustfunc CompareDepth(op syntax.Token, x, y Value, depth int) (bool, error) {
1259*4947cdc7SCole Faust	if depth < 1 {
1260*4947cdc7SCole Faust		return false, fmt.Errorf("comparison exceeded maximum recursion depth")
1261*4947cdc7SCole Faust	}
1262*4947cdc7SCole Faust	if sameType(x, y) {
1263*4947cdc7SCole Faust		if xcomp, ok := x.(Comparable); ok {
1264*4947cdc7SCole Faust			return xcomp.CompareSameType(op, y, depth)
1265*4947cdc7SCole Faust		}
1266*4947cdc7SCole Faust
1267*4947cdc7SCole Faust		// use identity comparison
1268*4947cdc7SCole Faust		switch op {
1269*4947cdc7SCole Faust		case syntax.EQL:
1270*4947cdc7SCole Faust			return x == y, nil
1271*4947cdc7SCole Faust		case syntax.NEQ:
1272*4947cdc7SCole Faust			return x != y, nil
1273*4947cdc7SCole Faust		}
1274*4947cdc7SCole Faust		return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
1275*4947cdc7SCole Faust	}
1276*4947cdc7SCole Faust
1277*4947cdc7SCole Faust	// different types
1278*4947cdc7SCole Faust
1279*4947cdc7SCole Faust	// int/float ordered comparisons
1280*4947cdc7SCole Faust	switch x := x.(type) {
1281*4947cdc7SCole Faust	case Int:
1282*4947cdc7SCole Faust		if y, ok := y.(Float); ok {
1283*4947cdc7SCole Faust			var cmp int
1284*4947cdc7SCole Faust			if y != y {
1285*4947cdc7SCole Faust				cmp = -1 // y is NaN
1286*4947cdc7SCole Faust			} else if !math.IsInf(float64(y), 0) {
1287*4947cdc7SCole Faust				cmp = x.rational().Cmp(y.rational()) // y is finite
1288*4947cdc7SCole Faust			} else if y > 0 {
1289*4947cdc7SCole Faust				cmp = -1 // y is +Inf
1290*4947cdc7SCole Faust			} else {
1291*4947cdc7SCole Faust				cmp = +1 // y is -Inf
1292*4947cdc7SCole Faust			}
1293*4947cdc7SCole Faust			return threeway(op, cmp), nil
1294*4947cdc7SCole Faust		}
1295*4947cdc7SCole Faust	case Float:
1296*4947cdc7SCole Faust		if y, ok := y.(Int); ok {
1297*4947cdc7SCole Faust			var cmp int
1298*4947cdc7SCole Faust			if x != x {
1299*4947cdc7SCole Faust				cmp = +1 // x is NaN
1300*4947cdc7SCole Faust			} else if !math.IsInf(float64(x), 0) {
1301*4947cdc7SCole Faust				cmp = x.rational().Cmp(y.rational()) // x is finite
1302*4947cdc7SCole Faust			} else if x > 0 {
1303*4947cdc7SCole Faust				cmp = +1 // x is +Inf
1304*4947cdc7SCole Faust			} else {
1305*4947cdc7SCole Faust				cmp = -1 // x is -Inf
1306*4947cdc7SCole Faust			}
1307*4947cdc7SCole Faust			return threeway(op, cmp), nil
1308*4947cdc7SCole Faust		}
1309*4947cdc7SCole Faust	}
1310*4947cdc7SCole Faust
1311*4947cdc7SCole Faust	// All other values of different types compare unequal.
1312*4947cdc7SCole Faust	switch op {
1313*4947cdc7SCole Faust	case syntax.EQL:
1314*4947cdc7SCole Faust		return false, nil
1315*4947cdc7SCole Faust	case syntax.NEQ:
1316*4947cdc7SCole Faust		return true, nil
1317*4947cdc7SCole Faust	}
1318*4947cdc7SCole Faust	return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
1319*4947cdc7SCole Faust}
1320*4947cdc7SCole Faust
1321*4947cdc7SCole Faustfunc sameType(x, y Value) bool {
1322*4947cdc7SCole Faust	return reflect.TypeOf(x) == reflect.TypeOf(y) || x.Type() == y.Type()
1323*4947cdc7SCole Faust}
1324*4947cdc7SCole Faust
1325*4947cdc7SCole Faust// threeway interprets a three-way comparison value cmp (-1, 0, +1)
1326*4947cdc7SCole Faust// as a boolean comparison (e.g. x < y).
1327*4947cdc7SCole Faustfunc threeway(op syntax.Token, cmp int) bool {
1328*4947cdc7SCole Faust	switch op {
1329*4947cdc7SCole Faust	case syntax.EQL:
1330*4947cdc7SCole Faust		return cmp == 0
1331*4947cdc7SCole Faust	case syntax.NEQ:
1332*4947cdc7SCole Faust		return cmp != 0
1333*4947cdc7SCole Faust	case syntax.LE:
1334*4947cdc7SCole Faust		return cmp <= 0
1335*4947cdc7SCole Faust	case syntax.LT:
1336*4947cdc7SCole Faust		return cmp < 0
1337*4947cdc7SCole Faust	case syntax.GE:
1338*4947cdc7SCole Faust		return cmp >= 0
1339*4947cdc7SCole Faust	case syntax.GT:
1340*4947cdc7SCole Faust		return cmp > 0
1341*4947cdc7SCole Faust	}
1342*4947cdc7SCole Faust	panic(op)
1343*4947cdc7SCole Faust}
1344*4947cdc7SCole Faust
1345*4947cdc7SCole Faustfunc b2i(b bool) int {
1346*4947cdc7SCole Faust	if b {
1347*4947cdc7SCole Faust		return 1
1348*4947cdc7SCole Faust	} else {
1349*4947cdc7SCole Faust		return 0
1350*4947cdc7SCole Faust	}
1351*4947cdc7SCole Faust}
1352*4947cdc7SCole Faust
1353*4947cdc7SCole Faust// Len returns the length of a string or sequence value,
1354*4947cdc7SCole Faust// and -1 for all others.
1355*4947cdc7SCole Faust//
1356*4947cdc7SCole Faust// Warning: Len(x) >= 0 does not imply Iterate(x) != nil.
1357*4947cdc7SCole Faust// A string has a known length but is not directly iterable.
1358*4947cdc7SCole Faustfunc Len(x Value) int {
1359*4947cdc7SCole Faust	switch x := x.(type) {
1360*4947cdc7SCole Faust	case String:
1361*4947cdc7SCole Faust		return x.Len()
1362*4947cdc7SCole Faust	case Indexable:
1363*4947cdc7SCole Faust		return x.Len()
1364*4947cdc7SCole Faust	case Sequence:
1365*4947cdc7SCole Faust		return x.Len()
1366*4947cdc7SCole Faust	}
1367*4947cdc7SCole Faust	return -1
1368*4947cdc7SCole Faust}
1369*4947cdc7SCole Faust
1370*4947cdc7SCole Faust// Iterate return a new iterator for the value if iterable, nil otherwise.
1371*4947cdc7SCole Faust// If the result is non-nil, the caller must call Done when finished with it.
1372*4947cdc7SCole Faust//
1373*4947cdc7SCole Faust// Warning: Iterate(x) != nil does not imply Len(x) >= 0.
1374*4947cdc7SCole Faust// Some iterables may have unknown length.
1375*4947cdc7SCole Faustfunc Iterate(x Value) Iterator {
1376*4947cdc7SCole Faust	if x, ok := x.(Iterable); ok {
1377*4947cdc7SCole Faust		return x.Iterate()
1378*4947cdc7SCole Faust	}
1379*4947cdc7SCole Faust	return nil
1380*4947cdc7SCole Faust}
1381*4947cdc7SCole Faust
1382*4947cdc7SCole Faust// Bytes is the type of a Starlark binary string.
1383*4947cdc7SCole Faust//
1384*4947cdc7SCole Faust// A Bytes encapsulates an immutable sequence of bytes.
1385*4947cdc7SCole Faust// It is comparable, indexable, and sliceable, but not direcly iterable;
1386*4947cdc7SCole Faust// use bytes.elems() for an iterable view.
1387*4947cdc7SCole Faust//
1388*4947cdc7SCole Faust// In this Go implementation, the elements of 'string' and 'bytes' are
1389*4947cdc7SCole Faust// both bytes, but in other implementations, notably Java, the elements
1390*4947cdc7SCole Faust// of a 'string' are UTF-16 codes (Java chars). The spec abstracts text
1391*4947cdc7SCole Faust// strings as sequences of UTF-k codes that encode Unicode code points,
1392*4947cdc7SCole Faust// and operations that convert from text to binary incur UTF-k-to-UTF-8
1393*4947cdc7SCole Faust// transcoding; conversely, conversion from binary to text incurs
1394*4947cdc7SCole Faust// UTF-8-to-UTF-k transcoding. Because k=8 for Go, these operations
1395*4947cdc7SCole Faust// are the identity function, at least for valid encodings of text.
1396*4947cdc7SCole Fausttype Bytes string
1397*4947cdc7SCole Faust
1398*4947cdc7SCole Faustvar (
1399*4947cdc7SCole Faust	_ Comparable = Bytes("")
1400*4947cdc7SCole Faust	_ Sliceable  = Bytes("")
1401*4947cdc7SCole Faust	_ Indexable  = Bytes("")
1402*4947cdc7SCole Faust)
1403*4947cdc7SCole Faust
1404*4947cdc7SCole Faustfunc (b Bytes) String() string        { return syntax.Quote(string(b), true) }
1405*4947cdc7SCole Faustfunc (b Bytes) Type() string          { return "bytes" }
1406*4947cdc7SCole Faustfunc (b Bytes) Freeze()               {} // immutable
1407*4947cdc7SCole Faustfunc (b Bytes) Truth() Bool           { return len(b) > 0 }
1408*4947cdc7SCole Faustfunc (b Bytes) Hash() (uint32, error) { return String(b).Hash() }
1409*4947cdc7SCole Faustfunc (b Bytes) Len() int              { return len(b) }
1410*4947cdc7SCole Faustfunc (b Bytes) Index(i int) Value     { return b[i : i+1] }
1411*4947cdc7SCole Faust
1412*4947cdc7SCole Faustfunc (b Bytes) Attr(name string) (Value, error) { return builtinAttr(b, name, bytesMethods) }
1413*4947cdc7SCole Faustfunc (b Bytes) AttrNames() []string             { return builtinAttrNames(bytesMethods) }
1414*4947cdc7SCole Faust
1415*4947cdc7SCole Faustfunc (b Bytes) Slice(start, end, step int) Value {
1416*4947cdc7SCole Faust	if step == 1 {
1417*4947cdc7SCole Faust		return b[start:end]
1418*4947cdc7SCole Faust	}
1419*4947cdc7SCole Faust
1420*4947cdc7SCole Faust	sign := signum(step)
1421*4947cdc7SCole Faust	var str []byte
1422*4947cdc7SCole Faust	for i := start; signum(end-i) == sign; i += step {
1423*4947cdc7SCole Faust		str = append(str, b[i])
1424*4947cdc7SCole Faust	}
1425*4947cdc7SCole Faust	return Bytes(str)
1426*4947cdc7SCole Faust}
1427*4947cdc7SCole Faust
1428*4947cdc7SCole Faustfunc (x Bytes) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
1429*4947cdc7SCole Faust	y := y_.(Bytes)
1430*4947cdc7SCole Faust	return threeway(op, strings.Compare(string(x), string(y))), nil
1431*4947cdc7SCole Faust}
1432