go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/starlark/value.go (about)

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