go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/starlark/library.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
     6  
     7  // This file defines the library of built-ins.
     8  //
     9  // Built-ins must explicitly check the "frozen" flag before updating
    10  // mutable types such as lists and dicts.
    11  
    12  import (
    13  	"errors"
    14  	"fmt"
    15  	"math"
    16  	"math/big"
    17  	"os"
    18  	"sort"
    19  	"strconv"
    20  	"strings"
    21  	"unicode"
    22  	"unicode/utf16"
    23  	"unicode/utf8"
    24  
    25  	"go.starlark.net/syntax"
    26  )
    27  
    28  // Universe defines the set of universal built-ins, such as None, True, and len.
    29  //
    30  // The Go application may add or remove items from the
    31  // universe dictionary before Starlark evaluation begins.
    32  // All values in the dictionary must be immutable.
    33  // Starlark programs cannot modify the dictionary.
    34  var Universe StringDict
    35  
    36  func init() {
    37  	// https://github.com/google/starlark-go/blob/master/doc/spec.md#built-in-constants-and-functions
    38  	Universe = StringDict{
    39  		"None":      None,
    40  		"True":      True,
    41  		"False":     False,
    42  		"abs":       NewBuiltin("abs", abs),
    43  		"any":       NewBuiltin("any", any),
    44  		"all":       NewBuiltin("all", all),
    45  		"bool":      NewBuiltin("bool", bool_),
    46  		"bytes":     NewBuiltin("bytes", bytes_),
    47  		"chr":       NewBuiltin("chr", chr),
    48  		"dict":      NewBuiltin("dict", dict),
    49  		"dir":       NewBuiltin("dir", dir),
    50  		"enumerate": NewBuiltin("enumerate", enumerate),
    51  		"fail":      NewBuiltin("fail", fail),
    52  		"float":     NewBuiltin("float", float),
    53  		"getattr":   NewBuiltin("getattr", getattr),
    54  		"hasattr":   NewBuiltin("hasattr", hasattr),
    55  		"hash":      NewBuiltin("hash", hash),
    56  		"int":       NewBuiltin("int", int_),
    57  		"len":       NewBuiltin("len", len_),
    58  		"list":      NewBuiltin("list", list),
    59  		"max":       NewBuiltin("max", minmax),
    60  		"min":       NewBuiltin("min", minmax),
    61  		"ord":       NewBuiltin("ord", ord),
    62  		"print":     NewBuiltin("print", print),
    63  		"range":     NewBuiltin("range", range_),
    64  		"repr":      NewBuiltin("repr", repr),
    65  		"reversed":  NewBuiltin("reversed", reversed),
    66  		"set":       NewBuiltin("set", set), // requires resolve.AllowSet
    67  		"sorted":    NewBuiltin("sorted", sorted),
    68  		"str":       NewBuiltin("str", str),
    69  		"tuple":     NewBuiltin("tuple", tuple),
    70  		"type":      NewBuiltin("type", type_),
    71  		"zip":       NewBuiltin("zip", zip),
    72  	}
    73  }
    74  
    75  // methods of built-in types
    76  // https://github.com/google/starlark-go/blob/master/doc/spec.md#built-in-methods
    77  var (
    78  	bytesMethods = map[string]*Builtin{
    79  		"elems": NewBuiltin("elems", bytes_elems),
    80  	}
    81  
    82  	dictMethods = map[string]*Builtin{
    83  		"clear":      NewBuiltin("clear", dict_clear),
    84  		"get":        NewBuiltin("get", dict_get),
    85  		"items":      NewBuiltin("items", dict_items),
    86  		"keys":       NewBuiltin("keys", dict_keys),
    87  		"pop":        NewBuiltin("pop", dict_pop),
    88  		"popitem":    NewBuiltin("popitem", dict_popitem),
    89  		"setdefault": NewBuiltin("setdefault", dict_setdefault),
    90  		"update":     NewBuiltin("update", dict_update),
    91  		"values":     NewBuiltin("values", dict_values),
    92  	}
    93  
    94  	listMethods = map[string]*Builtin{
    95  		"append": NewBuiltin("append", list_append),
    96  		"clear":  NewBuiltin("clear", list_clear),
    97  		"extend": NewBuiltin("extend", list_extend),
    98  		"index":  NewBuiltin("index", list_index),
    99  		"insert": NewBuiltin("insert", list_insert),
   100  		"pop":    NewBuiltin("pop", list_pop),
   101  		"remove": NewBuiltin("remove", list_remove),
   102  	}
   103  
   104  	stringMethods = map[string]*Builtin{
   105  		"capitalize":     NewBuiltin("capitalize", string_capitalize),
   106  		"codepoint_ords": NewBuiltin("codepoint_ords", string_iterable),
   107  		"codepoints":     NewBuiltin("codepoints", string_iterable), // sic
   108  		"count":          NewBuiltin("count", string_count),
   109  		"elem_ords":      NewBuiltin("elem_ords", string_iterable),
   110  		"elems":          NewBuiltin("elems", string_iterable),      // sic
   111  		"endswith":       NewBuiltin("endswith", string_startswith), // sic
   112  		"find":           NewBuiltin("find", string_find),
   113  		"format":         NewBuiltin("format", string_format),
   114  		"index":          NewBuiltin("index", string_index),
   115  		"isalnum":        NewBuiltin("isalnum", string_isalnum),
   116  		"isalpha":        NewBuiltin("isalpha", string_isalpha),
   117  		"isdigit":        NewBuiltin("isdigit", string_isdigit),
   118  		"islower":        NewBuiltin("islower", string_islower),
   119  		"isspace":        NewBuiltin("isspace", string_isspace),
   120  		"istitle":        NewBuiltin("istitle", string_istitle),
   121  		"isupper":        NewBuiltin("isupper", string_isupper),
   122  		"join":           NewBuiltin("join", string_join),
   123  		"lower":          NewBuiltin("lower", string_lower),
   124  		"lstrip":         NewBuiltin("lstrip", string_strip), // sic
   125  		"partition":      NewBuiltin("partition", string_partition),
   126  		"removeprefix":   NewBuiltin("removeprefix", string_removefix),
   127  		"removesuffix":   NewBuiltin("removesuffix", string_removefix),
   128  		"replace":        NewBuiltin("replace", string_replace),
   129  		"rfind":          NewBuiltin("rfind", string_rfind),
   130  		"rindex":         NewBuiltin("rindex", string_rindex),
   131  		"rpartition":     NewBuiltin("rpartition", string_partition), // sic
   132  		"rsplit":         NewBuiltin("rsplit", string_split),         // sic
   133  		"rstrip":         NewBuiltin("rstrip", string_strip),         // sic
   134  		"split":          NewBuiltin("split", string_split),
   135  		"splitlines":     NewBuiltin("splitlines", string_splitlines),
   136  		"startswith":     NewBuiltin("startswith", string_startswith),
   137  		"strip":          NewBuiltin("strip", string_strip),
   138  		"title":          NewBuiltin("title", string_title),
   139  		"upper":          NewBuiltin("upper", string_upper),
   140  	}
   141  
   142  	setMethods = map[string]*Builtin{
   143  		"add":                  NewBuiltin("add", set_add),
   144  		"clear":                NewBuiltin("clear", set_clear),
   145  		"difference":           NewBuiltin("difference", set_difference),
   146  		"discard":              NewBuiltin("discard", set_discard),
   147  		"intersection":         NewBuiltin("intersection", set_intersection),
   148  		"issubset":             NewBuiltin("issubset", set_issubset),
   149  		"issuperset":           NewBuiltin("issuperset", set_issuperset),
   150  		"pop":                  NewBuiltin("pop", set_pop),
   151  		"remove":               NewBuiltin("remove", set_remove),
   152  		"symmetric_difference": NewBuiltin("symmetric_difference", set_symmetric_difference),
   153  		"union":                NewBuiltin("union", set_union),
   154  	}
   155  )
   156  
   157  func builtinAttr(recv Value, name string, methods map[string]*Builtin) (Value, error) {
   158  	b := methods[name]
   159  	if b == nil {
   160  		return nil, nil // no such method
   161  	}
   162  	return b.BindReceiver(recv), nil
   163  }
   164  
   165  func builtinAttrNames(methods map[string]*Builtin) []string {
   166  	names := make([]string, 0, len(methods))
   167  	for name := range methods {
   168  		names = append(names, name)
   169  	}
   170  	sort.Strings(names)
   171  	return names
   172  }
   173  
   174  // ---- built-in functions ----
   175  
   176  // https://github.com/google/starlark-go/blob/master/doc/spec.md#abs
   177  func abs(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   178  	var x Value
   179  	if err := UnpackPositionalArgs("abs", args, kwargs, 1, &x); err != nil {
   180  		return nil, err
   181  	}
   182  	switch x := x.(type) {
   183  	case Float:
   184  		return Float(math.Abs(float64(x))), nil
   185  	case Int:
   186  		if x.Sign() >= 0 {
   187  			return x, nil
   188  		}
   189  		return zero.Sub(x), nil
   190  	default:
   191  		return nil, fmt.Errorf("got %s, want int or float", x.Type())
   192  	}
   193  }
   194  
   195  // https://github.com/google/starlark-go/blob/master/doc/spec.md#all
   196  func all(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   197  	var iterable Iterable
   198  	if err := UnpackPositionalArgs("all", args, kwargs, 1, &iterable); err != nil {
   199  		return nil, err
   200  	}
   201  	iter := iterable.Iterate()
   202  	defer iter.Done()
   203  	var x Value
   204  	for iter.Next(&x) {
   205  		if !x.Truth() {
   206  			return False, nil
   207  		}
   208  	}
   209  	return True, nil
   210  }
   211  
   212  // https://github.com/google/starlark-go/blob/master/doc/spec.md#any
   213  func any(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   214  	var iterable Iterable
   215  	if err := UnpackPositionalArgs("any", args, kwargs, 1, &iterable); err != nil {
   216  		return nil, err
   217  	}
   218  	iter := iterable.Iterate()
   219  	defer iter.Done()
   220  	var x Value
   221  	for iter.Next(&x) {
   222  		if x.Truth() {
   223  			return True, nil
   224  		}
   225  	}
   226  	return False, nil
   227  }
   228  
   229  // https://github.com/google/starlark-go/blob/master/doc/spec.md#bool
   230  func bool_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   231  	var x Value = False
   232  	if err := UnpackPositionalArgs("bool", args, kwargs, 0, &x); err != nil {
   233  		return nil, err
   234  	}
   235  	return x.Truth(), nil
   236  }
   237  
   238  // https://github.com/google/starlark-go/blob/master/doc/spec.md#bytes
   239  func bytes_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   240  	if len(kwargs) > 0 {
   241  		return nil, fmt.Errorf("bytes does not accept keyword arguments")
   242  	}
   243  	if len(args) != 1 {
   244  		return nil, fmt.Errorf("bytes: got %d arguments, want exactly 1", len(args))
   245  	}
   246  	switch x := args[0].(type) {
   247  	case Bytes:
   248  		return x, nil
   249  	case String:
   250  		// Invalid encodings are replaced by that of U+FFFD.
   251  		return Bytes(utf8Transcode(string(x))), nil
   252  	case Iterable:
   253  		// iterable of numeric byte values
   254  		var buf strings.Builder
   255  		if n := Len(x); n >= 0 {
   256  			// common case: known length
   257  			buf.Grow(n)
   258  		}
   259  		iter := x.Iterate()
   260  		defer iter.Done()
   261  		var elem Value
   262  		var b byte
   263  		for i := 0; iter.Next(&elem); i++ {
   264  			if err := AsInt(elem, &b); err != nil {
   265  				return nil, fmt.Errorf("bytes: at index %d, %s", i, err)
   266  			}
   267  			buf.WriteByte(b)
   268  		}
   269  		return Bytes(buf.String()), nil
   270  
   271  	default:
   272  		// Unlike string(foo), which stringifies it, bytes(foo) is an error.
   273  		return nil, fmt.Errorf("bytes: got %s, want string, bytes, or iterable of ints", x.Type())
   274  	}
   275  }
   276  
   277  // https://github.com/google/starlark-go/blob/master/doc/spec.md#chr
   278  func chr(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   279  	if len(kwargs) > 0 {
   280  		return nil, fmt.Errorf("chr does not accept keyword arguments")
   281  	}
   282  	if len(args) != 1 {
   283  		return nil, fmt.Errorf("chr: got %d arguments, want 1", len(args))
   284  	}
   285  	i, err := AsInt32(args[0])
   286  	if err != nil {
   287  		return nil, fmt.Errorf("chr: %s", err)
   288  	}
   289  	if i < 0 {
   290  		return nil, fmt.Errorf("chr: Unicode code point %d out of range (<0)", i)
   291  	}
   292  	if i > unicode.MaxRune {
   293  		return nil, fmt.Errorf("chr: Unicode code point U+%X out of range (>0x10FFFF)", i)
   294  	}
   295  	return String(string(rune(i))), nil
   296  }
   297  
   298  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict
   299  func dict(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   300  	if len(args) > 1 {
   301  		return nil, fmt.Errorf("dict: got %d arguments, want at most 1", len(args))
   302  	}
   303  	dict := new(Dict)
   304  	if err := updateDict(dict, args, kwargs); err != nil {
   305  		return nil, fmt.Errorf("dict: %v", err)
   306  	}
   307  	return dict, nil
   308  }
   309  
   310  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dir
   311  func dir(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   312  	if len(kwargs) > 0 {
   313  		return nil, fmt.Errorf("dir does not accept keyword arguments")
   314  	}
   315  	if len(args) != 1 {
   316  		return nil, fmt.Errorf("dir: got %d arguments, want 1", len(args))
   317  	}
   318  
   319  	var names []string
   320  	if x, ok := args[0].(HasAttrs); ok {
   321  		names = x.AttrNames()
   322  	}
   323  	sort.Strings(names)
   324  	elems := make([]Value, len(names))
   325  	for i, name := range names {
   326  		elems[i] = String(name)
   327  	}
   328  	return NewList(elems), nil
   329  }
   330  
   331  // https://github.com/google/starlark-go/blob/master/doc/spec.md#enumerate
   332  func enumerate(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   333  	var iterable Iterable
   334  	var start int
   335  	if err := UnpackPositionalArgs("enumerate", args, kwargs, 1, &iterable, &start); err != nil {
   336  		return nil, err
   337  	}
   338  
   339  	iter := iterable.Iterate()
   340  	defer iter.Done()
   341  
   342  	var pairs []Value
   343  	var x Value
   344  
   345  	if n := Len(iterable); n >= 0 {
   346  		// common case: known length
   347  		pairs = make([]Value, 0, n)
   348  		array := make(Tuple, 2*n) // allocate a single backing array
   349  		for i := 0; iter.Next(&x); i++ {
   350  			pair := array[:2:2]
   351  			array = array[2:]
   352  			pair[0] = MakeInt(start + i)
   353  			pair[1] = x
   354  			pairs = append(pairs, pair)
   355  		}
   356  	} else {
   357  		// non-sequence (unknown length)
   358  		for i := 0; iter.Next(&x); i++ {
   359  			pair := Tuple{MakeInt(start + i), x}
   360  			pairs = append(pairs, pair)
   361  		}
   362  	}
   363  
   364  	return NewList(pairs), nil
   365  }
   366  
   367  // https://github.com/google/starlark-go/blob/master/doc/spec.md#fail
   368  func fail(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   369  	sep := " "
   370  	if err := UnpackArgs("fail", nil, kwargs, "sep?", &sep); err != nil {
   371  		return nil, err
   372  	}
   373  	buf := new(strings.Builder)
   374  	buf.WriteString("fail: ")
   375  	for i, v := range args {
   376  		if i > 0 {
   377  			buf.WriteString(sep)
   378  		}
   379  		if s, ok := AsString(v); ok {
   380  			buf.WriteString(s)
   381  		} else {
   382  			writeValue(buf, v, nil)
   383  		}
   384  	}
   385  
   386  	return nil, errors.New(buf.String())
   387  }
   388  
   389  func float(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   390  	if len(kwargs) > 0 {
   391  		return nil, fmt.Errorf("float does not accept keyword arguments")
   392  	}
   393  	if len(args) == 0 {
   394  		return Float(0.0), nil
   395  	}
   396  	if len(args) != 1 {
   397  		return nil, fmt.Errorf("float got %d arguments, wants 1", len(args))
   398  	}
   399  	switch x := args[0].(type) {
   400  	case Bool:
   401  		if x {
   402  			return Float(1.0), nil
   403  		} else {
   404  			return Float(0.0), nil
   405  		}
   406  	case Int:
   407  		return x.finiteFloat()
   408  	case Float:
   409  		return x, nil
   410  	case String:
   411  		if x == "" {
   412  			return nil, fmt.Errorf("float: empty string")
   413  		}
   414  		// +/- NaN or Inf or Infinity (case insensitive)?
   415  		s := string(x)
   416  		switch x[len(x)-1] {
   417  		case 'y', 'Y':
   418  			if strings.EqualFold(s, "infinity") || strings.EqualFold(s, "+infinity") {
   419  				return inf, nil
   420  			} else if strings.EqualFold(s, "-infinity") {
   421  				return neginf, nil
   422  			}
   423  		case 'f', 'F':
   424  			if strings.EqualFold(s, "inf") || strings.EqualFold(s, "+inf") {
   425  				return inf, nil
   426  			} else if strings.EqualFold(s, "-inf") {
   427  				return neginf, nil
   428  			}
   429  		case 'n', 'N':
   430  			if strings.EqualFold(s, "nan") || strings.EqualFold(s, "+nan") || strings.EqualFold(s, "-nan") {
   431  				return nan, nil
   432  			}
   433  		}
   434  		f, err := strconv.ParseFloat(s, 64)
   435  		if math.IsInf(f, 0) {
   436  			return nil, fmt.Errorf("floating-point number too large")
   437  		}
   438  		if err != nil {
   439  			return nil, fmt.Errorf("invalid float literal: %s", s)
   440  		}
   441  		return Float(f), nil
   442  	default:
   443  		return nil, fmt.Errorf("float got %s, want number or string", x.Type())
   444  	}
   445  }
   446  
   447  var (
   448  	inf    = Float(math.Inf(+1))
   449  	neginf = Float(math.Inf(-1))
   450  	nan    = Float(math.NaN())
   451  )
   452  
   453  // https://github.com/google/starlark-go/blob/master/doc/spec.md#getattr
   454  func getattr(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   455  	var object, dflt Value
   456  	var name string
   457  	if err := UnpackPositionalArgs("getattr", args, kwargs, 2, &object, &name, &dflt); err != nil {
   458  		return nil, err
   459  	}
   460  	if object, ok := object.(HasAttrs); ok {
   461  		v, err := object.Attr(name)
   462  		if err != nil {
   463  			// An error could mean the field doesn't exist,
   464  			// or it exists but could not be computed.
   465  			if dflt != nil {
   466  				return dflt, nil
   467  			}
   468  			return nil, nameErr(b, err)
   469  		}
   470  		if v != nil {
   471  			return v, nil
   472  		}
   473  		// (nil, nil) => no such field
   474  	}
   475  	if dflt != nil {
   476  		return dflt, nil
   477  	}
   478  	return nil, fmt.Errorf("getattr: %s has no .%s field or method", object.Type(), name)
   479  }
   480  
   481  // https://github.com/google/starlark-go/blob/master/doc/spec.md#hasattr
   482  func hasattr(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   483  	var object Value
   484  	var name string
   485  	if err := UnpackPositionalArgs("hasattr", args, kwargs, 2, &object, &name); err != nil {
   486  		return nil, err
   487  	}
   488  	if object, ok := object.(HasAttrs); ok {
   489  		v, err := object.Attr(name)
   490  		if err == nil {
   491  			return Bool(v != nil), nil
   492  		}
   493  
   494  		// An error does not conclusively indicate presence or
   495  		// absence of a field: it could occur while computing
   496  		// the value of a present attribute, or it could be a
   497  		// "no such attribute" error with details.
   498  		for _, x := range object.AttrNames() {
   499  			if x == name {
   500  				return True, nil
   501  			}
   502  		}
   503  	}
   504  	return False, nil
   505  }
   506  
   507  // https://github.com/google/starlark-go/blob/master/doc/spec.md#hash
   508  func hash(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   509  	var x Value
   510  	if err := UnpackPositionalArgs("hash", args, kwargs, 1, &x); err != nil {
   511  		return nil, err
   512  	}
   513  
   514  	var h int64
   515  	switch x := x.(type) {
   516  	case String:
   517  		// The Starlark spec requires that the hash function be
   518  		// deterministic across all runs, motivated by the need
   519  		// for reproducibility of builds. Thus we cannot call
   520  		// String.Hash, which uses the fastest implementation
   521  		// available, because as varies across process restarts,
   522  		// and may evolve with the implementation.
   523  		h = int64(javaStringHash(string(x)))
   524  	case Bytes:
   525  		h = int64(softHashString(string(x))) // FNV32
   526  	default:
   527  		return nil, fmt.Errorf("hash: got %s, want string or bytes", x.Type())
   528  	}
   529  	return MakeInt64(h), nil
   530  }
   531  
   532  // javaStringHash returns the same hash as would be produced by
   533  // java.lang.String.hashCode. This requires transcoding the string to
   534  // UTF-16; transcoding may introduce Unicode replacement characters
   535  // U+FFFD if s does not contain valid UTF-8.
   536  func javaStringHash(s string) (h int32) {
   537  	for _, r := range s {
   538  		if utf16.IsSurrogate(r) {
   539  			c1, c2 := utf16.EncodeRune(r)
   540  			h = 31*h + c1
   541  			h = 31*h + c2
   542  		} else {
   543  			h = 31*h + r // r may be U+FFFD
   544  		}
   545  	}
   546  	return h
   547  }
   548  
   549  // https://github.com/google/starlark-go/blob/master/doc/spec.md#int
   550  func int_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   551  	var x Value = zero
   552  	var base Value
   553  	if err := UnpackArgs("int", args, kwargs, "x", &x, "base?", &base); err != nil {
   554  		return nil, err
   555  	}
   556  
   557  	if s, ok := AsString(x); ok {
   558  		b := 10
   559  		if base != nil {
   560  			var err error
   561  			b, err = AsInt32(base)
   562  			if err != nil {
   563  				return nil, fmt.Errorf("int: for base, got %s, want int", base.Type())
   564  			}
   565  			if b != 0 && (b < 2 || b > 36) {
   566  				return nil, fmt.Errorf("int: base must be an integer >= 2 && <= 36")
   567  			}
   568  		}
   569  		res := parseInt(s, b)
   570  		if res == nil {
   571  			return nil, fmt.Errorf("int: invalid literal with base %d: %s", b, s)
   572  		}
   573  		return res, nil
   574  	}
   575  
   576  	if base != nil {
   577  		return nil, fmt.Errorf("int: can't convert non-string with explicit base")
   578  	}
   579  
   580  	if b, ok := x.(Bool); ok {
   581  		if b {
   582  			return one, nil
   583  		} else {
   584  			return zero, nil
   585  		}
   586  	}
   587  
   588  	i, err := NumberToInt(x)
   589  	if err != nil {
   590  		return nil, fmt.Errorf("int: %s", err)
   591  	}
   592  	return i, nil
   593  }
   594  
   595  // parseInt defines the behavior of int(string, base=int). It returns nil on error.
   596  func parseInt(s string, base int) Value {
   597  	// remove sign
   598  	var neg bool
   599  	if s != "" {
   600  		if s[0] == '+' {
   601  			s = s[1:]
   602  		} else if s[0] == '-' {
   603  			neg = true
   604  			s = s[1:]
   605  		}
   606  	}
   607  
   608  	// remove optional base prefix
   609  	baseprefix := 0
   610  	if len(s) > 1 && s[0] == '0' {
   611  		if len(s) > 2 {
   612  			switch s[1] {
   613  			case 'o', 'O':
   614  				baseprefix = 8
   615  			case 'x', 'X':
   616  				baseprefix = 16
   617  			case 'b', 'B':
   618  				baseprefix = 2
   619  			}
   620  		}
   621  		if baseprefix != 0 {
   622  			// Remove the base prefix if it matches
   623  			// the explicit base, or if base=0.
   624  			if base == 0 || baseprefix == base {
   625  				base = baseprefix
   626  				s = s[2:]
   627  			}
   628  		} else {
   629  			// For automatic base detection,
   630  			// a string starting with zero
   631  			// must be all zeros.
   632  			// Thus we reject int("0755", 0).
   633  			if base == 0 {
   634  				for i := 1; i < len(s); i++ {
   635  					if s[i] != '0' {
   636  						return nil
   637  					}
   638  				}
   639  				return zero
   640  			}
   641  		}
   642  	}
   643  	if base == 0 {
   644  		base = 10
   645  	}
   646  
   647  	// we explicitly handled sign above.
   648  	// if a sign remains, it is invalid.
   649  	if s != "" && (s[0] == '-' || s[0] == '+') {
   650  		return nil
   651  	}
   652  
   653  	// s has no sign or base prefix.
   654  	if i, ok := new(big.Int).SetString(s, base); ok {
   655  		res := MakeBigInt(i)
   656  		if neg {
   657  			res = zero.Sub(res)
   658  		}
   659  		return res
   660  	}
   661  
   662  	return nil
   663  }
   664  
   665  // https://github.com/google/starlark-go/blob/master/doc/spec.md#len
   666  func len_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   667  	var x Value
   668  	if err := UnpackPositionalArgs("len", args, kwargs, 1, &x); err != nil {
   669  		return nil, err
   670  	}
   671  	len := Len(x)
   672  	if len < 0 {
   673  		return nil, fmt.Errorf("len: value of type %s has no len", x.Type())
   674  	}
   675  	return MakeInt(len), nil
   676  }
   677  
   678  // https://github.com/google/starlark-go/blob/master/doc/spec.md#list
   679  func list(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   680  	var iterable Iterable
   681  	if err := UnpackPositionalArgs("list", args, kwargs, 0, &iterable); err != nil {
   682  		return nil, err
   683  	}
   684  	var elems []Value
   685  	if iterable != nil {
   686  		iter := iterable.Iterate()
   687  		defer iter.Done()
   688  		if n := Len(iterable); n > 0 {
   689  			elems = make([]Value, 0, n) // preallocate if length known
   690  		}
   691  		var x Value
   692  		for iter.Next(&x) {
   693  			elems = append(elems, x)
   694  		}
   695  	}
   696  	return NewList(elems), nil
   697  }
   698  
   699  // https://github.com/google/starlark-go/blob/master/doc/spec.md#min
   700  func minmax(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   701  	if len(args) == 0 {
   702  		return nil, fmt.Errorf("%s requires at least one positional argument", b.Name())
   703  	}
   704  	var keyFunc Callable
   705  	if err := UnpackArgs(b.Name(), nil, kwargs, "key?", &keyFunc); err != nil {
   706  		return nil, err
   707  	}
   708  	var op syntax.Token
   709  	if b.Name() == "max" {
   710  		op = syntax.GT
   711  	} else {
   712  		op = syntax.LT
   713  	}
   714  	var iterable Value
   715  	if len(args) == 1 {
   716  		iterable = args[0]
   717  	} else {
   718  		iterable = args
   719  	}
   720  	iter := Iterate(iterable)
   721  	if iter == nil {
   722  		return nil, fmt.Errorf("%s: %s value is not iterable", b.Name(), iterable.Type())
   723  	}
   724  	defer iter.Done()
   725  	var extremum Value
   726  	if !iter.Next(&extremum) {
   727  		return nil, nameErr(b, "argument is an empty sequence")
   728  	}
   729  
   730  	var extremeKey Value
   731  	var keyargs Tuple
   732  	if keyFunc == nil {
   733  		extremeKey = extremum
   734  	} else {
   735  		keyargs = Tuple{extremum}
   736  		res, err := Call(thread, keyFunc, keyargs, nil)
   737  		if err != nil {
   738  			return nil, err // to preserve backtrace, don't modify error
   739  		}
   740  		extremeKey = res
   741  	}
   742  
   743  	var x Value
   744  	for iter.Next(&x) {
   745  		var key Value
   746  		if keyFunc == nil {
   747  			key = x
   748  		} else {
   749  			keyargs[0] = x
   750  			res, err := Call(thread, keyFunc, keyargs, nil)
   751  			if err != nil {
   752  				return nil, err // to preserve backtrace, don't modify error
   753  			}
   754  			key = res
   755  		}
   756  
   757  		if ok, err := Compare(op, key, extremeKey); err != nil {
   758  			return nil, nameErr(b, err)
   759  		} else if ok {
   760  			extremum = x
   761  			extremeKey = key
   762  		}
   763  	}
   764  	return extremum, nil
   765  }
   766  
   767  // https://github.com/google/starlark-go/blob/master/doc/spec.md#ord
   768  func ord(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   769  	if len(kwargs) > 0 {
   770  		return nil, fmt.Errorf("ord does not accept keyword arguments")
   771  	}
   772  	if len(args) != 1 {
   773  		return nil, fmt.Errorf("ord: got %d arguments, want 1", len(args))
   774  	}
   775  	switch x := args[0].(type) {
   776  	case String:
   777  		// ord(string) returns int value of sole rune.
   778  		s := string(x)
   779  		r, sz := utf8.DecodeRuneInString(s)
   780  		if sz == 0 || sz != len(s) {
   781  			n := utf8.RuneCountInString(s)
   782  			return nil, fmt.Errorf("ord: string encodes %d Unicode code points, want 1", n)
   783  		}
   784  		return MakeInt(int(r)), nil
   785  
   786  	case Bytes:
   787  		// ord(bytes) returns int value of sole byte.
   788  		if len(x) != 1 {
   789  			return nil, fmt.Errorf("ord: bytes has length %d, want 1", len(x))
   790  		}
   791  		return MakeInt(int(x[0])), nil
   792  	default:
   793  		return nil, fmt.Errorf("ord: got %s, want string or bytes", x.Type())
   794  	}
   795  }
   796  
   797  // https://github.com/google/starlark-go/blob/master/doc/spec.md#print
   798  func print(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   799  	sep := " "
   800  	if err := UnpackArgs("print", nil, kwargs, "sep?", &sep); err != nil {
   801  		return nil, err
   802  	}
   803  	buf := new(strings.Builder)
   804  	for i, v := range args {
   805  		if i > 0 {
   806  			buf.WriteString(sep)
   807  		}
   808  		if s, ok := AsString(v); ok {
   809  			buf.WriteString(s)
   810  		} else if b, ok := v.(Bytes); ok {
   811  			buf.WriteString(string(b))
   812  		} else {
   813  			writeValue(buf, v, nil)
   814  		}
   815  	}
   816  
   817  	s := buf.String()
   818  	if thread.Print != nil {
   819  		thread.Print(thread, s)
   820  	} else {
   821  		fmt.Fprintln(os.Stderr, s)
   822  	}
   823  	return None, nil
   824  }
   825  
   826  // https://github.com/google/starlark-go/blob/master/doc/spec.md#range
   827  func range_(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   828  	var start, stop, step int
   829  	step = 1
   830  	if err := UnpackPositionalArgs("range", args, kwargs, 1, &start, &stop, &step); err != nil {
   831  		return nil, err
   832  	}
   833  
   834  	if len(args) == 1 {
   835  		// range(stop)
   836  		start, stop = 0, start
   837  	}
   838  	if step == 0 {
   839  		// we were given range(start, stop, 0)
   840  		return nil, nameErr(b, "step argument must not be zero")
   841  	}
   842  
   843  	return rangeValue{start: start, stop: stop, step: step, len: rangeLen(start, stop, step)}, nil
   844  }
   845  
   846  // A rangeValue is a comparable, immutable, indexable sequence of integers
   847  // defined by the three parameters to a range(...) call.
   848  // Invariant: step != 0.
   849  type rangeValue struct{ start, stop, step, len int }
   850  
   851  var (
   852  	_ Indexable  = rangeValue{}
   853  	_ Sequence   = rangeValue{}
   854  	_ Comparable = rangeValue{}
   855  	_ Sliceable  = rangeValue{}
   856  )
   857  
   858  func (r rangeValue) Len() int          { return r.len }
   859  func (r rangeValue) Index(i int) Value { return MakeInt(r.start + i*r.step) }
   860  func (r rangeValue) Iterate() Iterator { return &rangeIterator{r, 0} }
   861  
   862  // rangeLen calculates the length of a range with the provided start, stop, and step.
   863  // caller must ensure that step is non-zero.
   864  func rangeLen(start, stop, step int) int {
   865  	switch {
   866  	case step > 0:
   867  		if stop > start {
   868  			return (stop-1-start)/step + 1
   869  		}
   870  	case step < 0:
   871  		if start > stop {
   872  			return (start-1-stop)/-step + 1
   873  		}
   874  	default:
   875  		panic("rangeLen: zero step")
   876  	}
   877  	return 0
   878  }
   879  
   880  func (r rangeValue) Slice(start, end, step int) Value {
   881  	newStart := r.start + r.step*start
   882  	newStop := r.start + r.step*end
   883  	newStep := r.step * step
   884  	return rangeValue{
   885  		start: newStart,
   886  		stop:  newStop,
   887  		step:  newStep,
   888  		len:   rangeLen(newStart, newStop, newStep),
   889  	}
   890  }
   891  
   892  func (r rangeValue) Freeze() {} // immutable
   893  func (r rangeValue) String() string {
   894  	if r.step != 1 {
   895  		return fmt.Sprintf("range(%d, %d, %d)", r.start, r.stop, r.step)
   896  	} else if r.start != 0 {
   897  		return fmt.Sprintf("range(%d, %d)", r.start, r.stop)
   898  	} else {
   899  		return fmt.Sprintf("range(%d)", r.stop)
   900  	}
   901  }
   902  func (r rangeValue) Type() string          { return "range" }
   903  func (r rangeValue) Truth() Bool           { return r.len > 0 }
   904  func (r rangeValue) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: range") }
   905  
   906  func (x rangeValue) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
   907  	y := y_.(rangeValue)
   908  	switch op {
   909  	case syntax.EQL:
   910  		return rangeEqual(x, y), nil
   911  	case syntax.NEQ:
   912  		return !rangeEqual(x, y), nil
   913  	default:
   914  		return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
   915  	}
   916  }
   917  
   918  func rangeEqual(x, y rangeValue) bool {
   919  	// Two ranges compare equal if they denote the same sequence.
   920  	if x.len != y.len {
   921  		return false // sequences differ in length
   922  	}
   923  	if x.len == 0 {
   924  		return true // both sequences are empty
   925  	}
   926  	if x.start != y.start {
   927  		return false // first element differs
   928  	}
   929  	return x.len == 1 || x.step == y.step
   930  }
   931  
   932  func (r rangeValue) contains(x Int) bool {
   933  	x32, err := AsInt32(x)
   934  	if err != nil {
   935  		return false // out of range
   936  	}
   937  	delta := x32 - r.start
   938  	quo, rem := delta/r.step, delta%r.step
   939  	return rem == 0 && 0 <= quo && quo < r.len
   940  }
   941  
   942  type rangeIterator struct {
   943  	r rangeValue
   944  	i int
   945  }
   946  
   947  func (it *rangeIterator) Next(p *Value) bool {
   948  	if it.i < it.r.len {
   949  		*p = it.r.Index(it.i)
   950  		it.i++
   951  		return true
   952  	}
   953  	return false
   954  }
   955  func (*rangeIterator) Done() {}
   956  
   957  // https://github.com/google/starlark-go/blob/master/doc/spec.md#repr
   958  func repr(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   959  	var x Value
   960  	if err := UnpackPositionalArgs("repr", args, kwargs, 1, &x); err != nil {
   961  		return nil, err
   962  	}
   963  	return String(x.String()), nil
   964  }
   965  
   966  // https://github.com/google/starlark-go/blob/master/doc/spec.md#reversed
   967  func reversed(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   968  	var iterable Iterable
   969  	if err := UnpackPositionalArgs("reversed", args, kwargs, 1, &iterable); err != nil {
   970  		return nil, err
   971  	}
   972  	iter := iterable.Iterate()
   973  	defer iter.Done()
   974  	var elems []Value
   975  	if n := Len(args[0]); n >= 0 {
   976  		elems = make([]Value, 0, n) // preallocate if length known
   977  	}
   978  	var x Value
   979  	for iter.Next(&x) {
   980  		elems = append(elems, x)
   981  	}
   982  	n := len(elems)
   983  	for i := 0; i < n>>1; i++ {
   984  		elems[i], elems[n-1-i] = elems[n-1-i], elems[i]
   985  	}
   986  	return NewList(elems), nil
   987  }
   988  
   989  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set
   990  func set(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
   991  	var iterable Iterable
   992  	if err := UnpackPositionalArgs("set", args, kwargs, 0, &iterable); err != nil {
   993  		return nil, err
   994  	}
   995  	set := new(Set)
   996  	if iterable != nil {
   997  		iter := iterable.Iterate()
   998  		defer iter.Done()
   999  		var x Value
  1000  		for iter.Next(&x) {
  1001  			if err := set.Insert(x); err != nil {
  1002  				return nil, nameErr(b, err)
  1003  			}
  1004  		}
  1005  	}
  1006  	return set, nil
  1007  }
  1008  
  1009  // https://github.com/google/starlark-go/blob/master/doc/spec.md#sorted
  1010  func sorted(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1011  	// Oddly, Python's sorted permits all arguments to be positional, thus so do we.
  1012  	var iterable Iterable
  1013  	var key Callable
  1014  	var reverse bool
  1015  	if err := UnpackArgs("sorted", args, kwargs,
  1016  		"iterable", &iterable,
  1017  		"key?", &key,
  1018  		"reverse?", &reverse,
  1019  	); err != nil {
  1020  		return nil, err
  1021  	}
  1022  
  1023  	iter := iterable.Iterate()
  1024  	defer iter.Done()
  1025  	var values []Value
  1026  	if n := Len(iterable); n > 0 {
  1027  		values = make(Tuple, 0, n) // preallocate if length is known
  1028  	}
  1029  	var x Value
  1030  	for iter.Next(&x) {
  1031  		values = append(values, x)
  1032  	}
  1033  
  1034  	// Derive keys from values by applying key function.
  1035  	var keys []Value
  1036  	if key != nil {
  1037  		keys = make([]Value, len(values))
  1038  		for i, v := range values {
  1039  			k, err := Call(thread, key, Tuple{v}, nil)
  1040  			if err != nil {
  1041  				return nil, err // to preserve backtrace, don't modify error
  1042  			}
  1043  			keys[i] = k
  1044  		}
  1045  	}
  1046  
  1047  	slice := &sortSlice{keys: keys, values: values}
  1048  	if reverse {
  1049  		sort.Stable(sort.Reverse(slice))
  1050  	} else {
  1051  		sort.Stable(slice)
  1052  	}
  1053  	return NewList(slice.values), slice.err
  1054  }
  1055  
  1056  type sortSlice struct {
  1057  	keys   []Value // nil => values[i] is key
  1058  	values []Value
  1059  	err    error
  1060  }
  1061  
  1062  func (s *sortSlice) Len() int { return len(s.values) }
  1063  func (s *sortSlice) Less(i, j int) bool {
  1064  	keys := s.keys
  1065  	if s.keys == nil {
  1066  		keys = s.values
  1067  	}
  1068  	ok, err := Compare(syntax.LT, keys[i], keys[j])
  1069  	if err != nil {
  1070  		s.err = err
  1071  	}
  1072  	return ok
  1073  }
  1074  func (s *sortSlice) Swap(i, j int) {
  1075  	if s.keys != nil {
  1076  		s.keys[i], s.keys[j] = s.keys[j], s.keys[i]
  1077  	}
  1078  	s.values[i], s.values[j] = s.values[j], s.values[i]
  1079  }
  1080  
  1081  // https://github.com/google/starlark-go/blob/master/doc/spec.md#str
  1082  func str(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1083  	if len(kwargs) > 0 {
  1084  		return nil, fmt.Errorf("str does not accept keyword arguments")
  1085  	}
  1086  	if len(args) != 1 {
  1087  		return nil, fmt.Errorf("str: got %d arguments, want exactly 1", len(args))
  1088  	}
  1089  	switch x := args[0].(type) {
  1090  	case String:
  1091  		return x, nil
  1092  	case Bytes:
  1093  		// Invalid encodings are replaced by that of U+FFFD.
  1094  		return String(utf8Transcode(string(x))), nil
  1095  	default:
  1096  		return String(x.String()), nil
  1097  	}
  1098  }
  1099  
  1100  // utf8Transcode returns the UTF-8-to-UTF-8 transcoding of s.
  1101  // The effect is that each code unit that is part of an
  1102  // invalid sequence is replaced by U+FFFD.
  1103  func utf8Transcode(s string) string {
  1104  	if utf8.ValidString(s) {
  1105  		return s
  1106  	}
  1107  	var out strings.Builder
  1108  	for _, r := range s {
  1109  		out.WriteRune(r)
  1110  	}
  1111  	return out.String()
  1112  }
  1113  
  1114  // https://github.com/google/starlark-go/blob/master/doc/spec.md#tuple
  1115  func tuple(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1116  	var iterable Iterable
  1117  	if err := UnpackPositionalArgs("tuple", args, kwargs, 0, &iterable); err != nil {
  1118  		return nil, err
  1119  	}
  1120  	if len(args) == 0 {
  1121  		return Tuple(nil), nil
  1122  	}
  1123  	iter := iterable.Iterate()
  1124  	defer iter.Done()
  1125  	var elems Tuple
  1126  	if n := Len(iterable); n > 0 {
  1127  		elems = make(Tuple, 0, n) // preallocate if length is known
  1128  	}
  1129  	var x Value
  1130  	for iter.Next(&x) {
  1131  		elems = append(elems, x)
  1132  	}
  1133  	return elems, nil
  1134  }
  1135  
  1136  // https://github.com/google/starlark-go/blob/master/doc/spec.md#type
  1137  func type_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1138  	if len(kwargs) > 0 {
  1139  		return nil, fmt.Errorf("type does not accept keyword arguments")
  1140  	}
  1141  	if len(args) != 1 {
  1142  		return nil, fmt.Errorf("type: got %d arguments, want exactly 1", len(args))
  1143  	}
  1144  	return String(args[0].Type()), nil
  1145  }
  1146  
  1147  // https://github.com/google/starlark-go/blob/master/doc/spec.md#zip
  1148  func zip(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1149  	if len(kwargs) > 0 {
  1150  		return nil, fmt.Errorf("zip does not accept keyword arguments")
  1151  	}
  1152  	rows, cols := 0, len(args)
  1153  	iters := make([]Iterator, cols)
  1154  	defer func() {
  1155  		for _, iter := range iters {
  1156  			if iter != nil {
  1157  				iter.Done()
  1158  			}
  1159  		}
  1160  	}()
  1161  	for i, seq := range args {
  1162  		it := Iterate(seq)
  1163  		if it == nil {
  1164  			return nil, fmt.Errorf("zip: argument #%d is not iterable: %s", i+1, seq.Type())
  1165  		}
  1166  		iters[i] = it
  1167  		n := Len(seq)
  1168  		if i == 0 || n < rows {
  1169  			rows = n // possibly -1
  1170  		}
  1171  	}
  1172  	var result []Value
  1173  	if rows >= 0 {
  1174  		// length known
  1175  		result = make([]Value, rows)
  1176  		array := make(Tuple, cols*rows) // allocate a single backing array
  1177  		for i := 0; i < rows; i++ {
  1178  			tuple := array[:cols:cols]
  1179  			array = array[cols:]
  1180  			for j, iter := range iters {
  1181  				iter.Next(&tuple[j])
  1182  			}
  1183  			result[i] = tuple
  1184  		}
  1185  	} else {
  1186  		// length not known
  1187  	outer:
  1188  		for {
  1189  			tuple := make(Tuple, cols)
  1190  			for i, iter := range iters {
  1191  				if !iter.Next(&tuple[i]) {
  1192  					break outer
  1193  				}
  1194  			}
  1195  			result = append(result, tuple)
  1196  		}
  1197  	}
  1198  	return NewList(result), nil
  1199  }
  1200  
  1201  // ---- methods of built-in types ---
  1202  
  1203  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·get
  1204  func dict_get(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1205  	var key, dflt Value
  1206  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &key, &dflt); err != nil {
  1207  		return nil, err
  1208  	}
  1209  	if v, ok, err := b.Receiver().(*Dict).Get(key); err != nil {
  1210  		return nil, nameErr(b, err)
  1211  	} else if ok {
  1212  		return v, nil
  1213  	} else if dflt != nil {
  1214  		return dflt, nil
  1215  	}
  1216  	return None, nil
  1217  }
  1218  
  1219  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·clear
  1220  func dict_clear(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1221  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1222  		return nil, err
  1223  	}
  1224  	return None, b.Receiver().(*Dict).Clear()
  1225  }
  1226  
  1227  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·items
  1228  func dict_items(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1229  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1230  		return nil, err
  1231  	}
  1232  	items := b.Receiver().(*Dict).Items()
  1233  	res := make([]Value, len(items))
  1234  	for i, item := range items {
  1235  		res[i] = item // convert [2]Value to Value
  1236  	}
  1237  	return NewList(res), nil
  1238  }
  1239  
  1240  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·keys
  1241  func dict_keys(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1242  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1243  		return nil, err
  1244  	}
  1245  	return NewList(b.Receiver().(*Dict).Keys()), nil
  1246  }
  1247  
  1248  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·pop
  1249  func dict_pop(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1250  	var k, d Value
  1251  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &k, &d); err != nil {
  1252  		return nil, err
  1253  	}
  1254  	if v, found, err := b.Receiver().(*Dict).Delete(k); err != nil {
  1255  		return nil, nameErr(b, err) // dict is frozen or key is unhashable
  1256  	} else if found {
  1257  		return v, nil
  1258  	} else if d != nil {
  1259  		return d, nil
  1260  	}
  1261  	return nil, nameErr(b, "missing key")
  1262  }
  1263  
  1264  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·popitem
  1265  func dict_popitem(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1266  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1267  		return nil, err
  1268  	}
  1269  	recv := b.Receiver().(*Dict)
  1270  	k, ok := recv.ht.first()
  1271  	if !ok {
  1272  		return nil, nameErr(b, "empty dict")
  1273  	}
  1274  	v, _, err := recv.Delete(k)
  1275  	if err != nil {
  1276  		return nil, nameErr(b, err) // dict is frozen
  1277  	}
  1278  	return Tuple{k, v}, nil
  1279  }
  1280  
  1281  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·setdefault
  1282  func dict_setdefault(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1283  	var key, dflt Value = nil, None
  1284  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &key, &dflt); err != nil {
  1285  		return nil, err
  1286  	}
  1287  	dict := b.Receiver().(*Dict)
  1288  	if v, ok, err := dict.Get(key); err != nil {
  1289  		return nil, nameErr(b, err)
  1290  	} else if ok {
  1291  		return v, nil
  1292  	} else if err := dict.SetKey(key, dflt); err != nil {
  1293  		return nil, nameErr(b, err)
  1294  	} else {
  1295  		return dflt, nil
  1296  	}
  1297  }
  1298  
  1299  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·update
  1300  func dict_update(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1301  	if len(args) > 1 {
  1302  		return nil, fmt.Errorf("update: got %d arguments, want at most 1", len(args))
  1303  	}
  1304  	if err := updateDict(b.Receiver().(*Dict), args, kwargs); err != nil {
  1305  		return nil, fmt.Errorf("update: %v", err)
  1306  	}
  1307  	return None, nil
  1308  }
  1309  
  1310  // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·update
  1311  func dict_values(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1312  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1313  		return nil, err
  1314  	}
  1315  	items := b.Receiver().(*Dict).Items()
  1316  	res := make([]Value, len(items))
  1317  	for i, item := range items {
  1318  		res[i] = item[1]
  1319  	}
  1320  	return NewList(res), nil
  1321  }
  1322  
  1323  // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·append
  1324  func list_append(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1325  	var object Value
  1326  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &object); err != nil {
  1327  		return nil, err
  1328  	}
  1329  	recv := b.Receiver().(*List)
  1330  	if err := recv.checkMutable("append to"); err != nil {
  1331  		return nil, nameErr(b, err)
  1332  	}
  1333  	recv.elems = append(recv.elems, object)
  1334  	return None, nil
  1335  }
  1336  
  1337  // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·clear
  1338  func list_clear(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1339  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1340  		return nil, err
  1341  	}
  1342  	if err := b.Receiver().(*List).Clear(); err != nil {
  1343  		return nil, nameErr(b, err)
  1344  	}
  1345  	return None, nil
  1346  }
  1347  
  1348  // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·extend
  1349  func list_extend(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1350  	recv := b.Receiver().(*List)
  1351  	var iterable Iterable
  1352  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &iterable); err != nil {
  1353  		return nil, err
  1354  	}
  1355  	if err := recv.checkMutable("extend"); err != nil {
  1356  		return nil, nameErr(b, err)
  1357  	}
  1358  	listExtend(recv, iterable)
  1359  	return None, nil
  1360  }
  1361  
  1362  // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·index
  1363  func list_index(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1364  	var value, start_, end_ Value
  1365  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &value, &start_, &end_); err != nil {
  1366  		return nil, err
  1367  	}
  1368  
  1369  	recv := b.Receiver().(*List)
  1370  	start, end, err := indices(start_, end_, recv.Len())
  1371  	if err != nil {
  1372  		return nil, nameErr(b, err)
  1373  	}
  1374  
  1375  	for i := start; i < end; i++ {
  1376  		if eq, err := Equal(recv.elems[i], value); err != nil {
  1377  			return nil, nameErr(b, err)
  1378  		} else if eq {
  1379  			return MakeInt(i), nil
  1380  		}
  1381  	}
  1382  	return nil, nameErr(b, "value not in list")
  1383  }
  1384  
  1385  // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·insert
  1386  func list_insert(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1387  	recv := b.Receiver().(*List)
  1388  	var index int
  1389  	var object Value
  1390  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 2, &index, &object); err != nil {
  1391  		return nil, err
  1392  	}
  1393  	if err := recv.checkMutable("insert into"); err != nil {
  1394  		return nil, nameErr(b, err)
  1395  	}
  1396  
  1397  	if index < 0 {
  1398  		index += recv.Len()
  1399  	}
  1400  
  1401  	if index >= recv.Len() {
  1402  		// end
  1403  		recv.elems = append(recv.elems, object)
  1404  	} else {
  1405  		if index < 0 {
  1406  			index = 0 // start
  1407  		}
  1408  		recv.elems = append(recv.elems, nil)
  1409  		copy(recv.elems[index+1:], recv.elems[index:]) // slide up one
  1410  		recv.elems[index] = object
  1411  	}
  1412  	return None, nil
  1413  }
  1414  
  1415  // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·remove
  1416  func list_remove(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1417  	recv := b.Receiver().(*List)
  1418  	var value Value
  1419  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &value); err != nil {
  1420  		return nil, err
  1421  	}
  1422  	if err := recv.checkMutable("remove from"); err != nil {
  1423  		return nil, nameErr(b, err)
  1424  	}
  1425  	for i, elem := range recv.elems {
  1426  		if eq, err := Equal(elem, value); err != nil {
  1427  			return nil, fmt.Errorf("remove: %v", err)
  1428  		} else if eq {
  1429  			recv.elems = append(recv.elems[:i], recv.elems[i+1:]...)
  1430  			return None, nil
  1431  		}
  1432  	}
  1433  	return nil, fmt.Errorf("remove: element not found")
  1434  }
  1435  
  1436  // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·pop
  1437  func list_pop(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1438  	recv := b.Receiver()
  1439  	list := recv.(*List)
  1440  	n := list.Len()
  1441  	i := n - 1
  1442  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &i); err != nil {
  1443  		return nil, err
  1444  	}
  1445  	origI := i
  1446  	if i < 0 {
  1447  		i += n
  1448  	}
  1449  	if i < 0 || i >= n {
  1450  		return nil, nameErr(b, outOfRange(origI, n, list))
  1451  	}
  1452  	if err := list.checkMutable("pop from"); err != nil {
  1453  		return nil, nameErr(b, err)
  1454  	}
  1455  	res := list.elems[i]
  1456  	list.elems = append(list.elems[:i], list.elems[i+1:]...)
  1457  	return res, nil
  1458  }
  1459  
  1460  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·capitalize
  1461  func string_capitalize(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1462  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1463  		return nil, err
  1464  	}
  1465  	s := string(b.Receiver().(String))
  1466  	res := new(strings.Builder)
  1467  	res.Grow(len(s))
  1468  	for i, r := range s {
  1469  		if i == 0 {
  1470  			r = unicode.ToTitle(r)
  1471  		} else {
  1472  			r = unicode.ToLower(r)
  1473  		}
  1474  		res.WriteRune(r)
  1475  	}
  1476  	return String(res.String()), nil
  1477  }
  1478  
  1479  // string_iterable returns an unspecified iterable value whose iterator yields:
  1480  // - elems: successive 1-byte substrings
  1481  // - codepoints: successive substrings that encode a single Unicode code point.
  1482  // - elem_ords: numeric values of successive bytes
  1483  // - codepoint_ords: numeric values of successive Unicode code points
  1484  func string_iterable(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1485  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1486  		return nil, err
  1487  	}
  1488  	s := b.Receiver().(String)
  1489  	ords := b.Name()[len(b.Name())-2] == 'd'
  1490  	codepoints := b.Name()[0] == 'c'
  1491  	if codepoints {
  1492  		return stringCodepoints{s, ords}, nil
  1493  	} else {
  1494  		return stringElems{s, ords}, nil
  1495  	}
  1496  }
  1497  
  1498  // bytes_elems returns an unspecified iterable value whose
  1499  // iterator yields the int values of successive elements.
  1500  func bytes_elems(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1501  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1502  		return nil, err
  1503  	}
  1504  	return bytesIterable{b.Receiver().(Bytes)}, nil
  1505  }
  1506  
  1507  // A bytesIterable is an iterable returned by bytes.elems(),
  1508  // whose iterator yields a sequence of numeric bytes values.
  1509  type bytesIterable struct{ bytes Bytes }
  1510  
  1511  var _ Iterable = (*bytesIterable)(nil)
  1512  
  1513  func (bi bytesIterable) String() string        { return bi.bytes.String() + ".elems()" }
  1514  func (bi bytesIterable) Type() string          { return "bytes.elems" }
  1515  func (bi bytesIterable) Freeze()               {} // immutable
  1516  func (bi bytesIterable) Truth() Bool           { return True }
  1517  func (bi bytesIterable) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", bi.Type()) }
  1518  func (bi bytesIterable) Iterate() Iterator     { return &bytesIterator{bi.bytes} }
  1519  
  1520  type bytesIterator struct{ bytes Bytes }
  1521  
  1522  func (it *bytesIterator) Next(p *Value) bool {
  1523  	if it.bytes == "" {
  1524  		return false
  1525  	}
  1526  	*p = MakeInt(int(it.bytes[0]))
  1527  	it.bytes = it.bytes[1:]
  1528  	return true
  1529  }
  1530  
  1531  func (*bytesIterator) Done() {}
  1532  
  1533  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·count
  1534  func string_count(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1535  	var sub string
  1536  	var start_, end_ Value
  1537  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &sub, &start_, &end_); err != nil {
  1538  		return nil, err
  1539  	}
  1540  
  1541  	recv := string(b.Receiver().(String))
  1542  	start, end, err := indices(start_, end_, len(recv))
  1543  	if err != nil {
  1544  		return nil, nameErr(b, err)
  1545  	}
  1546  
  1547  	var slice string
  1548  	if start < end {
  1549  		slice = recv[start:end]
  1550  	}
  1551  	return MakeInt(strings.Count(slice, sub)), nil
  1552  }
  1553  
  1554  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·isalnum
  1555  func string_isalnum(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1556  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1557  		return nil, err
  1558  	}
  1559  	recv := string(b.Receiver().(String))
  1560  	for _, r := range recv {
  1561  		if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
  1562  			return False, nil
  1563  		}
  1564  	}
  1565  	return Bool(recv != ""), nil
  1566  }
  1567  
  1568  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·isalpha
  1569  func string_isalpha(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1570  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1571  		return nil, err
  1572  	}
  1573  	recv := string(b.Receiver().(String))
  1574  	for _, r := range recv {
  1575  		if !unicode.IsLetter(r) {
  1576  			return False, nil
  1577  		}
  1578  	}
  1579  	return Bool(recv != ""), nil
  1580  }
  1581  
  1582  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·isdigit
  1583  func string_isdigit(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1584  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1585  		return nil, err
  1586  	}
  1587  	recv := string(b.Receiver().(String))
  1588  	for _, r := range recv {
  1589  		if !unicode.IsDigit(r) {
  1590  			return False, nil
  1591  		}
  1592  	}
  1593  	return Bool(recv != ""), nil
  1594  }
  1595  
  1596  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·islower
  1597  func string_islower(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1598  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1599  		return nil, err
  1600  	}
  1601  	recv := string(b.Receiver().(String))
  1602  	return Bool(isCasedString(recv) && recv == strings.ToLower(recv)), nil
  1603  }
  1604  
  1605  // isCasedString reports whether its argument contains any cased code points.
  1606  func isCasedString(s string) bool {
  1607  	for _, r := range s {
  1608  		if isCasedRune(r) {
  1609  			return true
  1610  		}
  1611  	}
  1612  	return false
  1613  }
  1614  
  1615  func isCasedRune(r rune) bool {
  1616  	// It's unclear what the correct behavior is for a rune such as 'ffi',
  1617  	// a lowercase letter with no upper or title case and no SimpleFold.
  1618  	return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || unicode.SimpleFold(r) != r
  1619  }
  1620  
  1621  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·isspace
  1622  func string_isspace(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1623  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1624  		return nil, err
  1625  	}
  1626  	recv := string(b.Receiver().(String))
  1627  	for _, r := range recv {
  1628  		if !unicode.IsSpace(r) {
  1629  			return False, nil
  1630  		}
  1631  	}
  1632  	return Bool(recv != ""), nil
  1633  }
  1634  
  1635  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·istitle
  1636  func string_istitle(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1637  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1638  		return nil, err
  1639  	}
  1640  	recv := string(b.Receiver().(String))
  1641  
  1642  	// Python semantics differ from x==strings.{To,}Title(x) in Go:
  1643  	// "uppercase characters may only follow uncased characters and
  1644  	// lowercase characters only cased ones."
  1645  	var cased, prevCased bool
  1646  	for _, r := range recv {
  1647  		if 'A' <= r && r <= 'Z' || unicode.IsTitle(r) { // e.g. "Dž"
  1648  			if prevCased {
  1649  				return False, nil
  1650  			}
  1651  			prevCased = true
  1652  			cased = true
  1653  		} else if unicode.IsLower(r) {
  1654  			if !prevCased {
  1655  				return False, nil
  1656  			}
  1657  			prevCased = true
  1658  			cased = true
  1659  		} else if unicode.IsUpper(r) {
  1660  			return False, nil
  1661  		} else {
  1662  			prevCased = false
  1663  		}
  1664  	}
  1665  	return Bool(cased), nil
  1666  }
  1667  
  1668  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·isupper
  1669  func string_isupper(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1670  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1671  		return nil, err
  1672  	}
  1673  	recv := string(b.Receiver().(String))
  1674  	return Bool(isCasedString(recv) && recv == strings.ToUpper(recv)), nil
  1675  }
  1676  
  1677  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·find
  1678  func string_find(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1679  	return string_find_impl(b, args, kwargs, true, false)
  1680  }
  1681  
  1682  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·format
  1683  func string_format(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1684  	format := string(b.Receiver().(String))
  1685  	var auto, manual bool // kinds of positional indexing used
  1686  	buf := new(strings.Builder)
  1687  	index := 0
  1688  	for {
  1689  		literal := format
  1690  		i := strings.IndexByte(format, '{')
  1691  		if i >= 0 {
  1692  			literal = format[:i]
  1693  		}
  1694  
  1695  		// Replace "}}" with "}" in non-field portion, rejecting a lone '}'.
  1696  		for {
  1697  			j := strings.IndexByte(literal, '}')
  1698  			if j < 0 {
  1699  				buf.WriteString(literal)
  1700  				break
  1701  			}
  1702  			if len(literal) == j+1 || literal[j+1] != '}' {
  1703  				return nil, fmt.Errorf("format: single '}' in format")
  1704  			}
  1705  			buf.WriteString(literal[:j+1])
  1706  			literal = literal[j+2:]
  1707  		}
  1708  
  1709  		if i < 0 {
  1710  			break // end of format string
  1711  		}
  1712  
  1713  		if i+1 < len(format) && format[i+1] == '{' {
  1714  			// "{{" means a literal '{'
  1715  			buf.WriteByte('{')
  1716  			format = format[i+2:]
  1717  			continue
  1718  		}
  1719  
  1720  		format = format[i+1:]
  1721  		i = strings.IndexByte(format, '}')
  1722  		if i < 0 {
  1723  			return nil, fmt.Errorf("format: unmatched '{' in format")
  1724  		}
  1725  
  1726  		var arg Value
  1727  		conv := "s"
  1728  		var spec string
  1729  
  1730  		field := format[:i]
  1731  		format = format[i+1:]
  1732  
  1733  		var name string
  1734  		if i := strings.IndexByte(field, '!'); i < 0 {
  1735  			// "name" or "name:spec"
  1736  			if i := strings.IndexByte(field, ':'); i < 0 {
  1737  				name = field
  1738  			} else {
  1739  				name = field[:i]
  1740  				spec = field[i+1:]
  1741  			}
  1742  		} else {
  1743  			// "name!conv" or "name!conv:spec"
  1744  			name = field[:i]
  1745  			field = field[i+1:]
  1746  			// "conv" or "conv:spec"
  1747  			if i := strings.IndexByte(field, ':'); i < 0 {
  1748  				conv = field
  1749  			} else {
  1750  				conv = field[:i]
  1751  				spec = field[i+1:]
  1752  			}
  1753  		}
  1754  
  1755  		if name == "" {
  1756  			// "{}": automatic indexing
  1757  			if manual {
  1758  				return nil, fmt.Errorf("format: cannot switch from manual field specification to automatic field numbering")
  1759  			}
  1760  			auto = true
  1761  			if index >= len(args) {
  1762  				return nil, fmt.Errorf("format: tuple index out of range")
  1763  			}
  1764  			arg = args[index]
  1765  			index++
  1766  		} else if num, ok := decimal(name); ok {
  1767  			// positional argument
  1768  			if auto {
  1769  				return nil, fmt.Errorf("format: cannot switch from automatic field numbering to manual field specification")
  1770  			}
  1771  			manual = true
  1772  			if num >= len(args) {
  1773  				return nil, fmt.Errorf("format: tuple index out of range")
  1774  			} else {
  1775  				arg = args[num]
  1776  			}
  1777  		} else {
  1778  			// keyword argument
  1779  			for _, kv := range kwargs {
  1780  				if string(kv[0].(String)) == name {
  1781  					arg = kv[1]
  1782  					break
  1783  				}
  1784  			}
  1785  			if arg == nil {
  1786  				// Starlark does not support Python's x.y or a[i] syntaxes,
  1787  				// or nested use of {...}.
  1788  				if strings.Contains(name, ".") {
  1789  					return nil, fmt.Errorf("format: attribute syntax x.y is not supported in replacement fields: %s", name)
  1790  				}
  1791  				if strings.Contains(name, "[") {
  1792  					return nil, fmt.Errorf("format: element syntax a[i] is not supported in replacement fields: %s", name)
  1793  				}
  1794  				if strings.Contains(name, "{") {
  1795  					return nil, fmt.Errorf("format: nested replacement fields not supported")
  1796  				}
  1797  				return nil, fmt.Errorf("format: keyword %s not found", name)
  1798  			}
  1799  		}
  1800  
  1801  		if spec != "" {
  1802  			// Starlark does not support Python's format_spec features.
  1803  			return nil, fmt.Errorf("format spec features not supported in replacement fields: %s", spec)
  1804  		}
  1805  
  1806  		switch conv {
  1807  		case "s":
  1808  			if str, ok := AsString(arg); ok {
  1809  				buf.WriteString(str)
  1810  			} else {
  1811  				writeValue(buf, arg, nil)
  1812  			}
  1813  		case "r":
  1814  			writeValue(buf, arg, nil)
  1815  		default:
  1816  			return nil, fmt.Errorf("format: unknown conversion %q", conv)
  1817  		}
  1818  	}
  1819  	return String(buf.String()), nil
  1820  }
  1821  
  1822  // decimal interprets s as a sequence of decimal digits.
  1823  func decimal(s string) (x int, ok bool) {
  1824  	n := len(s)
  1825  	for i := 0; i < n; i++ {
  1826  		digit := s[i] - '0'
  1827  		if digit > 9 {
  1828  			return 0, false
  1829  		}
  1830  		x = x*10 + int(digit)
  1831  		if x < 0 {
  1832  			return 0, false // underflow
  1833  		}
  1834  	}
  1835  	return x, true
  1836  }
  1837  
  1838  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·index
  1839  func string_index(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1840  	return string_find_impl(b, args, kwargs, false, false)
  1841  }
  1842  
  1843  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·join
  1844  func string_join(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1845  	recv := string(b.Receiver().(String))
  1846  	var iterable Iterable
  1847  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &iterable); err != nil {
  1848  		return nil, err
  1849  	}
  1850  	iter := iterable.Iterate()
  1851  	defer iter.Done()
  1852  	buf := new(strings.Builder)
  1853  	var x Value
  1854  	for i := 0; iter.Next(&x); i++ {
  1855  		if i > 0 {
  1856  			buf.WriteString(recv)
  1857  		}
  1858  		s, ok := AsString(x)
  1859  		if !ok {
  1860  			return nil, fmt.Errorf("join: in list, want string, got %s", x.Type())
  1861  		}
  1862  		buf.WriteString(s)
  1863  	}
  1864  	return String(buf.String()), nil
  1865  }
  1866  
  1867  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·lower
  1868  func string_lower(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1869  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  1870  		return nil, err
  1871  	}
  1872  	return String(strings.ToLower(string(b.Receiver().(String)))), nil
  1873  }
  1874  
  1875  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·partition
  1876  func string_partition(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1877  	recv := string(b.Receiver().(String))
  1878  	var sep string
  1879  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &sep); err != nil {
  1880  		return nil, err
  1881  	}
  1882  	if sep == "" {
  1883  		return nil, nameErr(b, "empty separator")
  1884  	}
  1885  	var i int
  1886  	if b.Name()[0] == 'p' {
  1887  		i = strings.Index(recv, sep) // partition
  1888  	} else {
  1889  		i = strings.LastIndex(recv, sep) // rpartition
  1890  	}
  1891  	tuple := make(Tuple, 0, 3)
  1892  	if i < 0 {
  1893  		if b.Name()[0] == 'p' {
  1894  			tuple = append(tuple, String(recv), String(""), String(""))
  1895  		} else {
  1896  			tuple = append(tuple, String(""), String(""), String(recv))
  1897  		}
  1898  	} else {
  1899  		tuple = append(tuple, String(recv[:i]), String(sep), String(recv[i+len(sep):]))
  1900  	}
  1901  	return tuple, nil
  1902  }
  1903  
  1904  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·removeprefix
  1905  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·removesuffix
  1906  func string_removefix(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1907  	recv := string(b.Receiver().(String))
  1908  	var fix string
  1909  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &fix); err != nil {
  1910  		return nil, err
  1911  	}
  1912  	if b.name[len("remove")] == 'p' {
  1913  		recv = strings.TrimPrefix(recv, fix)
  1914  	} else {
  1915  		recv = strings.TrimSuffix(recv, fix)
  1916  	}
  1917  	return String(recv), nil
  1918  }
  1919  
  1920  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·replace
  1921  func string_replace(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1922  	recv := string(b.Receiver().(String))
  1923  	var old, new string
  1924  	count := -1
  1925  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 2, &old, &new, &count); err != nil {
  1926  		return nil, err
  1927  	}
  1928  	return String(strings.Replace(recv, old, new, count)), nil
  1929  }
  1930  
  1931  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·rfind
  1932  func string_rfind(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1933  	return string_find_impl(b, args, kwargs, true, true)
  1934  }
  1935  
  1936  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·rindex
  1937  func string_rindex(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1938  	return string_find_impl(b, args, kwargs, false, true)
  1939  }
  1940  
  1941  // https://github.com/google/starlark-go/starlark/blob/master/doc/spec.md#string·startswith
  1942  // https://github.com/google/starlark-go/starlark/blob/master/doc/spec.md#string·endswith
  1943  func string_startswith(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1944  	var x Value
  1945  	var start, end Value = None, None
  1946  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &x, &start, &end); err != nil {
  1947  		return nil, err
  1948  	}
  1949  
  1950  	// compute effective substring.
  1951  	s := string(b.Receiver().(String))
  1952  	if start, end, err := indices(start, end, len(s)); err != nil {
  1953  		return nil, nameErr(b, err)
  1954  	} else {
  1955  		if end < start {
  1956  			end = start // => empty result
  1957  		}
  1958  		s = s[start:end]
  1959  	}
  1960  
  1961  	f := strings.HasPrefix
  1962  	if b.Name()[0] == 'e' { // endswith
  1963  		f = strings.HasSuffix
  1964  	}
  1965  
  1966  	switch x := x.(type) {
  1967  	case Tuple:
  1968  		for i, x := range x {
  1969  			prefix, ok := AsString(x)
  1970  			if !ok {
  1971  				return nil, fmt.Errorf("%s: want string, got %s, for element %d",
  1972  					b.Name(), x.Type(), i)
  1973  			}
  1974  			if f(s, prefix) {
  1975  				return True, nil
  1976  			}
  1977  		}
  1978  		return False, nil
  1979  	case String:
  1980  		return Bool(f(s, string(x))), nil
  1981  	}
  1982  	return nil, fmt.Errorf("%s: got %s, want string or tuple of string", b.Name(), x.Type())
  1983  }
  1984  
  1985  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·strip
  1986  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·lstrip
  1987  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·rstrip
  1988  func string_strip(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  1989  	var chars string
  1990  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &chars); err != nil {
  1991  		return nil, err
  1992  	}
  1993  	recv := string(b.Receiver().(String))
  1994  	var s string
  1995  	switch b.Name()[0] {
  1996  	case 's': // strip
  1997  		if chars != "" {
  1998  			s = strings.Trim(recv, chars)
  1999  		} else {
  2000  			s = strings.TrimSpace(recv)
  2001  		}
  2002  	case 'l': // lstrip
  2003  		if chars != "" {
  2004  			s = strings.TrimLeft(recv, chars)
  2005  		} else {
  2006  			s = strings.TrimLeftFunc(recv, unicode.IsSpace)
  2007  		}
  2008  	case 'r': // rstrip
  2009  		if chars != "" {
  2010  			s = strings.TrimRight(recv, chars)
  2011  		} else {
  2012  			s = strings.TrimRightFunc(recv, unicode.IsSpace)
  2013  		}
  2014  	}
  2015  	return String(s), nil
  2016  }
  2017  
  2018  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·title
  2019  func string_title(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2020  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  2021  		return nil, err
  2022  	}
  2023  
  2024  	s := string(b.Receiver().(String))
  2025  
  2026  	// Python semantics differ from x==strings.{To,}Title(x) in Go:
  2027  	// "uppercase characters may only follow uncased characters and
  2028  	// lowercase characters only cased ones."
  2029  	buf := new(strings.Builder)
  2030  	buf.Grow(len(s))
  2031  	var prevCased bool
  2032  	for _, r := range s {
  2033  		if prevCased {
  2034  			r = unicode.ToLower(r)
  2035  		} else {
  2036  			r = unicode.ToTitle(r)
  2037  		}
  2038  		prevCased = isCasedRune(r)
  2039  		buf.WriteRune(r)
  2040  	}
  2041  	return String(buf.String()), nil
  2042  }
  2043  
  2044  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·upper
  2045  func string_upper(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2046  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  2047  		return nil, err
  2048  	}
  2049  	return String(strings.ToUpper(string(b.Receiver().(String)))), nil
  2050  }
  2051  
  2052  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·split
  2053  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·rsplit
  2054  func string_split(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2055  	recv := string(b.Receiver().(String))
  2056  	var sep_ Value
  2057  	maxsplit := -1
  2058  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &sep_, &maxsplit); err != nil {
  2059  		return nil, err
  2060  	}
  2061  
  2062  	var res []string
  2063  
  2064  	if sep_ == nil || sep_ == None {
  2065  		// special case: split on whitespace
  2066  		if maxsplit < 0 {
  2067  			res = strings.Fields(recv)
  2068  		} else if b.Name() == "split" {
  2069  			res = splitspace(recv, maxsplit)
  2070  		} else { // rsplit
  2071  			res = rsplitspace(recv, maxsplit)
  2072  		}
  2073  
  2074  	} else if sep, ok := AsString(sep_); ok {
  2075  		if sep == "" {
  2076  			return nil, fmt.Errorf("split: empty separator")
  2077  		}
  2078  		// usual case: split on non-empty separator
  2079  		if maxsplit < 0 {
  2080  			res = strings.Split(recv, sep)
  2081  		} else if b.Name() == "split" {
  2082  			res = strings.SplitN(recv, sep, maxsplit+1)
  2083  		} else { // rsplit
  2084  			res = strings.Split(recv, sep)
  2085  			if excess := len(res) - maxsplit; excess > 0 {
  2086  				res[0] = strings.Join(res[:excess], sep)
  2087  				res = append(res[:1], res[excess:]...)
  2088  			}
  2089  		}
  2090  
  2091  	} else {
  2092  		return nil, fmt.Errorf("split: got %s for separator, want string", sep_.Type())
  2093  	}
  2094  
  2095  	list := make([]Value, len(res))
  2096  	for i, x := range res {
  2097  		list[i] = String(x)
  2098  	}
  2099  	return NewList(list), nil
  2100  }
  2101  
  2102  // Precondition: max >= 0.
  2103  func rsplitspace(s string, max int) []string {
  2104  	res := make([]string, 0, max+1)
  2105  	end := -1 // index of field end, or -1 in a region of spaces.
  2106  	for i := len(s); i > 0; {
  2107  		r, sz := utf8.DecodeLastRuneInString(s[:i])
  2108  		if unicode.IsSpace(r) {
  2109  			if end >= 0 {
  2110  				if len(res) == max {
  2111  					break // let this field run to the start
  2112  				}
  2113  				res = append(res, s[i:end])
  2114  				end = -1
  2115  			}
  2116  		} else if end < 0 {
  2117  			end = i
  2118  		}
  2119  		i -= sz
  2120  	}
  2121  	if end >= 0 {
  2122  		res = append(res, s[:end])
  2123  	}
  2124  
  2125  	resLen := len(res)
  2126  	for i := 0; i < resLen/2; i++ {
  2127  		res[i], res[resLen-1-i] = res[resLen-1-i], res[i]
  2128  	}
  2129  
  2130  	return res
  2131  }
  2132  
  2133  // Precondition: max >= 0.
  2134  func splitspace(s string, max int) []string {
  2135  	var res []string
  2136  	start := -1 // index of field start, or -1 in a region of spaces
  2137  	for i, r := range s {
  2138  		if unicode.IsSpace(r) {
  2139  			if start >= 0 {
  2140  				if len(res) == max {
  2141  					break // let this field run to the end
  2142  				}
  2143  				res = append(res, s[start:i])
  2144  				start = -1
  2145  			}
  2146  		} else if start == -1 {
  2147  			start = i
  2148  		}
  2149  	}
  2150  	if start >= 0 {
  2151  		res = append(res, s[start:])
  2152  	}
  2153  	return res
  2154  }
  2155  
  2156  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·splitlines
  2157  func string_splitlines(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2158  	var keepends bool
  2159  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &keepends); err != nil {
  2160  		return nil, err
  2161  	}
  2162  	var lines []string
  2163  	if s := string(b.Receiver().(String)); s != "" {
  2164  		// TODO(adonovan): handle CRLF correctly.
  2165  		if keepends {
  2166  			lines = strings.SplitAfter(s, "\n")
  2167  		} else {
  2168  			lines = strings.Split(s, "\n")
  2169  		}
  2170  		if strings.HasSuffix(s, "\n") {
  2171  			lines = lines[:len(lines)-1]
  2172  		}
  2173  	}
  2174  	list := make([]Value, len(lines))
  2175  	for i, x := range lines {
  2176  		list[i] = String(x)
  2177  	}
  2178  	return NewList(list), nil
  2179  }
  2180  
  2181  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·add.
  2182  func set_add(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2183  	var elem Value
  2184  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &elem); err != nil {
  2185  		return nil, err
  2186  	}
  2187  	if found, err := b.Receiver().(*Set).Has(elem); err != nil {
  2188  		return nil, nameErr(b, err)
  2189  	} else if found {
  2190  		return None, nil
  2191  	}
  2192  	err := b.Receiver().(*Set).Insert(elem)
  2193  	if err != nil {
  2194  		return nil, nameErr(b, err)
  2195  	}
  2196  	return None, nil
  2197  }
  2198  
  2199  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·clear.
  2200  func set_clear(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2201  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  2202  		return nil, err
  2203  	}
  2204  	if b.Receiver().(*Set).Len() > 0 {
  2205  		if err := b.Receiver().(*Set).Clear(); err != nil {
  2206  			return nil, nameErr(b, err)
  2207  		}
  2208  	}
  2209  	return None, nil
  2210  }
  2211  
  2212  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·difference.
  2213  func set_difference(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2214  	// TODO: support multiple others: s.difference(*others)
  2215  	var other Iterable
  2216  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil {
  2217  		return nil, err
  2218  	}
  2219  	iter := other.Iterate()
  2220  	defer iter.Done()
  2221  	diff, err := b.Receiver().(*Set).Difference(iter)
  2222  	if err != nil {
  2223  		return nil, nameErr(b, err)
  2224  	}
  2225  	return diff, nil
  2226  }
  2227  
  2228  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set_intersection.
  2229  func set_intersection(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2230  	// TODO: support multiple others: s.difference(*others)
  2231  	var other Iterable
  2232  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil {
  2233  		return nil, err
  2234  	}
  2235  	iter := other.Iterate()
  2236  	defer iter.Done()
  2237  	diff, err := b.Receiver().(*Set).Intersection(iter)
  2238  	if err != nil {
  2239  		return nil, nameErr(b, err)
  2240  	}
  2241  	return diff, nil
  2242  }
  2243  
  2244  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set_issubset.
  2245  func set_issubset(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2246  	var other Iterable
  2247  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil {
  2248  		return nil, err
  2249  	}
  2250  	iter := other.Iterate()
  2251  	defer iter.Done()
  2252  	diff, err := b.Receiver().(*Set).IsSubset(iter)
  2253  	if err != nil {
  2254  		return nil, nameErr(b, err)
  2255  	}
  2256  	return Bool(diff), nil
  2257  }
  2258  
  2259  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set_issuperset.
  2260  func set_issuperset(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2261  	var other Iterable
  2262  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil {
  2263  		return nil, err
  2264  	}
  2265  	iter := other.Iterate()
  2266  	defer iter.Done()
  2267  	diff, err := b.Receiver().(*Set).IsSuperset(iter)
  2268  	if err != nil {
  2269  		return nil, nameErr(b, err)
  2270  	}
  2271  	return Bool(diff), nil
  2272  }
  2273  
  2274  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·discard.
  2275  func set_discard(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2276  	var k Value
  2277  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &k); err != nil {
  2278  		return nil, err
  2279  	}
  2280  	if found, err := b.Receiver().(*Set).Has(k); err != nil {
  2281  		return nil, nameErr(b, err)
  2282  	} else if !found {
  2283  		return None, nil
  2284  	}
  2285  	if _, err := b.Receiver().(*Set).Delete(k); err != nil {
  2286  		return nil, nameErr(b, err) // set is frozen
  2287  	}
  2288  	return None, nil
  2289  }
  2290  
  2291  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·pop.
  2292  func set_pop(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2293  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0); err != nil {
  2294  		return nil, err
  2295  	}
  2296  	recv := b.Receiver().(*Set)
  2297  	k, ok := recv.ht.first()
  2298  	if !ok {
  2299  		return nil, nameErr(b, "empty set")
  2300  	}
  2301  	_, err := recv.Delete(k)
  2302  	if err != nil {
  2303  		return nil, nameErr(b, err) // set is frozen
  2304  	}
  2305  	return k, nil
  2306  }
  2307  
  2308  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·remove.
  2309  func set_remove(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2310  	var k Value
  2311  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &k); err != nil {
  2312  		return nil, err
  2313  	}
  2314  	if found, err := b.Receiver().(*Set).Delete(k); err != nil {
  2315  		return nil, nameErr(b, err) // dict is frozen or key is unhashable
  2316  	} else if found {
  2317  		return None, nil
  2318  	}
  2319  	return nil, nameErr(b, "missing key")
  2320  }
  2321  
  2322  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·symmetric_difference.
  2323  func set_symmetric_difference(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2324  	var other Iterable
  2325  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil {
  2326  		return nil, err
  2327  	}
  2328  	iter := other.Iterate()
  2329  	defer iter.Done()
  2330  	diff, err := b.Receiver().(*Set).SymmetricDifference(iter)
  2331  	if err != nil {
  2332  		return nil, nameErr(b, err)
  2333  	}
  2334  	return diff, nil
  2335  }
  2336  
  2337  // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·union.
  2338  func set_union(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) {
  2339  	var iterable Iterable
  2340  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &iterable); err != nil {
  2341  		return nil, err
  2342  	}
  2343  	iter := iterable.Iterate()
  2344  	defer iter.Done()
  2345  	union, err := b.Receiver().(*Set).Union(iter)
  2346  	if err != nil {
  2347  		return nil, nameErr(b, err)
  2348  	}
  2349  	return union, nil
  2350  }
  2351  
  2352  // Common implementation of string_{r}{find,index}.
  2353  func string_find_impl(b *Builtin, args Tuple, kwargs []Tuple, allowError, last bool) (Value, error) {
  2354  	var sub string
  2355  	var start_, end_ Value
  2356  	if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &sub, &start_, &end_); err != nil {
  2357  		return nil, err
  2358  	}
  2359  
  2360  	s := string(b.Receiver().(String))
  2361  	start, end, err := indices(start_, end_, len(s))
  2362  	if err != nil {
  2363  		return nil, nameErr(b, err)
  2364  	}
  2365  	var slice string
  2366  	if start < end {
  2367  		slice = s[start:end]
  2368  	}
  2369  
  2370  	var i int
  2371  	if last {
  2372  		i = strings.LastIndex(slice, sub)
  2373  	} else {
  2374  		i = strings.Index(slice, sub)
  2375  	}
  2376  	if i < 0 {
  2377  		if !allowError {
  2378  			return nil, nameErr(b, "substring not found")
  2379  		}
  2380  		return MakeInt(-1), nil
  2381  	}
  2382  	return MakeInt(i + start), nil
  2383  }
  2384  
  2385  // Common implementation of builtin dict function and dict.update method.
  2386  // Precondition: len(updates) == 0 or 1.
  2387  func updateDict(dict *Dict, updates Tuple, kwargs []Tuple) error {
  2388  	if len(updates) == 1 {
  2389  		switch updates := updates[0].(type) {
  2390  		case IterableMapping:
  2391  			// Iterate over dict's key/value pairs, not just keys.
  2392  			for _, item := range updates.Items() {
  2393  				if err := dict.SetKey(item[0], item[1]); err != nil {
  2394  					return err // dict is frozen
  2395  				}
  2396  			}
  2397  		default:
  2398  			// all other sequences
  2399  			iter := Iterate(updates)
  2400  			if iter == nil {
  2401  				return fmt.Errorf("got %s, want iterable", updates.Type())
  2402  			}
  2403  			defer iter.Done()
  2404  			var pair Value
  2405  			for i := 0; iter.Next(&pair); i++ {
  2406  				iter2 := Iterate(pair)
  2407  				if iter2 == nil {
  2408  					return fmt.Errorf("dictionary update sequence element #%d is not iterable (%s)", i, pair.Type())
  2409  
  2410  				}
  2411  				defer iter2.Done()
  2412  				len := Len(pair)
  2413  				if len < 0 {
  2414  					return fmt.Errorf("dictionary update sequence element #%d has unknown length (%s)", i, pair.Type())
  2415  				} else if len != 2 {
  2416  					return fmt.Errorf("dictionary update sequence element #%d has length %d, want 2", i, len)
  2417  				}
  2418  				var k, v Value
  2419  				iter2.Next(&k)
  2420  				iter2.Next(&v)
  2421  				if err := dict.SetKey(k, v); err != nil {
  2422  					return err
  2423  				}
  2424  			}
  2425  		}
  2426  	}
  2427  
  2428  	// Then add the kwargs.
  2429  	before := dict.Len()
  2430  	for _, pair := range kwargs {
  2431  		if err := dict.SetKey(pair[0], pair[1]); err != nil {
  2432  			return err // dict is frozen
  2433  		}
  2434  	}
  2435  	// In the common case, each kwarg will add another dict entry.
  2436  	// If that's not so, check whether it is because there was a duplicate kwarg.
  2437  	if dict.Len() < before+len(kwargs) {
  2438  		keys := make(map[String]bool, len(kwargs))
  2439  		for _, kv := range kwargs {
  2440  			k := kv[0].(String)
  2441  			if keys[k] {
  2442  				return fmt.Errorf("duplicate keyword arg: %v", k)
  2443  			}
  2444  			keys[k] = true
  2445  		}
  2446  	}
  2447  
  2448  	return nil
  2449  }
  2450  
  2451  // nameErr returns an error message of the form "name: msg"
  2452  // where name is b.Name() and msg is a string or error.
  2453  func nameErr(b *Builtin, msg interface{}) error {
  2454  	return fmt.Errorf("%s: %v", b.Name(), msg)
  2455  }