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