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