go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/starlark/eval.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  import (
     8  	"fmt"
     9  	"io"
    10  	"log"
    11  	"math/big"
    12  	"sort"
    13  	"strings"
    14  	"sync/atomic"
    15  	"time"
    16  	"unicode"
    17  	"unicode/utf8"
    18  	"unsafe"
    19  
    20  	"go.starlark.net/internal/compile"
    21  	"go.starlark.net/internal/spell"
    22  	"go.starlark.net/resolve"
    23  	"go.starlark.net/syntax"
    24  )
    25  
    26  // A Thread contains the state of a Starlark thread,
    27  // such as its call stack and thread-local storage.
    28  // The Thread is threaded throughout the evaluator.
    29  type Thread struct {
    30  	// Name is an optional name that describes the thread, for debugging.
    31  	Name string
    32  
    33  	// stack is the stack of (internal) call frames.
    34  	stack []*frame
    35  
    36  	// Print is the client-supplied implementation of the Starlark
    37  	// 'print' function. If nil, fmt.Fprintln(os.Stderr, msg) is
    38  	// used instead.
    39  	Print func(thread *Thread, msg string)
    40  
    41  	// Load is the client-supplied implementation of module loading.
    42  	// Repeated calls with the same module name must return the same
    43  	// module environment or error.
    44  	// The error message need not include the module name.
    45  	//
    46  	// See example_test.go for some example implementations of Load.
    47  	Load func(thread *Thread, module string) (StringDict, error)
    48  
    49  	// OnMaxSteps is called when the thread reaches the limit set by SetMaxExecutionSteps.
    50  	// The default behavior is to call thread.Cancel("too many steps").
    51  	OnMaxSteps func(thread *Thread)
    52  
    53  	// Steps a count of abstract computation steps executed
    54  	// by this thread. It is incremented by the interpreter. It may be used
    55  	// as a measure of the approximate cost of Starlark execution, by
    56  	// computing the difference in its value before and after a computation.
    57  	//
    58  	// The precise meaning of "step" is not specified and may change.
    59  	Steps, maxSteps uint64
    60  
    61  	// cancelReason records the reason from the first call to Cancel.
    62  	cancelReason *string
    63  
    64  	// locals holds arbitrary "thread-local" Go values belonging to the client.
    65  	// They are accessible to the client but not to any Starlark program.
    66  	locals map[string]interface{}
    67  
    68  	// proftime holds the accumulated execution time since the last profile event.
    69  	proftime time.Duration
    70  }
    71  
    72  // ExecutionSteps returns the current value of Steps.
    73  func (thread *Thread) ExecutionSteps() uint64 {
    74  	return thread.Steps
    75  }
    76  
    77  // SetMaxExecutionSteps sets a limit on the number of Starlark
    78  // computation steps that may be executed by this thread. If the
    79  // thread's step counter exceeds this limit, the interpreter calls
    80  // the optional OnMaxSteps function or the default behavior
    81  // of calling thread.Cancel("too many steps").
    82  func (thread *Thread) SetMaxExecutionSteps(max uint64) {
    83  	thread.maxSteps = max
    84  }
    85  
    86  // Uncancel resets the cancellation state.
    87  //
    88  // Unlike most methods of Thread, it is safe to call Uncancel from any
    89  // goroutine, even if the thread is actively executing.
    90  func (thread *Thread) Uncancel() {
    91  	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&thread.cancelReason)), nil)
    92  }
    93  
    94  // Cancel causes execution of Starlark code in the specified thread to
    95  // promptly fail with an EvalError that includes the specified reason.
    96  // There may be a delay before the interpreter observes the cancellation
    97  // if the thread is currently in a call to a built-in function.
    98  //
    99  // Call [Uncancel] to reset the cancellation state.
   100  //
   101  // Unlike most methods of Thread, it is safe to call Cancel from any
   102  // goroutine, even if the thread is actively executing.
   103  func (thread *Thread) Cancel(reason string) {
   104  	// Atomically set cancelReason, preserving earlier reason if any.
   105  	atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&thread.cancelReason)), nil, unsafe.Pointer(&reason))
   106  }
   107  
   108  // SetLocal sets the thread-local value associated with the specified key.
   109  // It must not be called after execution begins.
   110  func (thread *Thread) SetLocal(key string, value interface{}) {
   111  	if thread.locals == nil {
   112  		thread.locals = make(map[string]interface{})
   113  	}
   114  	thread.locals[key] = value
   115  }
   116  
   117  // Local returns the thread-local value associated with the specified key.
   118  func (thread *Thread) Local(key string) interface{} {
   119  	return thread.locals[key]
   120  }
   121  
   122  // CallFrame returns a copy of the specified frame of the callstack.
   123  // It should only be used in built-ins called from Starlark code.
   124  // Depth 0 means the frame of the built-in itself, 1 is its caller, and so on.
   125  //
   126  // It is equivalent to CallStack().At(depth), but more efficient.
   127  func (thread *Thread) CallFrame(depth int) CallFrame {
   128  	return thread.frameAt(depth).asCallFrame()
   129  }
   130  
   131  func (thread *Thread) frameAt(depth int) *frame {
   132  	return thread.stack[len(thread.stack)-1-depth]
   133  }
   134  
   135  // CallStack returns a new slice containing the thread's stack of call frames.
   136  func (thread *Thread) CallStack() CallStack {
   137  	frames := make([]CallFrame, len(thread.stack))
   138  	for i, fr := range thread.stack {
   139  		frames[i] = fr.asCallFrame()
   140  	}
   141  	return frames
   142  }
   143  
   144  // CallStackDepth returns the number of frames in the current call stack.
   145  func (thread *Thread) CallStackDepth() int { return len(thread.stack) }
   146  
   147  // A StringDict is a mapping from names to values, and represents
   148  // an environment such as the global variables of a module.
   149  // It is not a true starlark.Value.
   150  type StringDict map[string]Value
   151  
   152  // Keys returns a new sorted slice of d's keys.
   153  func (d StringDict) Keys() []string {
   154  	names := make([]string, 0, len(d))
   155  	for name := range d {
   156  		names = append(names, name)
   157  	}
   158  	sort.Strings(names)
   159  	return names
   160  }
   161  
   162  func (d StringDict) String() string {
   163  	buf := new(strings.Builder)
   164  	buf.WriteByte('{')
   165  	sep := ""
   166  	for _, name := range d.Keys() {
   167  		buf.WriteString(sep)
   168  		buf.WriteString(name)
   169  		buf.WriteString(": ")
   170  		writeValue(buf, d[name], nil)
   171  		sep = ", "
   172  	}
   173  	buf.WriteByte('}')
   174  	return buf.String()
   175  }
   176  
   177  func (d StringDict) Freeze() {
   178  	for _, v := range d {
   179  		v.Freeze()
   180  	}
   181  }
   182  
   183  // Has reports whether the dictionary contains the specified key.
   184  func (d StringDict) Has(key string) bool { _, ok := d[key]; return ok }
   185  
   186  // A frame records a call to a Starlark function (including module toplevel)
   187  // or a built-in function or method.
   188  type frame struct {
   189  	callable  Callable // current function (or toplevel) or built-in
   190  	pc        uint32   // program counter (Starlark frames only)
   191  	locals    []Value  // local variables (Starlark frames only)
   192  	spanStart int64    // start time of current profiler span
   193  }
   194  
   195  // Position returns the source position of the current point of execution in this frame.
   196  func (fr *frame) Position() syntax.Position {
   197  	switch c := fr.callable.(type) {
   198  	case *Function:
   199  		// Starlark function
   200  		return c.funcode.Position(fr.pc)
   201  	case callableWithPosition:
   202  		// If a built-in Callable defines
   203  		// a Position method, use it.
   204  		return c.Position()
   205  	}
   206  	return syntax.MakePosition(&builtinFilename, 0, 0)
   207  }
   208  
   209  var builtinFilename = "<builtin>"
   210  
   211  // Function returns the frame's function or built-in.
   212  func (fr *frame) Callable() Callable { return fr.callable }
   213  
   214  // A CallStack is a stack of call frames, outermost first.
   215  type CallStack []CallFrame
   216  
   217  // At returns a copy of the frame at depth i.
   218  // At(0) returns the topmost frame.
   219  func (stack CallStack) At(i int) CallFrame { return stack[len(stack)-1-i] }
   220  
   221  // Pop removes and returns the topmost frame.
   222  func (stack *CallStack) Pop() CallFrame {
   223  	last := len(*stack) - 1
   224  	top := (*stack)[last]
   225  	*stack = (*stack)[:last]
   226  	return top
   227  }
   228  
   229  // String returns a user-friendly description of the stack.
   230  func (stack CallStack) String() string {
   231  	out := new(strings.Builder)
   232  	if len(stack) > 0 {
   233  		fmt.Fprintf(out, "Traceback (most recent call last):\n")
   234  	}
   235  	for _, fr := range stack {
   236  		fmt.Fprintf(out, "  %s: in %s\n", fr.Pos, fr.Name)
   237  	}
   238  	return out.String()
   239  }
   240  
   241  // An EvalError is a Starlark evaluation error and
   242  // a copy of the thread's stack at the moment of the error.
   243  type EvalError struct {
   244  	Msg       string
   245  	CallStack CallStack
   246  	cause     error
   247  }
   248  
   249  // A CallFrame represents the function name and current
   250  // position of execution of an enclosing call frame.
   251  type CallFrame struct {
   252  	Name string
   253  	Pos  syntax.Position
   254  }
   255  
   256  func (fr *frame) asCallFrame() CallFrame {
   257  	return CallFrame{
   258  		Name: fr.Callable().Name(),
   259  		Pos:  fr.Position(),
   260  	}
   261  }
   262  
   263  func (thread *Thread) evalError(err error) *EvalError {
   264  	return &EvalError{
   265  		Msg:       err.Error(),
   266  		CallStack: thread.CallStack(),
   267  		cause:     err,
   268  	}
   269  }
   270  
   271  func (e *EvalError) Error() string { return e.Msg }
   272  
   273  // Backtrace returns a user-friendly error message describing the stack
   274  // of calls that led to this error.
   275  func (e *EvalError) Backtrace() string {
   276  	// If the topmost stack frame is a built-in function,
   277  	// remove it from the stack and add print "Error in fn:".
   278  	stack := e.CallStack
   279  	suffix := ""
   280  	if last := len(stack) - 1; last >= 0 && stack[last].Pos.Filename() == builtinFilename {
   281  		suffix = " in " + stack[last].Name
   282  		stack = stack[:last]
   283  	}
   284  	return fmt.Sprintf("%sError%s: %s", stack, suffix, e.Msg)
   285  }
   286  
   287  func (e *EvalError) Unwrap() error { return e.cause }
   288  
   289  // A Program is a compiled Starlark program.
   290  //
   291  // Programs are immutable, and contain no Values.
   292  // A Program may be created by parsing a source file (see SourceProgram)
   293  // or by loading a previously saved compiled program (see CompiledProgram).
   294  type Program struct {
   295  	compiled *compile.Program
   296  }
   297  
   298  // CompilerVersion is the version number of the protocol for compiled
   299  // files. Applications must not run programs compiled by one version
   300  // with an interpreter at another version, and should thus incorporate
   301  // the compiler version into the cache key when reusing compiled code.
   302  const CompilerVersion = compile.Version
   303  
   304  // Filename returns the name of the file from which this program was loaded.
   305  func (prog *Program) Filename() string { return prog.compiled.Toplevel.Pos.Filename() }
   306  
   307  func (prog *Program) String() string { return prog.Filename() }
   308  
   309  // NumLoads returns the number of load statements in the compiled program.
   310  func (prog *Program) NumLoads() int { return len(prog.compiled.Loads) }
   311  
   312  // Load(i) returns the name and position of the i'th module directly
   313  // loaded by this one, where 0 <= i < NumLoads().
   314  // The name is unresolved---exactly as it appears in the source.
   315  func (prog *Program) Load(i int) (string, syntax.Position) {
   316  	id := prog.compiled.Loads[i]
   317  	return id.Name, id.Pos
   318  }
   319  
   320  // WriteTo writes the compiled module to the specified output stream.
   321  func (prog *Program) Write(out io.Writer) error {
   322  	data := prog.compiled.Encode()
   323  	_, err := out.Write(data)
   324  	return err
   325  }
   326  
   327  // ExecFile calls [ExecFileOptions] using [syntax.LegacyFileOptions].
   328  // Deprecated: relies on legacy global variables.
   329  func ExecFile(thread *Thread, filename string, src interface{}, predeclared StringDict) (StringDict, error) {
   330  	return ExecFileOptions(syntax.LegacyFileOptions(), thread, filename, src, predeclared)
   331  }
   332  
   333  // ExecFileOptions parses, resolves, and executes a Starlark file in the
   334  // specified global environment, which may be modified during execution.
   335  //
   336  // Thread is the state associated with the Starlark thread.
   337  //
   338  // The filename and src parameters are as for syntax.Parse:
   339  // filename is the name of the file to execute,
   340  // and the name that appears in error messages;
   341  // src is an optional source of bytes to use
   342  // instead of filename.
   343  //
   344  // predeclared defines the predeclared names specific to this module.
   345  // Execution does not modify this dictionary, though it may mutate
   346  // its values.
   347  //
   348  // If ExecFileOptions fails during evaluation, it returns an *EvalError
   349  // containing a backtrace.
   350  func ExecFileOptions(opts *syntax.FileOptions, thread *Thread, filename string, src interface{}, predeclared StringDict) (StringDict, error) {
   351  	// Parse, resolve, and compile a Starlark source file.
   352  	_, mod, err := SourceProgramOptions(opts, filename, src, predeclared.Has)
   353  	if err != nil {
   354  		return nil, err
   355  	}
   356  
   357  	g, err := mod.Init(thread, predeclared)
   358  	g.Freeze()
   359  	return g, err
   360  }
   361  
   362  // SourceProgram calls [SourceProgramOptions] using [syntax.LegacyFileOptions].
   363  // Deprecated: relies on legacy global variables.
   364  func SourceProgram(filename string, src interface{}, isPredeclared func(string) bool) (*syntax.File, *Program, error) {
   365  	return SourceProgramOptions(syntax.LegacyFileOptions(), filename, src, isPredeclared)
   366  }
   367  
   368  // SourceProgramOptions produces a new program by parsing, resolving,
   369  // and compiling a Starlark source file.
   370  // On success, it returns the parsed file and the compiled program.
   371  // The filename and src parameters are as for syntax.Parse.
   372  //
   373  // The isPredeclared predicate reports whether a name is
   374  // a pre-declared identifier of the current module.
   375  // Its typical value is predeclared.Has,
   376  // where predeclared is a StringDict of pre-declared values.
   377  func SourceProgramOptions(opts *syntax.FileOptions, filename string, src interface{}, isPredeclared func(string) bool) (*syntax.File, *Program, error) {
   378  	f, err := opts.Parse(filename, src, 0)
   379  	if err != nil {
   380  		return nil, nil, err
   381  	}
   382  	prog, err := FileProgram(f, isPredeclared)
   383  	return f, prog, err
   384  }
   385  
   386  // FileProgram produces a new program by resolving,
   387  // and compiling the Starlark source file syntax tree.
   388  // On success, it returns the compiled program.
   389  //
   390  // Resolving a syntax tree mutates it.
   391  // Do not call FileProgram more than once on the same file.
   392  //
   393  // The isPredeclared predicate reports whether a name is
   394  // a pre-declared identifier of the current module.
   395  // Its typical value is predeclared.Has,
   396  // where predeclared is a StringDict of pre-declared values.
   397  func FileProgram(f *syntax.File, isPredeclared func(string) bool) (*Program, error) {
   398  	if err := resolve.File(f, isPredeclared, Universe.Has); err != nil {
   399  		return nil, err
   400  	}
   401  
   402  	var pos syntax.Position
   403  	if len(f.Stmts) > 0 {
   404  		pos = syntax.Start(f.Stmts[0])
   405  	} else {
   406  		pos = syntax.MakePosition(&f.Path, 1, 1)
   407  	}
   408  
   409  	module := f.Module.(*resolve.Module)
   410  	compiled := compile.File(f.Options, f.Stmts, pos, "<toplevel>", module.Locals, module.Globals)
   411  
   412  	return &Program{compiled}, nil
   413  }
   414  
   415  // CompiledProgram produces a new program from the representation
   416  // of a compiled program previously saved by Program.Write.
   417  func CompiledProgram(in io.Reader) (*Program, error) {
   418  	data, err := io.ReadAll(in)
   419  	if err != nil {
   420  		return nil, err
   421  	}
   422  	compiled, err := compile.DecodeProgram(data)
   423  	if err != nil {
   424  		return nil, err
   425  	}
   426  	return &Program{compiled}, nil
   427  }
   428  
   429  // Init creates a set of global variables for the program,
   430  // executes the toplevel code of the specified program,
   431  // and returns a new, unfrozen dictionary of the globals.
   432  func (prog *Program) Init(thread *Thread, predeclared StringDict) (StringDict, error) {
   433  	toplevel := makeToplevelFunction(prog.compiled, predeclared)
   434  
   435  	_, err := Call(thread, toplevel, nil, nil)
   436  
   437  	// Convert the global environment to a map.
   438  	// We return a (partial) map even in case of error.
   439  	return toplevel.Globals(), err
   440  }
   441  
   442  // ExecREPLChunk compiles and executes file f in the specified thread
   443  // and global environment. This is a variant of ExecFile specialized to
   444  // the needs of a REPL, in which a sequence of input chunks, each
   445  // syntactically a File, manipulates the same set of module globals,
   446  // which are not frozen after execution.
   447  //
   448  // This function is intended to support only go.starlark.net/repl.
   449  // Its API stability is not guaranteed.
   450  func ExecREPLChunk(f *syntax.File, thread *Thread, globals StringDict) error {
   451  	var predeclared StringDict
   452  
   453  	// -- variant of FileProgram --
   454  
   455  	if err := resolve.REPLChunk(f, globals.Has, predeclared.Has, Universe.Has); err != nil {
   456  		return err
   457  	}
   458  
   459  	var pos syntax.Position
   460  	if len(f.Stmts) > 0 {
   461  		pos = syntax.Start(f.Stmts[0])
   462  	} else {
   463  		pos = syntax.MakePosition(&f.Path, 1, 1)
   464  	}
   465  
   466  	module := f.Module.(*resolve.Module)
   467  	compiled := compile.File(f.Options, f.Stmts, pos, "<toplevel>", module.Locals, module.Globals)
   468  	prog := &Program{compiled}
   469  
   470  	// -- variant of Program.Init --
   471  
   472  	toplevel := makeToplevelFunction(prog.compiled, predeclared)
   473  
   474  	// Initialize module globals from parameter.
   475  	for i, id := range prog.compiled.Globals {
   476  		if v := globals[id.Name]; v != nil {
   477  			toplevel.module.globals[i] = v
   478  		}
   479  	}
   480  
   481  	_, err := Call(thread, toplevel, nil, nil)
   482  
   483  	// Reflect changes to globals back to parameter, even after an error.
   484  	for i, id := range prog.compiled.Globals {
   485  		if v := toplevel.module.globals[i]; v != nil {
   486  			globals[id.Name] = v
   487  		}
   488  	}
   489  
   490  	return err
   491  }
   492  
   493  func makeToplevelFunction(prog *compile.Program, predeclared StringDict) *Function {
   494  	// Create the Starlark value denoted by each program constant c.
   495  	constants := make([]Value, len(prog.Constants))
   496  	for i, c := range prog.Constants {
   497  		var v Value
   498  		switch c := c.(type) {
   499  		case int64:
   500  			v = MakeInt64(c)
   501  		case *big.Int:
   502  			v = MakeBigInt(c)
   503  		case string:
   504  			v = String(c)
   505  		case compile.Bytes:
   506  			v = Bytes(c)
   507  		case float64:
   508  			v = Float(c)
   509  		default:
   510  			log.Panicf("unexpected constant %T: %v", c, c)
   511  		}
   512  		constants[i] = v
   513  	}
   514  
   515  	return &Function{
   516  		funcode: prog.Toplevel,
   517  		module: &module{
   518  			program:     prog,
   519  			predeclared: predeclared,
   520  			globals:     make([]Value, len(prog.Globals)),
   521  			constants:   constants,
   522  		},
   523  	}
   524  }
   525  
   526  // Eval calls [EvalOptions] using [syntax.LegacyFileOptions].
   527  // Deprecated: relies on legacy global variables.
   528  func Eval(thread *Thread, filename string, src interface{}, env StringDict) (Value, error) {
   529  	return EvalOptions(syntax.LegacyFileOptions(), thread, filename, src, env)
   530  }
   531  
   532  // EvalOptions parses, resolves, and evaluates an expression within the
   533  // specified (predeclared) environment.
   534  //
   535  // Evaluation cannot mutate the environment dictionary itself,
   536  // though it may modify variables reachable from the dictionary.
   537  //
   538  // The filename and src parameters are as for syntax.Parse.
   539  //
   540  // If EvalOptions fails during evaluation, it returns an *EvalError
   541  // containing a backtrace.
   542  func EvalOptions(opts *syntax.FileOptions, thread *Thread, filename string, src interface{}, env StringDict) (Value, error) {
   543  	expr, err := opts.ParseExpr(filename, src, 0)
   544  	if err != nil {
   545  		return nil, err
   546  	}
   547  	f, err := makeExprFunc(opts, expr, env)
   548  	if err != nil {
   549  		return nil, err
   550  	}
   551  	return Call(thread, f, nil, nil)
   552  }
   553  
   554  // EvalExpr calls [EvalExprOptions] using [syntax.LegacyFileOptions].
   555  // Deprecated: relies on legacy global variables.
   556  func EvalExpr(thread *Thread, expr syntax.Expr, env StringDict) (Value, error) {
   557  	return EvalExprOptions(syntax.LegacyFileOptions(), thread, expr, env)
   558  }
   559  
   560  // EvalExprOptions resolves and evaluates an expression within the
   561  // specified (predeclared) environment.
   562  // Evaluating a comma-separated list of expressions yields a tuple value.
   563  //
   564  // Resolving an expression mutates it.
   565  // Do not call EvalExprOptions more than once for the same expression.
   566  //
   567  // Evaluation cannot mutate the environment dictionary itself,
   568  // though it may modify variables reachable from the dictionary.
   569  //
   570  // If EvalExprOptions fails during evaluation, it returns an *EvalError
   571  // containing a backtrace.
   572  func EvalExprOptions(opts *syntax.FileOptions, thread *Thread, expr syntax.Expr, env StringDict) (Value, error) {
   573  	fn, err := makeExprFunc(opts, expr, env)
   574  	if err != nil {
   575  		return nil, err
   576  	}
   577  	return Call(thread, fn, nil, nil)
   578  }
   579  
   580  // ExprFunc calls [ExprFuncOptions] using [syntax.LegacyFileOptions].
   581  // Deprecated: relies on legacy global variables.
   582  func ExprFunc(filename string, src interface{}, env StringDict) (*Function, error) {
   583  	return ExprFuncOptions(syntax.LegacyFileOptions(), filename, src, env)
   584  }
   585  
   586  // ExprFunc returns a no-argument function
   587  // that evaluates the expression whose source is src.
   588  func ExprFuncOptions(options *syntax.FileOptions, filename string, src interface{}, env StringDict) (*Function, error) {
   589  	expr, err := options.ParseExpr(filename, src, 0)
   590  	if err != nil {
   591  		return nil, err
   592  	}
   593  	return makeExprFunc(options, expr, env)
   594  }
   595  
   596  // makeExprFunc returns a no-argument function whose body is expr.
   597  // The options must be consistent with those used when parsing expr.
   598  func makeExprFunc(opts *syntax.FileOptions, expr syntax.Expr, env StringDict) (*Function, error) {
   599  	locals, err := resolve.ExprOptions(opts, expr, env.Has, Universe.Has)
   600  	if err != nil {
   601  		return nil, err
   602  	}
   603  
   604  	return makeToplevelFunction(compile.Expr(opts, expr, "<expr>", locals), env), nil
   605  }
   606  
   607  // The following functions are primitive operations of the byte code interpreter.
   608  
   609  // list += iterable
   610  func listExtend(x *List, y Iterable) {
   611  	if ylist, ok := y.(*List); ok {
   612  		// fast path: list += list
   613  		x.elems = append(x.elems, ylist.elems...)
   614  	} else {
   615  		iter := y.Iterate()
   616  		defer iter.Done()
   617  		var z Value
   618  		for iter.Next(&z) {
   619  			x.elems = append(x.elems, z)
   620  		}
   621  	}
   622  }
   623  
   624  // getAttr implements x.dot.
   625  func getAttr(x Value, name string) (Value, error) {
   626  	hasAttr, ok := x.(HasAttrs)
   627  	if !ok {
   628  		return nil, fmt.Errorf("%s has no .%s field or method", x.Type(), name)
   629  	}
   630  
   631  	var errmsg string
   632  	v, err := hasAttr.Attr(name)
   633  	if err == nil {
   634  		if v != nil {
   635  			return v, nil // success
   636  		}
   637  		// (nil, nil) => generic error
   638  		errmsg = fmt.Sprintf("%s has no .%s field or method", x.Type(), name)
   639  	} else if nsa, ok := err.(NoSuchAttrError); ok {
   640  		errmsg = string(nsa)
   641  	} else {
   642  		return nil, err // return error as is
   643  	}
   644  
   645  	// add spelling hint
   646  	if n := spell.Nearest(name, hasAttr.AttrNames()); n != "" {
   647  		errmsg = fmt.Sprintf("%s (did you mean .%s?)", errmsg, n)
   648  	}
   649  
   650  	return nil, fmt.Errorf("%s", errmsg)
   651  }
   652  
   653  // setField implements x.name = y.
   654  func setField(x Value, name string, y Value) error {
   655  	if x, ok := x.(HasSetField); ok {
   656  		err := x.SetField(name, y)
   657  		if _, ok := err.(NoSuchAttrError); ok {
   658  			// No such field: check spelling.
   659  			if n := spell.Nearest(name, x.AttrNames()); n != "" {
   660  				err = fmt.Errorf("%s (did you mean .%s?)", err, n)
   661  			}
   662  		}
   663  		return err
   664  	}
   665  
   666  	return fmt.Errorf("can't assign to .%s field of %s", name, x.Type())
   667  }
   668  
   669  // getIndex implements x[y].
   670  func getIndex(x, y Value) (Value, error) {
   671  	switch x := x.(type) {
   672  	case Mapping: // dict
   673  		z, found, err := x.Get(y)
   674  		if err != nil {
   675  			return nil, err
   676  		}
   677  		if !found {
   678  			return nil, fmt.Errorf("key %v not in %s", y, x.Type())
   679  		}
   680  		return z, nil
   681  
   682  	case Indexable: // string, list, tuple
   683  		n := x.Len()
   684  		i, err := AsInt32(y)
   685  		if err != nil {
   686  			return nil, fmt.Errorf("%s index: %s", x.Type(), err)
   687  		}
   688  		origI := i
   689  		if i < 0 {
   690  			i += n
   691  		}
   692  		if i < 0 || i >= n {
   693  			return nil, outOfRange(origI, n, x)
   694  		}
   695  		return x.Index(i), nil
   696  	}
   697  	return nil, fmt.Errorf("unhandled index operation %s[%s]", x.Type(), y.Type())
   698  }
   699  
   700  func outOfRange(i, n int, x Value) error {
   701  	if n == 0 {
   702  		return fmt.Errorf("index %d out of range: empty %s", i, x.Type())
   703  	} else {
   704  		return fmt.Errorf("%s index %d out of range [%d:%d]", x.Type(), i, -n, n-1)
   705  	}
   706  }
   707  
   708  // setIndex implements x[y] = z.
   709  func setIndex(x, y, z Value) error {
   710  	switch x := x.(type) {
   711  	case HasSetKey:
   712  		if err := x.SetKey(y, z); err != nil {
   713  			return err
   714  		}
   715  
   716  	case HasSetIndex:
   717  		n := x.Len()
   718  		i, err := AsInt32(y)
   719  		if err != nil {
   720  			return err
   721  		}
   722  		origI := i
   723  		if i < 0 {
   724  			i += n
   725  		}
   726  		if i < 0 || i >= n {
   727  			return outOfRange(origI, n, x)
   728  		}
   729  		return x.SetIndex(i, z)
   730  
   731  	default:
   732  		return fmt.Errorf("%s value does not support item assignment", x.Type())
   733  	}
   734  	return nil
   735  }
   736  
   737  // Unary applies a unary operator (+, -, ~, not) to its operand.
   738  func Unary(op syntax.Token, x Value) (Value, error) {
   739  	// The NOT operator is not customizable.
   740  	if op == syntax.NOT {
   741  		return !x.Truth(), nil
   742  	}
   743  
   744  	// Int, Float, and user-defined types
   745  	if x, ok := x.(HasUnary); ok {
   746  		// (nil, nil) => unhandled
   747  		y, err := x.Unary(op)
   748  		if y != nil || err != nil {
   749  			return y, err
   750  		}
   751  	}
   752  
   753  	return nil, fmt.Errorf("unknown unary op: %s %s", op, x.Type())
   754  }
   755  
   756  // Binary applies a strict binary operator (not AND or OR) to its operands.
   757  // For equality tests or ordered comparisons, use Compare instead.
   758  func Binary(op syntax.Token, x, y Value) (Value, error) {
   759  	switch op {
   760  	case syntax.PLUS:
   761  		switch x := x.(type) {
   762  		case String:
   763  			if y, ok := y.(String); ok {
   764  				return x + y, nil
   765  			}
   766  		case Int:
   767  			switch y := y.(type) {
   768  			case Int:
   769  				return x.Add(y), nil
   770  			case Float:
   771  				xf, err := x.finiteFloat()
   772  				if err != nil {
   773  					return nil, err
   774  				}
   775  				return xf + y, nil
   776  			}
   777  		case Float:
   778  			switch y := y.(type) {
   779  			case Float:
   780  				return x + y, nil
   781  			case Int:
   782  				yf, err := y.finiteFloat()
   783  				if err != nil {
   784  					return nil, err
   785  				}
   786  				return x + yf, nil
   787  			}
   788  		case *List:
   789  			if y, ok := y.(*List); ok {
   790  				z := make([]Value, 0, x.Len()+y.Len())
   791  				z = append(z, x.elems...)
   792  				z = append(z, y.elems...)
   793  				return NewList(z), nil
   794  			}
   795  		case Tuple:
   796  			if y, ok := y.(Tuple); ok {
   797  				z := make(Tuple, 0, len(x)+len(y))
   798  				z = append(z, x...)
   799  				z = append(z, y...)
   800  				return z, nil
   801  			}
   802  		}
   803  
   804  	case syntax.MINUS:
   805  		switch x := x.(type) {
   806  		case Int:
   807  			switch y := y.(type) {
   808  			case Int:
   809  				return x.Sub(y), nil
   810  			case Float:
   811  				xf, err := x.finiteFloat()
   812  				if err != nil {
   813  					return nil, err
   814  				}
   815  				return xf - y, nil
   816  			}
   817  		case Float:
   818  			switch y := y.(type) {
   819  			case Float:
   820  				return x - y, nil
   821  			case Int:
   822  				yf, err := y.finiteFloat()
   823  				if err != nil {
   824  					return nil, err
   825  				}
   826  				return x - yf, nil
   827  			}
   828  		case *Set: // difference
   829  			if y, ok := y.(*Set); ok {
   830  				iter := y.Iterate()
   831  				defer iter.Done()
   832  				return x.Difference(iter)
   833  			}
   834  		}
   835  
   836  	case syntax.STAR:
   837  		switch x := x.(type) {
   838  		case Int:
   839  			switch y := y.(type) {
   840  			case Int:
   841  				return x.Mul(y), nil
   842  			case Float:
   843  				xf, err := x.finiteFloat()
   844  				if err != nil {
   845  					return nil, err
   846  				}
   847  				return xf * y, nil
   848  			case String:
   849  				return stringRepeat(y, x)
   850  			case Bytes:
   851  				return bytesRepeat(y, x)
   852  			case *List:
   853  				elems, err := tupleRepeat(Tuple(y.elems), x)
   854  				if err != nil {
   855  					return nil, err
   856  				}
   857  				return NewList(elems), nil
   858  			case Tuple:
   859  				return tupleRepeat(y, x)
   860  			}
   861  		case Float:
   862  			switch y := y.(type) {
   863  			case Float:
   864  				return x * y, nil
   865  			case Int:
   866  				yf, err := y.finiteFloat()
   867  				if err != nil {
   868  					return nil, err
   869  				}
   870  				return x * yf, nil
   871  			}
   872  		case String:
   873  			if y, ok := y.(Int); ok {
   874  				return stringRepeat(x, y)
   875  			}
   876  		case Bytes:
   877  			if y, ok := y.(Int); ok {
   878  				return bytesRepeat(x, y)
   879  			}
   880  		case *List:
   881  			if y, ok := y.(Int); ok {
   882  				elems, err := tupleRepeat(Tuple(x.elems), y)
   883  				if err != nil {
   884  					return nil, err
   885  				}
   886  				return NewList(elems), nil
   887  			}
   888  		case Tuple:
   889  			if y, ok := y.(Int); ok {
   890  				return tupleRepeat(x, y)
   891  			}
   892  
   893  		}
   894  
   895  	case syntax.SLASH:
   896  		switch x := x.(type) {
   897  		case Int:
   898  			xf, err := x.finiteFloat()
   899  			if err != nil {
   900  				return nil, err
   901  			}
   902  			switch y := y.(type) {
   903  			case Int:
   904  				yf, err := y.finiteFloat()
   905  				if err != nil {
   906  					return nil, err
   907  				}
   908  				if yf == 0.0 {
   909  					return nil, fmt.Errorf("floating-point division by zero")
   910  				}
   911  				return xf / yf, nil
   912  			case Float:
   913  				if y == 0.0 {
   914  					return nil, fmt.Errorf("floating-point division by zero")
   915  				}
   916  				return xf / y, nil
   917  			}
   918  		case Float:
   919  			switch y := y.(type) {
   920  			case Float:
   921  				if y == 0.0 {
   922  					return nil, fmt.Errorf("floating-point division by zero")
   923  				}
   924  				return x / y, nil
   925  			case Int:
   926  				yf, err := y.finiteFloat()
   927  				if err != nil {
   928  					return nil, err
   929  				}
   930  				if yf == 0.0 {
   931  					return nil, fmt.Errorf("floating-point division by zero")
   932  				}
   933  				return x / yf, nil
   934  			}
   935  		}
   936  
   937  	case syntax.SLASHSLASH:
   938  		switch x := x.(type) {
   939  		case Int:
   940  			switch y := y.(type) {
   941  			case Int:
   942  				if y.Sign() == 0 {
   943  					return nil, fmt.Errorf("floored division by zero")
   944  				}
   945  				return x.Div(y), nil
   946  			case Float:
   947  				xf, err := x.finiteFloat()
   948  				if err != nil {
   949  					return nil, err
   950  				}
   951  				if y == 0.0 {
   952  					return nil, fmt.Errorf("floored division by zero")
   953  				}
   954  				return floor(xf / y), nil
   955  			}
   956  		case Float:
   957  			switch y := y.(type) {
   958  			case Float:
   959  				if y == 0.0 {
   960  					return nil, fmt.Errorf("floored division by zero")
   961  				}
   962  				return floor(x / y), nil
   963  			case Int:
   964  				yf, err := y.finiteFloat()
   965  				if err != nil {
   966  					return nil, err
   967  				}
   968  				if yf == 0.0 {
   969  					return nil, fmt.Errorf("floored division by zero")
   970  				}
   971  				return floor(x / yf), nil
   972  			}
   973  		}
   974  
   975  	case syntax.PERCENT:
   976  		switch x := x.(type) {
   977  		case Int:
   978  			switch y := y.(type) {
   979  			case Int:
   980  				if y.Sign() == 0 {
   981  					return nil, fmt.Errorf("integer modulo by zero")
   982  				}
   983  				return x.Mod(y), nil
   984  			case Float:
   985  				xf, err := x.finiteFloat()
   986  				if err != nil {
   987  					return nil, err
   988  				}
   989  				if y == 0 {
   990  					return nil, fmt.Errorf("floating-point modulo by zero")
   991  				}
   992  				return xf.Mod(y), nil
   993  			}
   994  		case Float:
   995  			switch y := y.(type) {
   996  			case Float:
   997  				if y == 0.0 {
   998  					return nil, fmt.Errorf("floating-point modulo by zero")
   999  				}
  1000  				return x.Mod(y), nil
  1001  			case Int:
  1002  				if y.Sign() == 0 {
  1003  					return nil, fmt.Errorf("floating-point modulo by zero")
  1004  				}
  1005  				yf, err := y.finiteFloat()
  1006  				if err != nil {
  1007  					return nil, err
  1008  				}
  1009  				return x.Mod(yf), nil
  1010  			}
  1011  		case String:
  1012  			return interpolate(string(x), y)
  1013  		}
  1014  
  1015  	case syntax.NOT_IN:
  1016  		z, err := Binary(syntax.IN, x, y)
  1017  		if err != nil {
  1018  			return nil, err
  1019  		}
  1020  		return !z.Truth(), nil
  1021  
  1022  	case syntax.IN:
  1023  		switch y := y.(type) {
  1024  		case *List:
  1025  			for _, elem := range y.elems {
  1026  				if eq, err := Equal(elem, x); err != nil {
  1027  					return nil, err
  1028  				} else if eq {
  1029  					return True, nil
  1030  				}
  1031  			}
  1032  			return False, nil
  1033  		case Tuple:
  1034  			for _, elem := range y {
  1035  				if eq, err := Equal(elem, x); err != nil {
  1036  					return nil, err
  1037  				} else if eq {
  1038  					return True, nil
  1039  				}
  1040  			}
  1041  			return False, nil
  1042  		case Mapping: // e.g. dict
  1043  			// Ignore error from Get as we cannot distinguish true
  1044  			// errors (value cycle, type error) from "key not found".
  1045  			_, found, _ := y.Get(x)
  1046  			return Bool(found), nil
  1047  		case *Set:
  1048  			ok, err := y.Has(x)
  1049  			return Bool(ok), err
  1050  		case String:
  1051  			needle, ok := x.(String)
  1052  			if !ok {
  1053  				return nil, fmt.Errorf("'in <string>' requires string as left operand, not %s", x.Type())
  1054  			}
  1055  			return Bool(strings.Contains(string(y), string(needle))), nil
  1056  		case Bytes:
  1057  			switch needle := x.(type) {
  1058  			case Bytes:
  1059  				return Bool(strings.Contains(string(y), string(needle))), nil
  1060  			case Int:
  1061  				var b byte
  1062  				if err := AsInt(needle, &b); err != nil {
  1063  					return nil, fmt.Errorf("int in bytes: %s", err)
  1064  				}
  1065  				return Bool(strings.IndexByte(string(y), b) >= 0), nil
  1066  			default:
  1067  				return nil, fmt.Errorf("'in bytes' requires bytes or int as left operand, not %s", x.Type())
  1068  			}
  1069  		case rangeValue:
  1070  			i, err := NumberToInt(x)
  1071  			if err != nil {
  1072  				return nil, fmt.Errorf("'in <range>' requires integer as left operand, not %s", x.Type())
  1073  			}
  1074  			return Bool(y.contains(i)), nil
  1075  		}
  1076  
  1077  	case syntax.PIPE:
  1078  		switch x := x.(type) {
  1079  		case Int:
  1080  			if y, ok := y.(Int); ok {
  1081  				return x.Or(y), nil
  1082  			}
  1083  
  1084  		case *Dict: // union
  1085  			if y, ok := y.(*Dict); ok {
  1086  				return x.Union(y), nil
  1087  			}
  1088  
  1089  		case *Set: // union
  1090  			if y, ok := y.(*Set); ok {
  1091  				iter := Iterate(y)
  1092  				defer iter.Done()
  1093  				return x.Union(iter)
  1094  			}
  1095  		}
  1096  
  1097  	case syntax.AMP:
  1098  		switch x := x.(type) {
  1099  		case Int:
  1100  			if y, ok := y.(Int); ok {
  1101  				return x.And(y), nil
  1102  			}
  1103  		case *Set: // intersection
  1104  			if y, ok := y.(*Set); ok {
  1105  				iter := y.Iterate()
  1106  				defer iter.Done()
  1107  				return x.Intersection(iter)
  1108  			}
  1109  		}
  1110  
  1111  	case syntax.CIRCUMFLEX:
  1112  		switch x := x.(type) {
  1113  		case Int:
  1114  			if y, ok := y.(Int); ok {
  1115  				return x.Xor(y), nil
  1116  			}
  1117  		case *Set: // symmetric difference
  1118  			if y, ok := y.(*Set); ok {
  1119  				iter := y.Iterate()
  1120  				defer iter.Done()
  1121  				return x.SymmetricDifference(iter)
  1122  			}
  1123  		}
  1124  
  1125  	case syntax.LTLT, syntax.GTGT:
  1126  		if x, ok := x.(Int); ok {
  1127  			y, err := AsInt32(y)
  1128  			if err != nil {
  1129  				return nil, err
  1130  			}
  1131  			if y < 0 {
  1132  				return nil, fmt.Errorf("negative shift count: %v", y)
  1133  			}
  1134  			if op == syntax.LTLT {
  1135  				if y >= 512 {
  1136  					return nil, fmt.Errorf("shift count too large: %v", y)
  1137  				}
  1138  				return x.Lsh(uint(y)), nil
  1139  			} else {
  1140  				return x.Rsh(uint(y)), nil
  1141  			}
  1142  		}
  1143  
  1144  	default:
  1145  		// unknown operator
  1146  		goto unknown
  1147  	}
  1148  
  1149  	// user-defined types
  1150  	// (nil, nil) => unhandled
  1151  	if x, ok := x.(HasBinary); ok {
  1152  		z, err := x.Binary(op, y, Left)
  1153  		if z != nil || err != nil {
  1154  			return z, err
  1155  		}
  1156  	}
  1157  	if y, ok := y.(HasBinary); ok {
  1158  		z, err := y.Binary(op, x, Right)
  1159  		if z != nil || err != nil {
  1160  			return z, err
  1161  		}
  1162  	}
  1163  
  1164  	// unsupported operand types
  1165  unknown:
  1166  	return nil, fmt.Errorf("unknown binary op: %s %s %s", x.Type(), op, y.Type())
  1167  }
  1168  
  1169  // It's always possible to overeat in small bites but we'll
  1170  // try to stop someone swallowing the world in one gulp.
  1171  const maxAlloc = 1 << 30
  1172  
  1173  func tupleRepeat(elems Tuple, n Int) (Tuple, error) {
  1174  	if len(elems) == 0 {
  1175  		return nil, nil
  1176  	}
  1177  	i, err := AsInt32(n)
  1178  	if err != nil {
  1179  		return nil, fmt.Errorf("repeat count %s too large", n)
  1180  	}
  1181  	if i < 1 {
  1182  		return nil, nil
  1183  	}
  1184  	// Inv: i > 0, len > 0
  1185  	sz := len(elems) * i
  1186  	if sz < 0 || sz >= maxAlloc { // sz < 0 => overflow
  1187  		// Don't print sz.
  1188  		return nil, fmt.Errorf("excessive repeat (%d * %d elements)", len(elems), i)
  1189  	}
  1190  	res := make([]Value, sz)
  1191  	// copy elems into res, doubling each time
  1192  	x := copy(res, elems)
  1193  	for x < len(res) {
  1194  		copy(res[x:], res[:x])
  1195  		x *= 2
  1196  	}
  1197  	return res, nil
  1198  }
  1199  
  1200  func bytesRepeat(b Bytes, n Int) (Bytes, error) {
  1201  	res, err := stringRepeat(String(b), n)
  1202  	return Bytes(res), err
  1203  }
  1204  
  1205  func stringRepeat(s String, n Int) (String, error) {
  1206  	if s == "" {
  1207  		return "", nil
  1208  	}
  1209  	i, err := AsInt32(n)
  1210  	if err != nil {
  1211  		return "", fmt.Errorf("repeat count %s too large", n)
  1212  	}
  1213  	if i < 1 {
  1214  		return "", nil
  1215  	}
  1216  	// Inv: i > 0, len > 0
  1217  	sz := len(s) * i
  1218  	if sz < 0 || sz >= maxAlloc { // sz < 0 => overflow
  1219  		// Don't print sz.
  1220  		return "", fmt.Errorf("excessive repeat (%d * %d elements)", len(s), i)
  1221  	}
  1222  	return String(strings.Repeat(string(s), i)), nil
  1223  }
  1224  
  1225  // Call calls the function fn with the specified positional and keyword arguments.
  1226  func Call(thread *Thread, fn Value, args Tuple, kwargs []Tuple) (Value, error) {
  1227  	c, ok := fn.(Callable)
  1228  	if !ok {
  1229  		return nil, fmt.Errorf("invalid call of non-function (%s)", fn.Type())
  1230  	}
  1231  
  1232  	// Allocate and push a new frame.
  1233  	var fr *frame
  1234  	// Optimization: use slack portion of thread.stack
  1235  	// slice as a freelist of empty frames.
  1236  	if n := len(thread.stack); n < cap(thread.stack) {
  1237  		fr = thread.stack[n : n+1][0]
  1238  	}
  1239  	if fr == nil {
  1240  		fr = new(frame)
  1241  	}
  1242  
  1243  	if thread.stack == nil {
  1244  		// one-time initialization of thread
  1245  		if thread.maxSteps == 0 {
  1246  			thread.maxSteps-- // (MaxUint64)
  1247  		}
  1248  	}
  1249  
  1250  	thread.stack = append(thread.stack, fr) // push
  1251  
  1252  	fr.callable = c
  1253  
  1254  	thread.beginProfSpan()
  1255  
  1256  	// Use defer to ensure that panics from built-ins
  1257  	// pass through the interpreter without leaving
  1258  	// it in a bad state.
  1259  	defer func() {
  1260  		thread.endProfSpan()
  1261  
  1262  		// clear out any references
  1263  		// TODO(adonovan): opt: zero fr.Locals and
  1264  		// reuse it if it is large enough.
  1265  		*fr = frame{}
  1266  
  1267  		thread.stack = thread.stack[:len(thread.stack)-1] // pop
  1268  	}()
  1269  
  1270  	result, err := c.CallInternal(thread, args, kwargs)
  1271  
  1272  	// Sanity check: nil is not a valid Starlark value.
  1273  	if result == nil && err == nil {
  1274  		err = fmt.Errorf("internal error: nil (not None) returned from %s", fn)
  1275  	}
  1276  
  1277  	// Always return an EvalError with an accurate frame.
  1278  	if err != nil {
  1279  		if _, ok := err.(*EvalError); !ok {
  1280  			err = thread.evalError(err)
  1281  		}
  1282  	}
  1283  
  1284  	return result, err
  1285  }
  1286  
  1287  func slice(x, lo, hi, step_ Value) (Value, error) {
  1288  	sliceable, ok := x.(Sliceable)
  1289  	if !ok {
  1290  		return nil, fmt.Errorf("invalid slice operand %s", x.Type())
  1291  	}
  1292  
  1293  	n := sliceable.Len()
  1294  	step := 1
  1295  	if step_ != None {
  1296  		var err error
  1297  		step, err = AsInt32(step_)
  1298  		if err != nil {
  1299  			return nil, fmt.Errorf("invalid slice step: %s", err)
  1300  		}
  1301  		if step == 0 {
  1302  			return nil, fmt.Errorf("zero is not a valid slice step")
  1303  		}
  1304  	}
  1305  
  1306  	// TODO(adonovan): opt: preallocate result array.
  1307  
  1308  	var start, end int
  1309  	if step > 0 {
  1310  		// positive stride
  1311  		// default indices are [0:n].
  1312  		var err error
  1313  		start, end, err = indices(lo, hi, n)
  1314  		if err != nil {
  1315  			return nil, err
  1316  		}
  1317  
  1318  		if end < start {
  1319  			end = start // => empty result
  1320  		}
  1321  	} else {
  1322  		// negative stride
  1323  		// default indices are effectively [n-1:-1], though to
  1324  		// get this effect using explicit indices requires
  1325  		// [n-1:-1-n:-1] because of the treatment of -ve values.
  1326  		start = n - 1
  1327  		if err := asIndex(lo, n, &start); err != nil {
  1328  			return nil, fmt.Errorf("invalid start index: %s", err)
  1329  		}
  1330  		if start >= n {
  1331  			start = n - 1
  1332  		}
  1333  
  1334  		end = -1
  1335  		if err := asIndex(hi, n, &end); err != nil {
  1336  			return nil, fmt.Errorf("invalid end index: %s", err)
  1337  		}
  1338  		if end < -1 {
  1339  			end = -1
  1340  		}
  1341  
  1342  		if start < end {
  1343  			start = end // => empty result
  1344  		}
  1345  	}
  1346  
  1347  	return sliceable.Slice(start, end, step), nil
  1348  }
  1349  
  1350  // From Hacker's Delight, section 2.8.
  1351  func signum64(x int64) int { return int(uint64(x>>63) | uint64(-x)>>63) }
  1352  func signum(x int) int     { return signum64(int64(x)) }
  1353  
  1354  // indices converts start_ and end_ to indices in the range [0:len].
  1355  // The start index defaults to 0 and the end index defaults to len.
  1356  // An index -len < i < 0 is treated like i+len.
  1357  // All other indices outside the range are clamped to the nearest value in the range.
  1358  // Beware: start may be greater than end.
  1359  // This function is suitable only for slices with positive strides.
  1360  func indices(start_, end_ Value, len int) (start, end int, err error) {
  1361  	start = 0
  1362  	if err := asIndex(start_, len, &start); err != nil {
  1363  		return 0, 0, fmt.Errorf("invalid start index: %s", err)
  1364  	}
  1365  	// Clamp to [0:len].
  1366  	if start < 0 {
  1367  		start = 0
  1368  	} else if start > len {
  1369  		start = len
  1370  	}
  1371  
  1372  	end = len
  1373  	if err := asIndex(end_, len, &end); err != nil {
  1374  		return 0, 0, fmt.Errorf("invalid end index: %s", err)
  1375  	}
  1376  	// Clamp to [0:len].
  1377  	if end < 0 {
  1378  		end = 0
  1379  	} else if end > len {
  1380  		end = len
  1381  	}
  1382  
  1383  	return start, end, nil
  1384  }
  1385  
  1386  // asIndex sets *result to the integer value of v, adding len to it
  1387  // if it is negative.  If v is nil or None, *result is unchanged.
  1388  func asIndex(v Value, len int, result *int) error {
  1389  	if v != nil && v != None {
  1390  		var err error
  1391  		*result, err = AsInt32(v)
  1392  		if err != nil {
  1393  			return err
  1394  		}
  1395  		if *result < 0 {
  1396  			*result += len
  1397  		}
  1398  	}
  1399  	return nil
  1400  }
  1401  
  1402  // setArgs sets the values of the formal parameters of function fn in
  1403  // based on the actual parameter values in args and kwargs.
  1404  func setArgs(locals []Value, fn *Function, args Tuple, kwargs []Tuple) error {
  1405  
  1406  	// This is the general schema of a function:
  1407  	//
  1408  	//   def f(p1, p2=dp2, p3=dp3, *args, k1, k2=dk2, k3, **kwargs)
  1409  	//
  1410  	// The p parameters are non-kwonly, and may be specified positionally.
  1411  	// The k parameters are kwonly, and must be specified by name.
  1412  	// The defaults tuple is (dp2, dp3, mandatory, dk2, mandatory).
  1413  	//
  1414  	// Arguments are processed as follows:
  1415  	// - positional arguments are bound to a prefix of [p1, p2, p3].
  1416  	// - surplus positional arguments are bound to *args.
  1417  	// - keyword arguments are bound to any of {p1, p2, p3, k1, k2, k3};
  1418  	//   duplicate bindings are rejected.
  1419  	// - surplus keyword arguments are bound to **kwargs.
  1420  	// - defaults are bound to each parameter from p2 to k3 if no value was set.
  1421  	//   default values come from the tuple above.
  1422  	//   It is an error if the tuple entry for an unset parameter is 'mandatory'.
  1423  
  1424  	// Nullary function?
  1425  	if fn.NumParams() == 0 {
  1426  		if nactual := len(args) + len(kwargs); nactual > 0 {
  1427  			return fmt.Errorf("function %s accepts no arguments (%d given)", fn.Name(), nactual)
  1428  		}
  1429  		return nil
  1430  	}
  1431  
  1432  	cond := func(x bool, y, z interface{}) interface{} {
  1433  		if x {
  1434  			return y
  1435  		}
  1436  		return z
  1437  	}
  1438  
  1439  	// nparams is the number of ordinary parameters (sans *args and **kwargs).
  1440  	nparams := fn.NumParams()
  1441  	var kwdict *Dict
  1442  	if fn.HasKwargs() {
  1443  		nparams--
  1444  		kwdict = new(Dict)
  1445  		locals[nparams] = kwdict
  1446  	}
  1447  	if fn.HasVarargs() {
  1448  		nparams--
  1449  	}
  1450  
  1451  	// nonkwonly is the number of non-kwonly parameters.
  1452  	nonkwonly := nparams - fn.NumKwonlyParams()
  1453  
  1454  	// Too many positional args?
  1455  	n := len(args)
  1456  	if len(args) > nonkwonly {
  1457  		if !fn.HasVarargs() {
  1458  			return fmt.Errorf("function %s accepts %s%d positional argument%s (%d given)",
  1459  				fn.Name(),
  1460  				cond(len(fn.defaults) > fn.NumKwonlyParams(), "at most ", ""),
  1461  				nonkwonly,
  1462  				cond(nonkwonly == 1, "", "s"),
  1463  				len(args))
  1464  		}
  1465  		n = nonkwonly
  1466  	}
  1467  
  1468  	// Bind positional arguments to non-kwonly parameters.
  1469  	for i := 0; i < n; i++ {
  1470  		locals[i] = args[i]
  1471  	}
  1472  
  1473  	// Bind surplus positional arguments to *args parameter.
  1474  	if fn.HasVarargs() {
  1475  		tuple := make(Tuple, len(args)-n)
  1476  		for i := n; i < len(args); i++ {
  1477  			tuple[i-n] = args[i]
  1478  		}
  1479  		locals[nparams] = tuple
  1480  	}
  1481  
  1482  	// Bind keyword arguments to parameters.
  1483  	paramIdents := fn.funcode.Locals[:nparams]
  1484  	for _, pair := range kwargs {
  1485  		k, v := pair[0].(String), pair[1]
  1486  		if i := findParam(paramIdents, string(k)); i >= 0 {
  1487  			if locals[i] != nil {
  1488  				return fmt.Errorf("function %s got multiple values for parameter %s", fn.Name(), k)
  1489  			}
  1490  			locals[i] = v
  1491  			continue
  1492  		}
  1493  		if kwdict == nil {
  1494  			return fmt.Errorf("function %s got an unexpected keyword argument %s", fn.Name(), k)
  1495  		}
  1496  		oldlen := kwdict.Len()
  1497  		kwdict.SetKey(k, v)
  1498  		if kwdict.Len() == oldlen {
  1499  			return fmt.Errorf("function %s got multiple values for parameter %s", fn.Name(), k)
  1500  		}
  1501  	}
  1502  
  1503  	// Are defaults required?
  1504  	if n < nparams || fn.NumKwonlyParams() > 0 {
  1505  		m := nparams - len(fn.defaults) // first default
  1506  
  1507  		// Report errors for missing required arguments.
  1508  		var missing []string
  1509  		var i int
  1510  		for i = n; i < m; i++ {
  1511  			if locals[i] == nil {
  1512  				missing = append(missing, paramIdents[i].Name)
  1513  			}
  1514  		}
  1515  
  1516  		// Bind default values to parameters.
  1517  		for ; i < nparams; i++ {
  1518  			if locals[i] == nil {
  1519  				dflt := fn.defaults[i-m]
  1520  				if _, ok := dflt.(mandatory); ok {
  1521  					missing = append(missing, paramIdents[i].Name)
  1522  					continue
  1523  				}
  1524  				locals[i] = dflt
  1525  			}
  1526  		}
  1527  
  1528  		if missing != nil {
  1529  			return fmt.Errorf("function %s missing %d argument%s (%s)",
  1530  				fn.Name(), len(missing), cond(len(missing) > 1, "s", ""), strings.Join(missing, ", "))
  1531  		}
  1532  	}
  1533  	return nil
  1534  }
  1535  
  1536  func findParam(params []compile.Binding, name string) int {
  1537  	for i, param := range params {
  1538  		if param.Name == name {
  1539  			return i
  1540  		}
  1541  	}
  1542  	return -1
  1543  }
  1544  
  1545  // https://github.com/google/starlark-go/blob/master/doc/spec.md#string-interpolation
  1546  func interpolate(format string, x Value) (Value, error) {
  1547  	buf := new(strings.Builder)
  1548  	index := 0
  1549  	nargs := 1
  1550  	if tuple, ok := x.(Tuple); ok {
  1551  		nargs = len(tuple)
  1552  	}
  1553  	for {
  1554  		i := strings.IndexByte(format, '%')
  1555  		if i < 0 {
  1556  			buf.WriteString(format)
  1557  			break
  1558  		}
  1559  		buf.WriteString(format[:i])
  1560  		format = format[i+1:]
  1561  
  1562  		if format != "" && format[0] == '%' {
  1563  			buf.WriteByte('%')
  1564  			format = format[1:]
  1565  			continue
  1566  		}
  1567  
  1568  		var arg Value
  1569  		if format != "" && format[0] == '(' {
  1570  			// keyword argument: %(name)s.
  1571  			format = format[1:]
  1572  			j := strings.IndexByte(format, ')')
  1573  			if j < 0 {
  1574  				return nil, fmt.Errorf("incomplete format key")
  1575  			}
  1576  			key := format[:j]
  1577  			if dict, ok := x.(Mapping); !ok {
  1578  				return nil, fmt.Errorf("format requires a mapping")
  1579  			} else if v, found, _ := dict.Get(String(key)); found {
  1580  				arg = v
  1581  			} else {
  1582  				return nil, fmt.Errorf("key not found: %s", key)
  1583  			}
  1584  			format = format[j+1:]
  1585  		} else {
  1586  			// positional argument: %s.
  1587  			if index >= nargs {
  1588  				return nil, fmt.Errorf("not enough arguments for format string")
  1589  			}
  1590  			if tuple, ok := x.(Tuple); ok {
  1591  				arg = tuple[index]
  1592  			} else {
  1593  				arg = x
  1594  			}
  1595  		}
  1596  
  1597  		// NOTE: Starlark does not support any of these optional Python features:
  1598  		// - optional conversion flags: [#0- +], etc.
  1599  		// - optional minimum field width (number or *).
  1600  		// - optional precision (.123 or *)
  1601  		// - optional length modifier
  1602  
  1603  		// conversion type
  1604  		if format == "" {
  1605  			return nil, fmt.Errorf("incomplete format")
  1606  		}
  1607  		switch c := format[0]; c {
  1608  		case 's', 'r':
  1609  			if str, ok := AsString(arg); ok && c == 's' {
  1610  				buf.WriteString(str)
  1611  			} else {
  1612  				writeValue(buf, arg, nil)
  1613  			}
  1614  		case 'd', 'i', 'o', 'x', 'X':
  1615  			i, err := NumberToInt(arg)
  1616  			if err != nil {
  1617  				return nil, fmt.Errorf("%%%c format requires integer: %v", c, err)
  1618  			}
  1619  			switch c {
  1620  			case 'd', 'i':
  1621  				fmt.Fprintf(buf, "%d", i)
  1622  			case 'o':
  1623  				fmt.Fprintf(buf, "%o", i)
  1624  			case 'x':
  1625  				fmt.Fprintf(buf, "%x", i)
  1626  			case 'X':
  1627  				fmt.Fprintf(buf, "%X", i)
  1628  			}
  1629  		case 'e', 'f', 'g', 'E', 'F', 'G':
  1630  			f, ok := AsFloat(arg)
  1631  			if !ok {
  1632  				return nil, fmt.Errorf("%%%c format requires float, not %s", c, arg.Type())
  1633  			}
  1634  			Float(f).format(buf, c)
  1635  		case 'c':
  1636  			switch arg := arg.(type) {
  1637  			case Int:
  1638  				// chr(int)
  1639  				r, err := AsInt32(arg)
  1640  				if err != nil || r < 0 || r > unicode.MaxRune {
  1641  					return nil, fmt.Errorf("%%c format requires a valid Unicode code point, got %s", arg)
  1642  				}
  1643  				buf.WriteRune(rune(r))
  1644  			case String:
  1645  				r, size := utf8.DecodeRuneInString(string(arg))
  1646  				if size != len(arg) || len(arg) == 0 {
  1647  					return nil, fmt.Errorf("%%c format requires a single-character string")
  1648  				}
  1649  				buf.WriteRune(r)
  1650  			default:
  1651  				return nil, fmt.Errorf("%%c format requires int or single-character string, not %s", arg.Type())
  1652  			}
  1653  		case '%':
  1654  			buf.WriteByte('%')
  1655  		default:
  1656  			return nil, fmt.Errorf("unknown conversion %%%c", c)
  1657  		}
  1658  		format = format[1:]
  1659  		index++
  1660  	}
  1661  
  1662  	if index < nargs {
  1663  		return nil, fmt.Errorf("too many arguments for format string")
  1664  	}
  1665  
  1666  	return String(buf.String()), nil
  1667  }