blob: 81e29ed10b947569d9d019cb6167804f9694bc25 [file] [log] [blame]
Alan Donovan312d1a52017-10-02 10:10:28 -04001// Copyright 2017 The Bazel Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Alan Donovane3deafe2018-10-23 11:05:09 -04005// Package starlark provides a Starlark interpreter.
Alan Donovan312d1a52017-10-02 10:10:28 -04006//
Alan Donovane3deafe2018-10-23 11:05:09 -04007// Starlark values are represented by the Value interface.
Alan Donovan312d1a52017-10-02 10:10:28 -04008// The following built-in Value types are known to the evaluator:
9//
10// NoneType -- NoneType
11// Bool -- bool
12// Int -- int
13// Float -- float
14// String -- string
15// *List -- list
16// Tuple -- tuple
17// *Dict -- dict
18// *Set -- set
Alan Donovane3deafe2018-10-23 11:05:09 -040019// *Function -- function (implemented in Starlark)
alandonovan4cbd8962017-10-19 13:18:36 -040020// *Builtin -- builtin_function_or_method (function or method implemented in Go)
Alan Donovan312d1a52017-10-02 10:10:28 -040021//
22// Client applications may define new data types that satisfy at least
23// the Value interface. Such types may provide additional operations by
24// implementing any of these optional interfaces:
25//
26// Callable -- value is callable like a function
27// Comparable -- value defines its own comparison operations
28// Iterable -- value is iterable using 'for' loops
29// Sequence -- value is iterable sequence of known length
30// Indexable -- value is sequence with efficient random access
jmillikin-stripe3ccab942018-10-05 07:09:12 -070031// Mapping -- value maps from keys to values, like a dictionary
Alan Donovan312d1a52017-10-02 10:10:28 -040032// HasBinary -- value defines binary operations such as * and +
33// HasAttrs -- value has readable fields or methods x.f
34// HasSetField -- value has settable fields x.f
35// HasSetIndex -- value supports element update using x[i]=y
jmillikin-stripe3ccab942018-10-05 07:09:12 -070036// HasSetKey -- value supports map update using x[k]=v
alandonovan58f91012019-01-03 16:32:47 -050037// HasUnary -- value defines unary operations such as + and -
Alan Donovan312d1a52017-10-02 10:10:28 -040038//
39// Client applications may also define domain-specific functions in Go
Alan Donovane3deafe2018-10-23 11:05:09 -040040// and make them available to Starlark programs. Use NewBuiltin to
Alan Donovan312d1a52017-10-02 10:10:28 -040041// construct a built-in value that wraps a Go function. The
42// implementation of the Go function may use UnpackArgs to make sense of
43// the positional and keyword arguments provided by the caller.
44//
alandonovan6677ee52020-02-03 09:41:50 -050045// Starlark's None value is not equal to Go's nil. Go's nil is not a legal
46// Starlark value, but the compiler will not stop you from converting nil
47// to Value. Be careful to avoid allowing Go nil values to leak into
48// Starlark data structures.
Alan Donovan312d1a52017-10-02 10:10:28 -040049//
50// The Compare operation requires two arguments of the same
51// type, but this constraint cannot be expressed in Go's type system.
52// (This is the classic "binary method problem".)
53// So, each Value type's CompareSameType method is a partial function
54// that compares a value only against others of the same type.
55// Use the package's standalone Compare (or Equal) function to compare
56// an arbitrary pair of values.
57//
Alan Donovane3deafe2018-10-23 11:05:09 -040058// To parse and evaluate a Starlark source file, use ExecFile. The Eval
Alan Donovan312d1a52017-10-02 10:10:28 -040059// function evaluates a single expression. All evaluator functions
60// require a Thread parameter which defines the "thread-local storage"
Alan Donovane3deafe2018-10-23 11:05:09 -040061// of a Starlark thread and may be used to plumb application state
alandonovan6677ee52020-02-03 09:41:50 -050062// through Starlark code and into callbacks. When evaluation fails it
Alan Donovan312d1a52017-10-02 10:10:28 -040063// returns an EvalError from which the application may obtain a
Alan Donovane3deafe2018-10-23 11:05:09 -040064// backtrace of active Starlark calls.
Alan Donovan312d1a52017-10-02 10:10:28 -040065//
Alan Donovan6beab7e2018-10-31 17:53:09 -040066package starlark // import "go.starlark.net/starlark"
Alan Donovan312d1a52017-10-02 10:10:28 -040067
Alan Donovane3deafe2018-10-23 11:05:09 -040068// This file defines the data types of Starlark and their basic operations.
Alan Donovan312d1a52017-10-02 10:10:28 -040069
70import (
Alan Donovan312d1a52017-10-02 10:10:28 -040071 "fmt"
72 "math"
73 "math/big"
74 "reflect"
75 "strconv"
76 "strings"
77 "unicode/utf8"
78
Alan Donovan6beab7e2018-10-31 17:53:09 -040079 "go.starlark.net/internal/compile"
80 "go.starlark.net/syntax"
Alan Donovan312d1a52017-10-02 10:10:28 -040081)
82
Alan Donovane3deafe2018-10-23 11:05:09 -040083// Value is a value in the Starlark interpreter.
Alan Donovan312d1a52017-10-02 10:10:28 -040084type Value interface {
85 // String returns the string representation of the value.
Alan Donovane3deafe2018-10-23 11:05:09 -040086 // Starlark string values are quoted as if by Python's repr.
Alan Donovan312d1a52017-10-02 10:10:28 -040087 String() string
88
89 // Type returns a short string describing the value's type.
90 Type() string
91
92 // Freeze causes the value, and all values transitively
93 // reachable from it through collections and closures, to be
94 // marked as frozen. All subsequent mutations to the data
95 // structure through this API will fail dynamically, making the
96 // data structure immutable and safe for publishing to other
Alan Donovane3deafe2018-10-23 11:05:09 -040097 // Starlark interpreters running concurrently.
Alan Donovan312d1a52017-10-02 10:10:28 -040098 Freeze()
99
alandonovan5ce1e422017-10-17 15:20:32 -0400100 // Truth returns the truth value of an object.
Alan Donovan312d1a52017-10-02 10:10:28 -0400101 Truth() Bool
102
103 // Hash returns a function of x such that Equals(x, y) => Hash(x) == Hash(y).
104 // Hash may fail if the value's type is not hashable, or if the value
alandonovane35f71a2019-05-14 14:50:48 -0400105 // contains a non-hashable value. The hash is used only by dictionaries and
106 // is not exposed to the Starlark program.
Alan Donovan312d1a52017-10-02 10:10:28 -0400107 Hash() (uint32, error)
108}
109
110// A Comparable is a value that defines its own equivalence relation and
111// perhaps ordered comparisons.
112type Comparable interface {
113 Value
114 // CompareSameType compares one value to another of the same Type().
115 // The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE.
116 // CompareSameType returns an error if an ordered comparison was
117 // requested for a type that does not support it.
118 //
119 // Implementations that recursively compare subcomponents of
120 // the value should use the CompareDepth function, not Compare, to
121 // avoid infinite recursion on cyclic structures.
122 //
123 // The depth parameter is used to bound comparisons of cyclic
124 // data structures. Implementations should decrement depth
125 // before calling CompareDepth and should return an error if depth
126 // < 1.
127 //
128 // Client code should not call this method. Instead, use the
129 // standalone Compare or Equals functions, which are defined for
130 // all pairs of operands.
131 CompareSameType(op syntax.Token, y Value, depth int) (bool, error)
132}
133
134var (
Alan Donovan312d1a52017-10-02 10:10:28 -0400135 _ Comparable = Int{}
136 _ Comparable = False
137 _ Comparable = Float(0)
138 _ Comparable = String("")
139 _ Comparable = (*Dict)(nil)
140 _ Comparable = (*List)(nil)
141 _ Comparable = Tuple(nil)
142 _ Comparable = (*Set)(nil)
143)
144
145// A Callable value f may be the operand of a function call, f(x).
alandonovanaeec83f2018-10-22 13:24:13 -0400146//
147// Clients should use the Call function, never the CallInternal method.
Alan Donovan312d1a52017-10-02 10:10:28 -0400148type Callable interface {
149 Value
150 Name() string
alandonovanaeec83f2018-10-22 13:24:13 -0400151 CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error)
Alan Donovan312d1a52017-10-02 10:10:28 -0400152}
153
alandonovan40b4ab62019-04-03 16:41:37 -0400154type callableWithPosition interface {
155 Callable
156 Position() syntax.Position
157}
158
Alan Donovan312d1a52017-10-02 10:10:28 -0400159var (
alandonovan40b4ab62019-04-03 16:41:37 -0400160 _ Callable = (*Builtin)(nil)
161 _ Callable = (*Function)(nil)
162 _ callableWithPosition = (*Function)(nil)
Alan Donovan312d1a52017-10-02 10:10:28 -0400163)
164
165// An Iterable abstracts a sequence of values.
166// An iterable value may be iterated over by a 'for' loop or used where
Alan Donovane3deafe2018-10-23 11:05:09 -0400167// any other Starlark iterable is allowed. Unlike a Sequence, the length
Alan Donovan312d1a52017-10-02 10:10:28 -0400168// of an Iterable is not necessarily known in advance of iteration.
169type Iterable interface {
170 Value
171 Iterate() Iterator // must be followed by call to Iterator.Done
172}
173
174// A Sequence is a sequence of values of known length.
175type Sequence interface {
176 Iterable
177 Len() int
178}
179
180var (
181 _ Sequence = (*Dict)(nil)
182 _ Sequence = (*Set)(nil)
183)
184
185// An Indexable is a sequence of known length that supports efficient random access.
186// It is not necessarily iterable.
187type Indexable interface {
188 Value
189 Index(i int) Value // requires 0 <= i < Len()
190 Len() int
191}
192
Nick Santosd3cd7362018-05-18 12:58:53 -0400193// A Sliceable is a sequence that can be cut into pieces with the slice operator (x[i:j:step]).
194//
195// All native indexable objects are sliceable.
196// This is a separate interface for backwards-compatibility.
197type Sliceable interface {
198 Indexable
199 // For positive strides (step > 0), 0 <= start <= end <= n.
200 // For negative strides (step < 0), -1 <= end <= start < n.
Josh Bleecher Snyderd5c553a2019-01-16 12:51:06 -0800201 // The caller must ensure that the start and end indices are valid
202 // and that step is non-zero.
Nick Santosd3cd7362018-05-18 12:58:53 -0400203 Slice(start, end, step int) Value
204}
205
Alan Donovan312d1a52017-10-02 10:10:28 -0400206// A HasSetIndex is an Indexable value whose elements may be assigned (x[i] = y).
207//
208// The implementation should not add Len to a negative index as the
209// evaluator does this before the call.
210type HasSetIndex interface {
211 Indexable
212 SetIndex(index int, v Value) error
213}
214
215var (
216 _ HasSetIndex = (*List)(nil)
217 _ Indexable = Tuple(nil)
218 _ Indexable = String("")
Nick Santosd3cd7362018-05-18 12:58:53 -0400219 _ Sliceable = Tuple(nil)
220 _ Sliceable = String("")
221 _ Sliceable = (*List)(nil)
Alan Donovan312d1a52017-10-02 10:10:28 -0400222)
223
224// An Iterator provides a sequence of values to the caller.
225//
226// The caller must call Done when the iterator is no longer needed.
227// Operations that modify a sequence will fail if it has active iterators.
228//
229// Example usage:
230//
231// iter := iterable.Iterator()
232// defer iter.Done()
233// var x Value
234// for iter.Next(&x) {
235// ...
236// }
237//
238type Iterator interface {
239 // If the iterator is exhausted, Next returns false.
240 // Otherwise it sets *p to the current element of the sequence,
241 // advances the iterator, and returns true.
242 Next(p *Value) bool
243 Done()
244}
245
jmillikin-stripe3ccab942018-10-05 07:09:12 -0700246// A Mapping is a mapping from keys to values, such as a dictionary.
alandonovan1ed64972019-01-04 13:04:39 -0500247//
248// If a type satisfies both Mapping and Iterable, the iterator yields
249// the keys of the mapping.
Alan Donovan312d1a52017-10-02 10:10:28 -0400250type Mapping interface {
251 Value
252 // Get returns the value corresponding to the specified key,
253 // or !found if the mapping does not contain the key.
alandonovan7f065b62018-03-19 14:58:49 -0400254 //
255 // Get also defines the behavior of "v in mapping".
256 // The 'in' operator reports the 'found' component, ignoring errors.
Alan Donovan312d1a52017-10-02 10:10:28 -0400257 Get(Value) (v Value, found bool, err error)
258}
259
alandonovan1ed64972019-01-04 13:04:39 -0500260// An IterableMapping is a mapping that supports key enumeration.
261type IterableMapping interface {
262 Mapping
263 Iterate() Iterator // see Iterable interface
264 Items() []Tuple // a new slice containing all key/value pairs
265}
266
267var _ IterableMapping = (*Dict)(nil)
Alan Donovan312d1a52017-10-02 10:10:28 -0400268
jmillikin-stripe3ccab942018-10-05 07:09:12 -0700269// A HasSetKey supports map update using x[k]=v syntax, like a dictionary.
270type HasSetKey interface {
271 Mapping
272 SetKey(k, v Value) error
273}
274
275var _ HasSetKey = (*Dict)(nil)
276
Alan Donovan312d1a52017-10-02 10:10:28 -0400277// A HasBinary value may be used as either operand of these binary operators:
alandonovan93b8d142019-01-06 11:57:29 -0500278// + - * / // % in not in | & ^ << >>
279//
Alan Donovan312d1a52017-10-02 10:10:28 -0400280// The Side argument indicates whether the receiver is the left or right operand.
281//
282// An implementation may decline to handle an operation by returning (nil, nil).
283// For this reason, clients should always call the standalone Binary(op, x, y)
284// function rather than calling the method directly.
285type HasBinary interface {
286 Value
287 Binary(op syntax.Token, y Value, side Side) (Value, error)
288}
289
290type Side bool
291
292const (
293 Left Side = false
294 Right Side = true
295)
296
alandonovan58f91012019-01-03 16:32:47 -0500297// A HasUnary value may be used as the operand of these unary operators:
298// + - ~
299//
300// An implementation may decline to handle an operation by returning (nil, nil).
301// For this reason, clients should always call the standalone Unary(op, x)
302// function rather than calling the method directly.
303type HasUnary interface {
304 Value
305 Unary(op syntax.Token) (Value, error)
306}
307
Alan Donovan312d1a52017-10-02 10:10:28 -0400308// A HasAttrs value has fields or methods that may be read by a dot expression (y = x.f).
309// Attribute names may be listed using the built-in 'dir' function.
310//
311// For implementation convenience, a result of (nil, nil) from Attr is
312// interpreted as a "no such field or method" error. Implementations are
313// free to return a more precise error.
314type HasAttrs interface {
315 Value
316 Attr(name string) (Value, error) // returns (nil, nil) if attribute not present
317 AttrNames() []string // callers must not modify the result.
318}
319
320var (
321 _ HasAttrs = String("")
322 _ HasAttrs = new(List)
323 _ HasAttrs = new(Dict)
324 _ HasAttrs = new(Set)
325)
326
327// A HasSetField value has fields that may be written by a dot expression (x.f = y).
Alan Donovan557c1f12019-02-04 16:12:53 -0500328//
alandonovan6afa1bb2019-02-06 17:49:05 -0500329// An implementation of SetField may return a NoSuchAttrError,
330// in which case the runtime may augment the error message to
331// warn of possible misspelling.
Alan Donovan312d1a52017-10-02 10:10:28 -0400332type HasSetField interface {
333 HasAttrs
334 SetField(name string, val Value) error
335}
336
alandonovan6afa1bb2019-02-06 17:49:05 -0500337// A NoSuchAttrError may be returned by an implementation of
338// HasAttrs.Attr or HasSetField.SetField to indicate that no such field
339// exists. In that case the runtime may augment the error message to
340// warn of possible misspelling.
341type NoSuchAttrError string
342
343func (e NoSuchAttrError) Error() string { return string(e) }
Alan Donovan557c1f12019-02-04 16:12:53 -0500344
Alan Donovan312d1a52017-10-02 10:10:28 -0400345// NoneType is the type of None. Its only legal value is None.
346// (We represent it as a number, not struct{}, so that None may be constant.)
347type NoneType byte
348
349const None = NoneType(0)
350
351func (NoneType) String() string { return "None" }
352func (NoneType) Type() string { return "NoneType" }
353func (NoneType) Freeze() {} // immutable
354func (NoneType) Truth() Bool { return False }
355func (NoneType) Hash() (uint32, error) { return 0, nil }
Alan Donovan312d1a52017-10-02 10:10:28 -0400356
Alan Donovane3deafe2018-10-23 11:05:09 -0400357// Bool is the type of a Starlark bool.
Alan Donovan312d1a52017-10-02 10:10:28 -0400358type Bool bool
359
360const (
361 False Bool = false
362 True Bool = true
363)
364
365func (b Bool) String() string {
366 if b {
367 return "True"
368 } else {
369 return "False"
370 }
371}
372func (b Bool) Type() string { return "bool" }
373func (b Bool) Freeze() {} // immutable
374func (b Bool) Truth() Bool { return b }
375func (b Bool) Hash() (uint32, error) { return uint32(b2i(bool(b))), nil }
376func (x Bool) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
377 y := y_.(Bool)
378 return threeway(op, b2i(bool(x))-b2i(bool(y))), nil
379}
380
Alan Donovane3deafe2018-10-23 11:05:09 -0400381// Float is the type of a Starlark float.
Alan Donovan312d1a52017-10-02 10:10:28 -0400382type Float float64
383
alandonovan3b7e02e2020-11-11 12:03:41 -0500384func (f Float) String() string {
385 var buf strings.Builder
386 f.format(&buf, 'g')
387 return buf.String()
388}
389
390func (f Float) format(buf *strings.Builder, conv byte) {
391 ff := float64(f)
392 if !isFinite(ff) {
393 if math.IsInf(ff, +1) {
394 buf.WriteString("+inf")
395 } else if math.IsInf(ff, -1) {
396 buf.WriteString("-inf")
397 } else {
398 buf.WriteString("nan")
399 }
400 return
401 }
402
403 // %g is the default format used by str.
404 // It uses the minimum precision to avoid ambiguity,
405 // and always includes a '.' or an 'e' so that the value
406 // is self-evidently a float, not an int.
407 if conv == 'g' || conv == 'G' {
408 s := strconv.FormatFloat(ff, conv, -1, 64)
409 buf.WriteString(s)
410 // Ensure result always has a decimal point if no exponent.
411 // "123" -> "123.0"
412 if strings.IndexByte(s, conv-'g'+'e') < 0 && strings.IndexByte(s, '.') < 0 {
413 buf.WriteString(".0")
414 }
415 return
416 }
417
418 // %[eEfF] use 6-digit precision
419 buf.WriteString(strconv.FormatFloat(ff, conv, 6, 64))
420}
421
422func (f Float) Type() string { return "float" }
423func (f Float) Freeze() {} // immutable
424func (f Float) Truth() Bool { return f != 0.0 }
Alan Donovan312d1a52017-10-02 10:10:28 -0400425func (f Float) Hash() (uint32, error) {
426 // Equal float and int values must yield the same hash.
427 // TODO(adonovan): opt: if f is non-integral, and thus not equal
428 // to any Int, we can avoid the Int conversion and use a cheaper hash.
429 if isFinite(float64(f)) {
430 return finiteFloatToInt(f).Hash()
431 }
432 return 1618033, nil // NaN, +/-Inf
433}
434
435func floor(f Float) Float { return Float(math.Floor(float64(f))) }
436
437// isFinite reports whether f represents a finite rational value.
438// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
439func isFinite(f float64) bool {
440 return math.Abs(f) <= math.MaxFloat64
441}
442
443func (x Float) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
444 y := y_.(Float)
alandonovan3b7e02e2020-11-11 12:03:41 -0500445 return threeway(op, floatCmp(x, y)), nil
446}
447
448// floatCmp performs a three-valued comparison on floats,
449// which are totally ordered with NaN > +Inf.
450func floatCmp(x, y Float) int {
451 if x > y {
452 return +1
453 } else if x < y {
454 return -1
455 } else if x == y {
456 return 0
Alan Donovan312d1a52017-10-02 10:10:28 -0400457 }
alandonovan3b7e02e2020-11-11 12:03:41 -0500458
459 // At least one operand is NaN.
460 if x == x {
461 return -1 // y is NaN
462 } else if y == y {
463 return +1 // x is NaN
464 }
465 return 0 // both NaN
Alan Donovan312d1a52017-10-02 10:10:28 -0400466}
467
468func (f Float) rational() *big.Rat { return new(big.Rat).SetFloat64(float64(f)) }
469
470// AsFloat returns the float64 value closest to x.
alandonovan3b7e02e2020-11-11 12:03:41 -0500471// The f result is undefined if x is not a float or Int.
472// The result may be infinite if x is a very large Int.
Alan Donovan312d1a52017-10-02 10:10:28 -0400473func AsFloat(x Value) (f float64, ok bool) {
474 switch x := x.(type) {
475 case Float:
476 return float64(x), true
477 case Int:
478 return float64(x.Float()), true
479 }
480 return 0, false
481}
482
alandonovan227f4aa2020-10-06 17:39:52 -0400483func (x Float) Mod(y Float) Float {
484 z := Float(math.Mod(float64(x), float64(y)))
485 if (x < 0) != (y < 0) && z != 0 {
486 z += y
487 }
488 return z
489}
Alan Donovan312d1a52017-10-02 10:10:28 -0400490
alandonovan58f91012019-01-03 16:32:47 -0500491// Unary implements the operations +float and -float.
492func (f Float) Unary(op syntax.Token) (Value, error) {
493 switch op {
494 case syntax.MINUS:
495 return -f, nil
496 case syntax.PLUS:
497 return +f, nil
498 }
499 return nil, nil
500}
501
alandonovanebe61bd2021-02-12 16:57:32 -0500502// String is the type of a Starlark text string.
Alan Donovan312d1a52017-10-02 10:10:28 -0400503//
alandonovana21eb0f2018-06-25 15:30:48 -0400504// A String encapsulates an an immutable sequence of bytes,
505// but strings are not directly iterable. Instead, iterate
506// over the result of calling one of these four methods:
507// codepoints, codepoint_ords, elems, elem_ords.
alandonovanc996ede2018-10-12 13:53:43 -0400508//
alandonovanebe61bd2021-02-12 16:57:32 -0500509// Strings typically contain text; use Bytes for binary strings.
510// The Starlark spec defines text strings as sequences of UTF-k
511// codes that encode Unicode code points. In this Go implementation,
512// k=8, whereas in a Java implementation, k=16. For portability,
513// operations on strings should aim to avoid assumptions about
514// the value of k.
515//
alandonovanc996ede2018-10-12 13:53:43 -0400516// Warning: the contract of the Value interface's String method is that
Alan Donovane3deafe2018-10-23 11:05:09 -0400517// it returns the value printed in Starlark notation,
alandonovanc996ede2018-10-12 13:53:43 -0400518// so s.String() or fmt.Sprintf("%s", s) returns a quoted string.
519// Use string(s) or s.GoString() or fmt.Sprintf("%#v", s) to obtain the raw contents
Alan Donovane3deafe2018-10-23 11:05:09 -0400520// of a Starlark string as a Go string.
Alan Donovan312d1a52017-10-02 10:10:28 -0400521type String string
522
alandonovanebe61bd2021-02-12 16:57:32 -0500523func (s String) String() string { return syntax.Quote(string(s), false) }
alandonovanc996ede2018-10-12 13:53:43 -0400524func (s String) GoString() string { return string(s) }
Alan Donovan312d1a52017-10-02 10:10:28 -0400525func (s String) Type() string { return "string" }
526func (s String) Freeze() {} // immutable
527func (s String) Truth() Bool { return len(s) > 0 }
528func (s String) Hash() (uint32, error) { return hashString(string(s)), nil }
529func (s String) Len() int { return len(s) } // bytes
530func (s String) Index(i int) Value { return s[i : i+1] }
531
Nick Santosd3cd7362018-05-18 12:58:53 -0400532func (s String) Slice(start, end, step int) Value {
533 if step == 1 {
alandonovan5c7d5aa2018-12-03 17:05:15 -0500534 return s[start:end]
Nick Santosd3cd7362018-05-18 12:58:53 -0400535 }
536
537 sign := signum(step)
538 var str []byte
539 for i := start; signum(end-i) == sign; i += step {
540 str = append(str, s[i])
541 }
542 return String(str)
543}
544
Alan Donovan312d1a52017-10-02 10:10:28 -0400545func (s String) Attr(name string) (Value, error) { return builtinAttr(s, name, stringMethods) }
546func (s String) AttrNames() []string { return builtinAttrNames(stringMethods) }
547
548func (x String) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
549 y := y_.(String)
550 return threeway(op, strings.Compare(string(x), string(y))), nil
551}
552
553func AsString(x Value) (string, bool) { v, ok := x.(String); return string(v), ok }
554
alandonovanebe61bd2021-02-12 16:57:32 -0500555// A stringElems is an iterable whose iterator yields a sequence of
556// elements (bytes), either numerically or as successive substrings.
557// It is an indexable sequence.
558type stringElems struct {
559 s String
560 ords bool
Alan Donovan312d1a52017-10-02 10:10:28 -0400561}
562
alandonovanebe61bd2021-02-12 16:57:32 -0500563var (
564 _ Iterable = (*stringElems)(nil)
565 _ Indexable = (*stringElems)(nil)
566)
Alan Donovan312d1a52017-10-02 10:10:28 -0400567
alandonovanebe61bd2021-02-12 16:57:32 -0500568func (si stringElems) String() string {
alandonovan0569d1c2018-03-29 14:47:42 -0400569 if si.ords {
alandonovanebe61bd2021-02-12 16:57:32 -0500570 return si.s.String() + ".elem_ords()"
alandonovan0569d1c2018-03-29 14:47:42 -0400571 } else {
alandonovanebe61bd2021-02-12 16:57:32 -0500572 return si.s.String() + ".elems()"
Alan Donovan312d1a52017-10-02 10:10:28 -0400573 }
574}
alandonovanebe61bd2021-02-12 16:57:32 -0500575func (si stringElems) Type() string { return "string.elems" }
576func (si stringElems) Freeze() {} // immutable
577func (si stringElems) Truth() Bool { return True }
578func (si stringElems) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", si.Type()) }
579func (si stringElems) Iterate() Iterator { return &stringElemsIterator{si, 0} }
580func (si stringElems) Len() int { return len(si.s) }
581func (si stringElems) Index(i int) Value {
582 if si.ords {
583 return MakeInt(int(si.s[i]))
Alan Donovan312d1a52017-10-02 10:10:28 -0400584 } else {
alandonovanebe61bd2021-02-12 16:57:32 -0500585 // TODO(adonovan): opt: preallocate canonical 1-byte strings
586 // to avoid interface allocation.
587 return si.s[i : i+1]
Alan Donovan312d1a52017-10-02 10:10:28 -0400588 }
589}
Alan Donovan312d1a52017-10-02 10:10:28 -0400590
alandonovanebe61bd2021-02-12 16:57:32 -0500591type stringElemsIterator struct {
592 si stringElems
Alan Donovan312d1a52017-10-02 10:10:28 -0400593 i int
594}
595
alandonovanebe61bd2021-02-12 16:57:32 -0500596func (it *stringElemsIterator) Next(p *Value) bool {
597 if it.i == len(it.si.s) {
598 return false
599 }
600 *p = it.si.Index(it.i)
601 it.i++
602 return true
603}
604
605func (*stringElemsIterator) Done() {}
606
607// A stringCodepoints is an iterable whose iterator yields a sequence of
608// Unicode code points, either numerically or as successive substrings.
609// It is not indexable.
610type stringCodepoints struct {
611 s String
612 ords bool
613}
614
615var _ Iterable = (*stringCodepoints)(nil)
616
617func (si stringCodepoints) String() string {
618 if si.ords {
619 return si.s.String() + ".codepoint_ords()"
620 } else {
621 return si.s.String() + ".codepoints()"
622 }
623}
624func (si stringCodepoints) Type() string { return "string.codepoints" }
625func (si stringCodepoints) Freeze() {} // immutable
626func (si stringCodepoints) Truth() Bool { return True }
627func (si stringCodepoints) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", si.Type()) }
628func (si stringCodepoints) Iterate() Iterator { return &stringCodepointsIterator{si, 0} }
629
630type stringCodepointsIterator struct {
631 si stringCodepoints
632 i int
633}
634
635func (it *stringCodepointsIterator) Next(p *Value) bool {
Alan Donovan312d1a52017-10-02 10:10:28 -0400636 s := it.si.s[it.i:]
637 if s == "" {
638 return false
639 }
alandonovanebe61bd2021-02-12 16:57:32 -0500640 r, sz := utf8.DecodeRuneInString(string(s))
641 if !it.si.ords {
642 if r == utf8.RuneError {
643 *p = String(r)
644 } else {
Alan Donovan312d1a52017-10-02 10:10:28 -0400645 *p = s[:sz]
Alan Donovan312d1a52017-10-02 10:10:28 -0400646 }
Alan Donovan312d1a52017-10-02 10:10:28 -0400647 } else {
alandonovanebe61bd2021-02-12 16:57:32 -0500648 *p = MakeInt(int(r))
Alan Donovan312d1a52017-10-02 10:10:28 -0400649 }
alandonovanebe61bd2021-02-12 16:57:32 -0500650 it.i += sz
Alan Donovan312d1a52017-10-02 10:10:28 -0400651 return true
652}
653
alandonovanebe61bd2021-02-12 16:57:32 -0500654func (*stringCodepointsIterator) Done() {}
Alan Donovan312d1a52017-10-02 10:10:28 -0400655
Alan Donovane3deafe2018-10-23 11:05:09 -0400656// A Function is a function defined by a Starlark def statement or lambda expression.
657// The initialization behavior of a Starlark module is also represented by a Function.
Alan Donovan312d1a52017-10-02 10:10:28 -0400658type Function struct {
alandonovan8c4023c2018-04-02 13:08:46 -0400659 funcode *compile.Funcode
alandonovan3ee16852019-05-28 15:56:13 -0400660 module *module
alandonovan8c4023c2018-04-02 13:08:46 -0400661 defaults Tuple
662 freevars Tuple
alandonovan3ee16852019-05-28 15:56:13 -0400663}
alandonovan8c4023c2018-04-02 13:08:46 -0400664
alandonovan3ee16852019-05-28 15:56:13 -0400665// A module is the dynamic counterpart to a Program.
666// All functions in the same program share a module.
667type module struct {
668 program *compile.Program
alandonovan8c4023c2018-04-02 13:08:46 -0400669 predeclared StringDict
670 globals []Value
671 constants []Value
Alan Donovan312d1a52017-10-02 10:10:28 -0400672}
673
alandonovan3ee16852019-05-28 15:56:13 -0400674// makeGlobalDict returns a new, unfrozen StringDict containing all global
675// variables so far defined in the module.
676func (m *module) makeGlobalDict() StringDict {
677 r := make(StringDict, len(m.program.Globals))
678 for i, id := range m.program.Globals {
679 if v := m.globals[i]; v != nil {
680 r[id.Name] = v
681 }
682 }
683 return r
684}
685
alandonovan93f3e0c2018-03-30 10:42:28 -0400686func (fn *Function) Name() string { return fn.funcode.Name } // "lambda" for anonymous functions
Alessandro Arzilli3b628ff2018-12-05 15:04:35 +0100687func (fn *Function) Doc() string { return fn.funcode.Doc }
alandonovan93f3e0c2018-03-30 10:42:28 -0400688func (fn *Function) Hash() (uint32, error) { return hashString(fn.funcode.Name), nil }
Alan Donovan312d1a52017-10-02 10:10:28 -0400689func (fn *Function) Freeze() { fn.defaults.Freeze(); fn.freevars.Freeze() }
690func (fn *Function) String() string { return toString(fn) }
691func (fn *Function) Type() string { return "function" }
692func (fn *Function) Truth() Bool { return true }
693
alandonovan93f3e0c2018-03-30 10:42:28 -0400694// Globals returns a new, unfrozen StringDict containing all global
695// variables so far defined in the function's module.
alandonovan3ee16852019-05-28 15:56:13 -0400696func (fn *Function) Globals() StringDict { return fn.module.makeGlobalDict() }
alandonovan93f3e0c2018-03-30 10:42:28 -0400697
698func (fn *Function) Position() syntax.Position { return fn.funcode.Pos }
699func (fn *Function) NumParams() int { return fn.funcode.NumParams }
Alan Donovan52153852019-02-13 19:18:15 -0500700func (fn *Function) NumKwonlyParams() int { return fn.funcode.NumKwonlyParams }
alandonovan9b055552018-11-02 14:29:51 -0400701
702// Param returns the name and position of the ith parameter,
703// where 0 <= i < NumParams().
Alan Donovan52153852019-02-13 19:18:15 -0500704// The *args and **kwargs parameters are at the end
705// even if there were optional parameters after *args.
alandonovan93f3e0c2018-03-30 10:42:28 -0400706func (fn *Function) Param(i int) (string, syntax.Position) {
alandonovanfc7a7f42019-07-16 22:31:58 -0400707 if i >= fn.NumParams() {
708 panic(i)
709 }
alandonovan93f3e0c2018-03-30 10:42:28 -0400710 id := fn.funcode.Locals[i]
711 return id.Name, id.Pos
712}
713func (fn *Function) HasVarargs() bool { return fn.funcode.HasVarargs }
714func (fn *Function) HasKwargs() bool { return fn.funcode.HasKwargs }
Alan Donovan312d1a52017-10-02 10:10:28 -0400715
716// A Builtin is a function implemented in Go.
717type Builtin struct {
718 name string
719 fn func(thread *Thread, fn *Builtin, args Tuple, kwargs []Tuple) (Value, error)
720 recv Value // for bound methods (e.g. "".startswith)
721}
722
723func (b *Builtin) Name() string { return b.name }
724func (b *Builtin) Freeze() {
725 if b.recv != nil {
726 b.recv.Freeze()
727 }
728}
729func (b *Builtin) Hash() (uint32, error) {
730 h := hashString(b.name)
731 if b.recv != nil {
732 h ^= 5521
733 }
734 return h, nil
735}
736func (b *Builtin) Receiver() Value { return b.recv }
737func (b *Builtin) String() string { return toString(b) }
alandonovan4cbd8962017-10-19 13:18:36 -0400738func (b *Builtin) Type() string { return "builtin_function_or_method" }
alandonovanaeec83f2018-10-22 13:24:13 -0400739func (b *Builtin) CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error) {
740 return b.fn(thread, b, args, kwargs)
Alan Donovan312d1a52017-10-02 10:10:28 -0400741}
742func (b *Builtin) Truth() Bool { return true }
743
alandonovan4cbd8962017-10-19 13:18:36 -0400744// NewBuiltin returns a new 'builtin_function_or_method' value with the specified name
Alan Donovan312d1a52017-10-02 10:10:28 -0400745// and implementation. It compares unequal with all other values.
746func NewBuiltin(name string, fn func(thread *Thread, fn *Builtin, args Tuple, kwargs []Tuple) (Value, error)) *Builtin {
747 return &Builtin{name: name, fn: fn}
748}
749
750// BindReceiver returns a new Builtin value representing a method
751// closure, that is, a built-in function bound to a receiver value.
752//
alandonovan4cbd8962017-10-19 13:18:36 -0400753// In the example below, the value of f is the string.index
754// built-in method bound to the receiver value "abc":
Alan Donovan312d1a52017-10-02 10:10:28 -0400755//
756// f = "abc".index; f("a"); f("b")
757//
758// In the common case, the receiver is bound only during the call,
759// but this still results in the creation of a temporary method closure:
760//
761// "abc".index("a")
762//
763func (b *Builtin) BindReceiver(recv Value) *Builtin {
764 return &Builtin{name: b.name, fn: b.fn, recv: recv}
765}
766
Alan Donovane3deafe2018-10-23 11:05:09 -0400767// A *Dict represents a Starlark dictionary.
alandonovanf83458d2019-04-02 20:34:11 -0400768// The zero value of Dict is a valid empty dictionary.
769// If you know the exact final number of entries,
770// it is more efficient to call NewDict.
Alan Donovan312d1a52017-10-02 10:10:28 -0400771type Dict struct {
772 ht hashtable
773}
774
alandonovanf83458d2019-04-02 20:34:11 -0400775// NewDict returns a set with initial space for
776// at least size insertions before rehashing.
777func NewDict(size int) *Dict {
778 dict := new(Dict)
779 dict.ht.init(size)
780 return dict
781}
782
Alan Donovan312d1a52017-10-02 10:10:28 -0400783func (d *Dict) Clear() error { return d.ht.clear() }
784func (d *Dict) Delete(k Value) (v Value, found bool, err error) { return d.ht.delete(k) }
785func (d *Dict) Get(k Value) (v Value, found bool, err error) { return d.ht.lookup(k) }
786func (d *Dict) Items() []Tuple { return d.ht.items() }
787func (d *Dict) Keys() []Value { return d.ht.keys() }
788func (d *Dict) Len() int { return int(d.ht.len) }
789func (d *Dict) Iterate() Iterator { return d.ht.iterate() }
jmillikin-stripe3ccab942018-10-05 07:09:12 -0700790func (d *Dict) SetKey(k, v Value) error { return d.ht.insert(k, v) }
Alan Donovan312d1a52017-10-02 10:10:28 -0400791func (d *Dict) String() string { return toString(d) }
792func (d *Dict) Type() string { return "dict" }
793func (d *Dict) Freeze() { d.ht.freeze() }
794func (d *Dict) Truth() Bool { return d.Len() > 0 }
795func (d *Dict) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable type: dict") }
796
797func (d *Dict) Attr(name string) (Value, error) { return builtinAttr(d, name, dictMethods) }
798func (d *Dict) AttrNames() []string { return builtinAttrNames(dictMethods) }
799
800func (x *Dict) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
801 y := y_.(*Dict)
802 switch op {
803 case syntax.EQL:
804 ok, err := dictsEqual(x, y, depth)
805 return ok, err
806 case syntax.NEQ:
807 ok, err := dictsEqual(x, y, depth)
808 return !ok, err
809 default:
810 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
811 }
812}
813
814func dictsEqual(x, y *Dict, depth int) (bool, error) {
815 if x.Len() != y.Len() {
816 return false, nil
817 }
818 for _, xitem := range x.Items() {
819 key, xval := xitem[0], xitem[1]
820
821 if yval, found, _ := y.Get(key); !found {
822 return false, nil
823 } else if eq, err := EqualDepth(xval, yval, depth-1); err != nil {
824 return false, err
825 } else if !eq {
826 return false, nil
827 }
828 }
829 return true, nil
830}
831
Alan Donovane3deafe2018-10-23 11:05:09 -0400832// A *List represents a Starlark list value.
Alan Donovan312d1a52017-10-02 10:10:28 -0400833type List struct {
834 elems []Value
835 frozen bool
836 itercount uint32 // number of active iterators (ignored if frozen)
837}
838
839// NewList returns a list containing the specified elements.
840// Callers should not subsequently modify elems.
841func NewList(elems []Value) *List { return &List{elems: elems} }
842
843func (l *List) Freeze() {
844 if !l.frozen {
845 l.frozen = true
846 for _, elem := range l.elems {
847 elem.Freeze()
848 }
849 }
850}
851
852// checkMutable reports an error if the list should not be mutated.
853// verb+" list" should describe the operation.
alandonovan7c0e5a32018-11-02 15:38:05 -0400854func (l *List) checkMutable(verb string) error {
Alan Donovan312d1a52017-10-02 10:10:28 -0400855 if l.frozen {
856 return fmt.Errorf("cannot %s frozen list", verb)
857 }
alandonovan7c0e5a32018-11-02 15:38:05 -0400858 if l.itercount > 0 {
Alan Donovan312d1a52017-10-02 10:10:28 -0400859 return fmt.Errorf("cannot %s list during iteration", verb)
860 }
861 return nil
862}
863
864func (l *List) String() string { return toString(l) }
865func (l *List) Type() string { return "list" }
866func (l *List) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable type: list") }
867func (l *List) Truth() Bool { return l.Len() > 0 }
868func (l *List) Len() int { return len(l.elems) }
869func (l *List) Index(i int) Value { return l.elems[i] }
870
Nick Santosd3cd7362018-05-18 12:58:53 -0400871func (l *List) Slice(start, end, step int) Value {
872 if step == 1 {
873 elems := append([]Value{}, l.elems[start:end]...)
874 return NewList(elems)
875 }
876
877 sign := signum(step)
878 var list []Value
879 for i := start; signum(end-i) == sign; i += step {
880 list = append(list, l.elems[i])
881 }
882 return NewList(list)
883}
884
Alan Donovan312d1a52017-10-02 10:10:28 -0400885func (l *List) Attr(name string) (Value, error) { return builtinAttr(l, name, listMethods) }
886func (l *List) AttrNames() []string { return builtinAttrNames(listMethods) }
887
888func (l *List) Iterate() Iterator {
889 if !l.frozen {
890 l.itercount++
891 }
892 return &listIterator{l: l}
893}
894
895func (x *List) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
896 y := y_.(*List)
897 // It's tempting to check x == y as an optimization here,
898 // but wrong because a list containing NaN is not equal to itself.
899 return sliceCompare(op, x.elems, y.elems, depth)
900}
901
902func sliceCompare(op syntax.Token, x, y []Value, depth int) (bool, error) {
903 // Fast path: check length.
904 if len(x) != len(y) && (op == syntax.EQL || op == syntax.NEQ) {
905 return op == syntax.NEQ, nil
906 }
907
908 // Find first element that is not equal in both lists.
909 for i := 0; i < len(x) && i < len(y); i++ {
910 if eq, err := EqualDepth(x[i], y[i], depth-1); err != nil {
911 return false, err
912 } else if !eq {
913 switch op {
914 case syntax.EQL:
915 return false, nil
916 case syntax.NEQ:
917 return true, nil
918 default:
919 return CompareDepth(op, x[i], y[i], depth-1)
920 }
921 }
922 }
923
924 return threeway(op, len(x)-len(y)), nil
925}
926
927type listIterator struct {
928 l *List
929 i int
930}
931
932func (it *listIterator) Next(p *Value) bool {
933 if it.i < it.l.Len() {
934 *p = it.l.elems[it.i]
935 it.i++
936 return true
937 }
938 return false
939}
940
941func (it *listIterator) Done() {
942 if !it.l.frozen {
943 it.l.itercount--
944 }
945}
946
947func (l *List) SetIndex(i int, v Value) error {
alandonovan7c0e5a32018-11-02 15:38:05 -0400948 if err := l.checkMutable("assign to element of"); err != nil {
Alan Donovan312d1a52017-10-02 10:10:28 -0400949 return err
950 }
951 l.elems[i] = v
952 return nil
953}
954
955func (l *List) Append(v Value) error {
alandonovan7c0e5a32018-11-02 15:38:05 -0400956 if err := l.checkMutable("append to"); err != nil {
Alan Donovan312d1a52017-10-02 10:10:28 -0400957 return err
958 }
959 l.elems = append(l.elems, v)
960 return nil
961}
962
963func (l *List) Clear() error {
alandonovan7c0e5a32018-11-02 15:38:05 -0400964 if err := l.checkMutable("clear"); err != nil {
Alan Donovan312d1a52017-10-02 10:10:28 -0400965 return err
966 }
967 for i := range l.elems {
968 l.elems[i] = nil // aid GC
969 }
970 l.elems = l.elems[:0]
971 return nil
972}
973
Alan Donovane3deafe2018-10-23 11:05:09 -0400974// A Tuple represents a Starlark tuple value.
Alan Donovan312d1a52017-10-02 10:10:28 -0400975type Tuple []Value
976
977func (t Tuple) Len() int { return len(t) }
978func (t Tuple) Index(i int) Value { return t[i] }
Nick Santosd3cd7362018-05-18 12:58:53 -0400979
980func (t Tuple) Slice(start, end, step int) Value {
981 if step == 1 {
982 return t[start:end]
983 }
984
985 sign := signum(step)
986 var tuple Tuple
987 for i := start; signum(end-i) == sign; i += step {
988 tuple = append(tuple, t[i])
989 }
990 return tuple
991}
992
Alan Donovan312d1a52017-10-02 10:10:28 -0400993func (t Tuple) Iterate() Iterator { return &tupleIterator{elems: t} }
994func (t Tuple) Freeze() {
995 for _, elem := range t {
996 elem.Freeze()
997 }
998}
999func (t Tuple) String() string { return toString(t) }
1000func (t Tuple) Type() string { return "tuple" }
1001func (t Tuple) Truth() Bool { return len(t) > 0 }
1002
1003func (x Tuple) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
1004 y := y_.(Tuple)
1005 return sliceCompare(op, x, y, depth)
1006}
1007
1008func (t Tuple) Hash() (uint32, error) {
1009 // Use same algorithm as Python.
1010 var x, mult uint32 = 0x345678, 1000003
1011 for _, elem := range t {
1012 y, err := elem.Hash()
1013 if err != nil {
1014 return 0, err
1015 }
1016 x = x ^ y*mult
1017 mult += 82520 + uint32(len(t)+len(t))
1018 }
1019 return x, nil
1020}
1021
1022type tupleIterator struct{ elems Tuple }
1023
1024func (it *tupleIterator) Next(p *Value) bool {
1025 if len(it.elems) > 0 {
1026 *p = it.elems[0]
1027 it.elems = it.elems[1:]
1028 return true
1029 }
1030 return false
1031}
1032
1033func (it *tupleIterator) Done() {}
1034
Alan Donovane3deafe2018-10-23 11:05:09 -04001035// A Set represents a Starlark set value.
alandonovanf83458d2019-04-02 20:34:11 -04001036// The zero value of Set is a valid empty set.
1037// If you know the exact final number of elements,
1038// it is more efficient to call NewSet.
Alan Donovan312d1a52017-10-02 10:10:28 -04001039type Set struct {
1040 ht hashtable // values are all None
1041}
1042
alandonovanf83458d2019-04-02 20:34:11 -04001043// NewSet returns a dictionary with initial space for
1044// at least size insertions before rehashing.
1045func NewSet(size int) *Set {
1046 set := new(Set)
1047 set.ht.init(size)
1048 return set
1049}
1050
Alan Donovan312d1a52017-10-02 10:10:28 -04001051func (s *Set) Delete(k Value) (found bool, err error) { _, found, err = s.ht.delete(k); return }
1052func (s *Set) Clear() error { return s.ht.clear() }
1053func (s *Set) Has(k Value) (found bool, err error) { _, found, err = s.ht.lookup(k); return }
1054func (s *Set) Insert(k Value) error { return s.ht.insert(k, None) }
1055func (s *Set) Len() int { return int(s.ht.len) }
1056func (s *Set) Iterate() Iterator { return s.ht.iterate() }
1057func (s *Set) String() string { return toString(s) }
1058func (s *Set) Type() string { return "set" }
1059func (s *Set) elems() []Value { return s.ht.keys() }
1060func (s *Set) Freeze() { s.ht.freeze() }
1061func (s *Set) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable type: set") }
1062func (s *Set) Truth() Bool { return s.Len() > 0 }
1063
1064func (s *Set) Attr(name string) (Value, error) { return builtinAttr(s, name, setMethods) }
1065func (s *Set) AttrNames() []string { return builtinAttrNames(setMethods) }
1066
1067func (x *Set) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
1068 y := y_.(*Set)
1069 switch op {
1070 case syntax.EQL:
1071 ok, err := setsEqual(x, y, depth)
1072 return ok, err
1073 case syntax.NEQ:
1074 ok, err := setsEqual(x, y, depth)
1075 return !ok, err
1076 default:
1077 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
1078 }
1079}
1080
1081func setsEqual(x, y *Set, depth int) (bool, error) {
1082 if x.Len() != y.Len() {
1083 return false, nil
1084 }
1085 for _, elem := range x.elems() {
1086 if found, _ := y.Has(elem); !found {
1087 return false, nil
1088 }
1089 }
1090 return true, nil
1091}
1092
1093func (s *Set) Union(iter Iterator) (Value, error) {
1094 set := new(Set)
1095 for _, elem := range s.elems() {
1096 set.Insert(elem) // can't fail
1097 }
1098 var x Value
1099 for iter.Next(&x) {
1100 if err := set.Insert(x); err != nil {
1101 return nil, err
1102 }
1103 }
1104 return set, nil
1105}
1106
1107// toString returns the string form of value v.
1108// It may be more efficient than v.String() for larger values.
1109func toString(v Value) string {
Josh Bleecher Snyder8cb25c82019-03-01 14:24:35 -08001110 buf := new(strings.Builder)
1111 writeValue(buf, v, nil)
Alan Donovan312d1a52017-10-02 10:10:28 -04001112 return buf.String()
1113}
1114
alandonovan0ed7e5b2019-01-03 16:11:58 -05001115// writeValue writes x to out.
1116//
1117// path is used to detect cycles.
1118// It contains the list of *List and *Dict values we're currently printing.
Alan Donovan312d1a52017-10-02 10:10:28 -04001119// (These are the only potentially cyclic structures.)
Josh Bleecher Snyder81e440d2019-03-02 07:02:02 -08001120// Callers should generally pass nil for path.
alandonovan0ed7e5b2019-01-03 16:11:58 -05001121// It is safe to re-use the same path slice for multiple calls.
Josh Bleecher Snyder8cb25c82019-03-01 14:24:35 -08001122func writeValue(out *strings.Builder, x Value, path []Value) {
Alan Donovan312d1a52017-10-02 10:10:28 -04001123 switch x := x.(type) {
alandonovan15a68dc2018-03-05 16:23:41 -05001124 case nil:
1125 out.WriteString("<nil>") // indicates a bug
1126
alandonovanebe61bd2021-02-12 16:57:32 -05001127 // These four cases are duplicates of T.String(), for efficiency.
Alan Donovan312d1a52017-10-02 10:10:28 -04001128 case NoneType:
1129 out.WriteString("None")
1130
1131 case Int:
1132 out.WriteString(x.String())
1133
1134 case Bool:
1135 if x {
1136 out.WriteString("True")
1137 } else {
1138 out.WriteString("False")
1139 }
1140
1141 case String:
alandonovanebe61bd2021-02-12 16:57:32 -05001142 out.WriteString(syntax.Quote(string(x), false))
Alan Donovan312d1a52017-10-02 10:10:28 -04001143
1144 case *List:
1145 out.WriteByte('[')
1146 if pathContains(path, x) {
1147 out.WriteString("...") // list contains itself
1148 } else {
1149 for i, elem := range x.elems {
1150 if i > 0 {
1151 out.WriteString(", ")
1152 }
1153 writeValue(out, elem, append(path, x))
1154 }
1155 }
1156 out.WriteByte(']')
1157
1158 case Tuple:
1159 out.WriteByte('(')
1160 for i, elem := range x {
1161 if i > 0 {
1162 out.WriteString(", ")
1163 }
1164 writeValue(out, elem, path)
1165 }
1166 if len(x) == 1 {
1167 out.WriteByte(',')
1168 }
1169 out.WriteByte(')')
1170
1171 case *Function:
1172 fmt.Fprintf(out, "<function %s>", x.Name())
1173
1174 case *Builtin:
1175 if x.recv != nil {
1176 fmt.Fprintf(out, "<built-in method %s of %s value>", x.Name(), x.recv.Type())
1177 } else {
1178 fmt.Fprintf(out, "<built-in function %s>", x.Name())
1179 }
1180
1181 case *Dict:
1182 out.WriteByte('{')
1183 if pathContains(path, x) {
1184 out.WriteString("...") // dict contains itself
1185 } else {
1186 sep := ""
1187 for _, item := range x.Items() {
1188 k, v := item[0], item[1]
1189 out.WriteString(sep)
1190 writeValue(out, k, path)
1191 out.WriteString(": ")
1192 writeValue(out, v, append(path, x)) // cycle check
1193 sep = ", "
1194 }
1195 }
1196 out.WriteByte('}')
1197
1198 case *Set:
1199 out.WriteString("set([")
1200 for i, elem := range x.elems() {
1201 if i > 0 {
1202 out.WriteString(", ")
1203 }
1204 writeValue(out, elem, path)
1205 }
1206 out.WriteString("])")
1207
1208 default:
1209 out.WriteString(x.String())
1210 }
1211}
1212
1213func pathContains(path []Value, x Value) bool {
1214 for _, y := range path {
1215 if x == y {
1216 return true
1217 }
1218 }
1219 return false
1220}
1221
1222const maxdepth = 10
1223
Alan Donovane3deafe2018-10-23 11:05:09 -04001224// Equal reports whether two Starlark values are equal.
Alan Donovan312d1a52017-10-02 10:10:28 -04001225func Equal(x, y Value) (bool, error) {
alandonovan4bb5ab62018-03-06 20:21:45 -05001226 if x, ok := x.(String); ok {
1227 return x == y, nil // fast path for an important special case
1228 }
Alan Donovan312d1a52017-10-02 10:10:28 -04001229 return EqualDepth(x, y, maxdepth)
1230}
1231
Alan Donovane3deafe2018-10-23 11:05:09 -04001232// EqualDepth reports whether two Starlark values are equal.
Alan Donovan312d1a52017-10-02 10:10:28 -04001233//
1234// Recursive comparisons by implementations of Value.CompareSameType
1235// should use EqualDepth to prevent infinite recursion.
1236func EqualDepth(x, y Value, depth int) (bool, error) {
1237 return CompareDepth(syntax.EQL, x, y, depth)
1238}
1239
Alan Donovane3deafe2018-10-23 11:05:09 -04001240// Compare compares two Starlark values.
Alan Donovan312d1a52017-10-02 10:10:28 -04001241// The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE.
1242// Compare returns an error if an ordered comparison was
1243// requested for a type that does not support it.
1244//
1245// Recursive comparisons by implementations of Value.CompareSameType
1246// should use CompareDepth to prevent infinite recursion.
1247func Compare(op syntax.Token, x, y Value) (bool, error) {
1248 return CompareDepth(op, x, y, maxdepth)
1249}
1250
Alan Donovane3deafe2018-10-23 11:05:09 -04001251// CompareDepth compares two Starlark values.
Alan Donovan312d1a52017-10-02 10:10:28 -04001252// The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE.
1253// CompareDepth returns an error if an ordered comparison was
1254// requested for a pair of values that do not support it.
1255//
1256// The depth parameter limits the maximum depth of recursion
1257// in cyclic data structures.
1258func CompareDepth(op syntax.Token, x, y Value, depth int) (bool, error) {
1259 if depth < 1 {
1260 return false, fmt.Errorf("comparison exceeded maximum recursion depth")
1261 }
1262 if sameType(x, y) {
1263 if xcomp, ok := x.(Comparable); ok {
1264 return xcomp.CompareSameType(op, y, depth)
1265 }
1266
1267 // use identity comparison
1268 switch op {
1269 case syntax.EQL:
1270 return x == y, nil
1271 case syntax.NEQ:
1272 return x != y, nil
1273 }
1274 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
1275 }
1276
1277 // different types
1278
1279 // int/float ordered comparisons
1280 switch x := x.(type) {
1281 case Int:
1282 if y, ok := y.(Float); ok {
Alan Donovan312d1a52017-10-02 10:10:28 -04001283 var cmp int
alandonovan3b7e02e2020-11-11 12:03:41 -05001284 if y != y {
1285 cmp = -1 // y is NaN
1286 } else if !math.IsInf(float64(y), 0) {
Alan Donovan312d1a52017-10-02 10:10:28 -04001287 cmp = x.rational().Cmp(y.rational()) // y is finite
1288 } else if y > 0 {
1289 cmp = -1 // y is +Inf
1290 } else {
1291 cmp = +1 // y is -Inf
1292 }
1293 return threeway(op, cmp), nil
1294 }
1295 case Float:
1296 if y, ok := y.(Int); ok {
Alan Donovan312d1a52017-10-02 10:10:28 -04001297 var cmp int
alandonovan3b7e02e2020-11-11 12:03:41 -05001298 if x != x {
1299 cmp = +1 // x is NaN
1300 } else if !math.IsInf(float64(x), 0) {
Alan Donovan312d1a52017-10-02 10:10:28 -04001301 cmp = x.rational().Cmp(y.rational()) // x is finite
1302 } else if x > 0 {
alandonovan3b7e02e2020-11-11 12:03:41 -05001303 cmp = +1 // x is +Inf
Alan Donovan312d1a52017-10-02 10:10:28 -04001304 } else {
alandonovan3b7e02e2020-11-11 12:03:41 -05001305 cmp = -1 // x is -Inf
Alan Donovan312d1a52017-10-02 10:10:28 -04001306 }
1307 return threeway(op, cmp), nil
1308 }
1309 }
1310
1311 // All other values of different types compare unequal.
1312 switch op {
1313 case syntax.EQL:
1314 return false, nil
1315 case syntax.NEQ:
1316 return true, nil
1317 }
1318 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
1319}
1320
1321func sameType(x, y Value) bool {
1322 return reflect.TypeOf(x) == reflect.TypeOf(y) || x.Type() == y.Type()
1323}
1324
1325// threeway interprets a three-way comparison value cmp (-1, 0, +1)
1326// as a boolean comparison (e.g. x < y).
1327func threeway(op syntax.Token, cmp int) bool {
1328 switch op {
1329 case syntax.EQL:
1330 return cmp == 0
1331 case syntax.NEQ:
1332 return cmp != 0
1333 case syntax.LE:
1334 return cmp <= 0
1335 case syntax.LT:
1336 return cmp < 0
1337 case syntax.GE:
1338 return cmp >= 0
1339 case syntax.GT:
1340 return cmp > 0
1341 }
1342 panic(op)
1343}
1344
1345func b2i(b bool) int {
1346 if b {
1347 return 1
1348 } else {
1349 return 0
1350 }
1351}
1352
1353// Len returns the length of a string or sequence value,
1354// and -1 for all others.
1355//
1356// Warning: Len(x) >= 0 does not imply Iterate(x) != nil.
1357// A string has a known length but is not directly iterable.
1358func Len(x Value) int {
1359 switch x := x.(type) {
1360 case String:
1361 return x.Len()
alandonovanebe61bd2021-02-12 16:57:32 -05001362 case Indexable:
1363 return x.Len()
Alan Donovan312d1a52017-10-02 10:10:28 -04001364 case Sequence:
1365 return x.Len()
1366 }
1367 return -1
1368}
1369
1370// Iterate return a new iterator for the value if iterable, nil otherwise.
1371// If the result is non-nil, the caller must call Done when finished with it.
1372//
1373// Warning: Iterate(x) != nil does not imply Len(x) >= 0.
1374// Some iterables may have unknown length.
1375func Iterate(x Value) Iterator {
1376 if x, ok := x.(Iterable); ok {
1377 return x.Iterate()
1378 }
1379 return nil
1380}
alandonovanebe61bd2021-02-12 16:57:32 -05001381
1382// Bytes is the type of a Starlark binary string.
1383//
1384// A Bytes encapsulates an immutable sequence of bytes.
1385// It is comparable, indexable, and sliceable, but not direcly iterable;
1386// use bytes.elems() for an iterable view.
1387//
1388// In this Go implementation, the elements of 'string' and 'bytes' are
1389// both bytes, but in other implementations, notably Java, the elements
1390// of a 'string' are UTF-16 codes (Java chars). The spec abstracts text
1391// strings as sequences of UTF-k codes that encode Unicode code points,
1392// and operations that convert from text to binary incur UTF-k-to-UTF-8
1393// transcoding; conversely, conversion from binary to text incurs
1394// UTF-8-to-UTF-k transcoding. Because k=8 for Go, these operations
1395// are the identity function, at least for valid encodings of text.
1396type Bytes string
1397
1398var (
1399 _ Comparable = Bytes("")
1400 _ Sliceable = Bytes("")
1401 _ Indexable = Bytes("")
1402)
1403
1404func (b Bytes) String() string { return syntax.Quote(string(b), true) }
1405func (b Bytes) Type() string { return "bytes" }
1406func (b Bytes) Freeze() {} // immutable
1407func (b Bytes) Truth() Bool { return len(b) > 0 }
1408func (b Bytes) Hash() (uint32, error) { return String(b).Hash() }
1409func (b Bytes) Len() int { return len(b) }
1410func (b Bytes) Index(i int) Value { return b[i : i+1] }
1411
1412func (b Bytes) Attr(name string) (Value, error) { return builtinAttr(b, name, bytesMethods) }
1413func (b Bytes) AttrNames() []string { return builtinAttrNames(bytesMethods) }
1414
1415func (b Bytes) Slice(start, end, step int) Value {
1416 if step == 1 {
1417 return b[start:end]
1418 }
1419
1420 sign := signum(step)
1421 var str []byte
1422 for i := start; signum(end-i) == sign; i += step {
1423 str = append(str, b[i])
1424 }
1425 return Bytes(str)
1426}
1427
1428func (x Bytes) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
1429 y := y_.(Bytes)
1430 return threeway(op, strings.Compare(string(x), string(y))), nil
1431}