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