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