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