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