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 }