github.com/k14s/starlark-go@v0.0.0-20200720175618-3a5c849cc368/starlark/value.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 provides a Starlark interpreter. 6 // 7 // Starlark values are represented by the Value interface. 8 // The following built-in Value types are known to the evaluator: 9 // 10 // NoneType -- NoneType 11 // Bool -- bool 12 // Int -- int 13 // Float -- float 14 // String -- string 15 // *List -- list 16 // Tuple -- tuple 17 // *Dict -- dict 18 // *Set -- set 19 // *Function -- function (implemented in Starlark) 20 // *Builtin -- builtin_function_or_method (function or method implemented in Go) 21 // 22 // Client applications may define new data types that satisfy at least 23 // the Value interface. Such types may provide additional operations by 24 // implementing any of these optional interfaces: 25 // 26 // Callable -- value is callable like a function 27 // Comparable -- value defines its own comparison operations 28 // Iterable -- value is iterable using 'for' loops 29 // Sequence -- value is iterable sequence of known length 30 // Indexable -- value is sequence with efficient random access 31 // Mapping -- value maps from keys to values, like a dictionary 32 // HasBinary -- value defines binary operations such as * and + 33 // HasAttrs -- value has readable fields or methods x.f 34 // HasSetField -- value has settable fields x.f 35 // HasSetIndex -- value supports element update using x[i]=y 36 // HasSetKey -- value supports map update using x[k]=v 37 // HasUnary -- value defines unary operations such as + and - 38 // 39 // Client applications may also define domain-specific functions in Go 40 // and make them available to Starlark programs. Use NewBuiltin to 41 // construct a built-in value that wraps a Go function. The 42 // implementation of the Go function may use UnpackArgs to make sense of 43 // the positional and keyword arguments provided by the caller. 44 // 45 // Starlark's None value is not equal to Go's nil, but nil may be 46 // assigned to a Starlark Value. Be careful to avoid allowing Go nil 47 // values to leak into Starlark data structures. 48 // 49 // The Compare operation requires two arguments of the same 50 // type, but this constraint cannot be expressed in Go's type system. 51 // (This is the classic "binary method problem".) 52 // So, each Value type's CompareSameType method is a partial function 53 // that compares a value only against others of the same type. 54 // Use the package's standalone Compare (or Equal) function to compare 55 // an arbitrary pair of values. 56 // 57 // To parse and evaluate a Starlark source file, use ExecFile. The Eval 58 // function evaluates a single expression. All evaluator functions 59 // require a Thread parameter which defines the "thread-local storage" 60 // of a Starlark thread and may be used to plumb application state 61 // through Sklyark code and into callbacks. When evaluation fails it 62 // returns an EvalError from which the application may obtain a 63 // backtrace of active Starlark calls. 64 // 65 package starlark // import "github.com/k14s/starlark-go/starlark" 66 67 // This file defines the data types of Starlark and their basic operations. 68 69 import ( 70 "fmt" 71 "math" 72 "math/big" 73 "reflect" 74 "strconv" 75 "strings" 76 "unicode/utf8" 77 78 "github.com/k14s/starlark-go/internal/compile" 79 "github.com/k14s/starlark-go/syntax" 80 ) 81 82 // Value is a value in the Starlark interpreter. 83 type Value interface { 84 // String returns the string representation of the value. 85 // Starlark string values are quoted as if by Python's repr. 86 String() string 87 88 // Type returns a short string describing the value's type. 89 Type() string 90 91 // Freeze causes the value, and all values transitively 92 // reachable from it through collections and closures, to be 93 // marked as frozen. All subsequent mutations to the data 94 // structure through this API will fail dynamically, making the 95 // data structure immutable and safe for publishing to other 96 // Starlark interpreters running concurrently. 97 Freeze() 98 99 // Truth returns the truth value of an object. 100 Truth() Bool 101 102 // Hash returns a function of x such that Equals(x, y) => Hash(x) == Hash(y). 103 // Hash may fail if the value's type is not hashable, or if the value 104 // contains a non-hashable value. The hash is used only by dictionaries and 105 // is not exposed to the Starlark program. 106 Hash() (uint32, error) 107 } 108 109 // A Comparable is a value that defines its own equivalence relation and 110 // perhaps ordered comparisons. 111 type Comparable interface { 112 Value 113 // CompareSameType compares one value to another of the same Type(). 114 // The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE. 115 // CompareSameType returns an error if an ordered comparison was 116 // requested for a type that does not support it. 117 // 118 // Implementations that recursively compare subcomponents of 119 // the value should use the CompareDepth function, not Compare, to 120 // avoid infinite recursion on cyclic structures. 121 // 122 // The depth parameter is used to bound comparisons of cyclic 123 // data structures. Implementations should decrement depth 124 // before calling CompareDepth and should return an error if depth 125 // < 1. 126 // 127 // Client code should not call this method. Instead, use the 128 // standalone Compare or Equals functions, which are defined for 129 // all pairs of operands. 130 CompareSameType(op syntax.Token, y Value, depth int) (bool, error) 131 } 132 133 var ( 134 _ Comparable = None 135 _ Comparable = Int{} 136 _ Comparable = False 137 _ Comparable = Float(0) 138 _ Comparable = String("") 139 _ Comparable = (*Dict)(nil) 140 _ Comparable = (*List)(nil) 141 _ Comparable = Tuple(nil) 142 _ Comparable = (*Set)(nil) 143 ) 144 145 // A Callable value f may be the operand of a function call, f(x). 146 // 147 // Clients should use the Call function, never the CallInternal method. 148 type Callable interface { 149 Value 150 Name() string 151 CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error) 152 } 153 154 type callableWithPosition interface { 155 Callable 156 Position() syntax.Position 157 } 158 159 var ( 160 _ Callable = (*Builtin)(nil) 161 _ Callable = (*Function)(nil) 162 _ callableWithPosition = (*Function)(nil) 163 ) 164 165 // An Iterable abstracts a sequence of values. 166 // An iterable value may be iterated over by a 'for' loop or used where 167 // any other Starlark iterable is allowed. Unlike a Sequence, the length 168 // of an Iterable is not necessarily known in advance of iteration. 169 type Iterable interface { 170 Value 171 Iterate() Iterator // must be followed by call to Iterator.Done 172 } 173 174 // A Sequence is a sequence of values of known length. 175 type Sequence interface { 176 Iterable 177 Len() int 178 } 179 180 var ( 181 _ Sequence = (*Dict)(nil) 182 _ Sequence = (*Set)(nil) 183 ) 184 185 // An Indexable is a sequence of known length that supports efficient random access. 186 // It is not necessarily iterable. 187 type Indexable interface { 188 Value 189 Index(i int) Value // requires 0 <= i < Len() 190 Len() int 191 } 192 193 // A Sliceable is a sequence that can be cut into pieces with the slice operator (x[i:j:step]). 194 // 195 // All native indexable objects are sliceable. 196 // This is a separate interface for backwards-compatibility. 197 type Sliceable interface { 198 Indexable 199 // For positive strides (step > 0), 0 <= start <= end <= n. 200 // For negative strides (step < 0), -1 <= end <= start < n. 201 // The caller must ensure that the start and end indices are valid 202 // and that step is non-zero. 203 Slice(start, end, step int) Value 204 } 205 206 // A HasSetIndex is an Indexable value whose elements may be assigned (x[i] = y). 207 // 208 // The implementation should not add Len to a negative index as the 209 // evaluator does this before the call. 210 type HasSetIndex interface { 211 Indexable 212 SetIndex(index int, v Value) error 213 } 214 215 var ( 216 _ HasSetIndex = (*List)(nil) 217 _ Indexable = Tuple(nil) 218 _ Indexable = String("") 219 _ Sliceable = Tuple(nil) 220 _ Sliceable = String("") 221 _ Sliceable = (*List)(nil) 222 ) 223 224 // An Iterator provides a sequence of values to the caller. 225 // 226 // The caller must call Done when the iterator is no longer needed. 227 // Operations that modify a sequence will fail if it has active iterators. 228 // 229 // Example usage: 230 // 231 // iter := iterable.Iterator() 232 // defer iter.Done() 233 // var x Value 234 // for iter.Next(&x) { 235 // ... 236 // } 237 // 238 type Iterator interface { 239 // If the iterator is exhausted, Next returns false. 240 // Otherwise it sets *p to the current element of the sequence, 241 // advances the iterator, and returns true. 242 Next(p *Value) bool 243 Done() 244 } 245 246 // A Mapping is a mapping from keys to values, such as a dictionary. 247 // 248 // If a type satisfies both Mapping and Iterable, the iterator yields 249 // the keys of the mapping. 250 type Mapping interface { 251 Value 252 // Get returns the value corresponding to the specified key, 253 // or !found if the mapping does not contain the key. 254 // 255 // Get also defines the behavior of "v in mapping". 256 // The 'in' operator reports the 'found' component, ignoring errors. 257 Get(Value) (v Value, found bool, err error) 258 } 259 260 // An IterableMapping is a mapping that supports key enumeration. 261 type IterableMapping interface { 262 Mapping 263 Iterate() Iterator // see Iterable interface 264 Items() []Tuple // a new slice containing all key/value pairs 265 } 266 267 var _ IterableMapping = (*Dict)(nil) 268 269 // A HasSetKey supports map update using x[k]=v syntax, like a dictionary. 270 type HasSetKey interface { 271 Mapping 272 SetKey(k, v Value) error 273 } 274 275 var _ HasSetKey = (*Dict)(nil) 276 277 // A HasBinary value may be used as either operand of these binary operators: 278 // + - * / // % in not in | & ^ << >> 279 // 280 // The Side argument indicates whether the receiver is the left or right operand. 281 // 282 // An implementation may decline to handle an operation by returning (nil, nil). 283 // For this reason, clients should always call the standalone Binary(op, x, y) 284 // function rather than calling the method directly. 285 type HasBinary interface { 286 Value 287 Binary(op syntax.Token, y Value, side Side) (Value, error) 288 } 289 290 type Side bool 291 292 const ( 293 Left Side = false 294 Right Side = true 295 ) 296 297 // A HasUnary value may be used as the operand of these unary operators: 298 // + - ~ 299 // 300 // An implementation may decline to handle an operation by returning (nil, nil). 301 // For this reason, clients should always call the standalone Unary(op, x) 302 // function rather than calling the method directly. 303 type HasUnary interface { 304 Value 305 Unary(op syntax.Token) (Value, error) 306 } 307 308 // A HasAttrs value has fields or methods that may be read by a dot expression (y = x.f). 309 // Attribute names may be listed using the built-in 'dir' function. 310 // 311 // For implementation convenience, a result of (nil, nil) from Attr is 312 // interpreted as a "no such field or method" error. Implementations are 313 // free to return a more precise error. 314 type HasAttrs interface { 315 Value 316 Attr(name string) (Value, error) // returns (nil, nil) if attribute not present 317 AttrNames() []string // callers must not modify the result. 318 } 319 320 var ( 321 _ HasAttrs = String("") 322 _ HasAttrs = new(List) 323 _ HasAttrs = new(Dict) 324 _ HasAttrs = new(Set) 325 ) 326 327 // A HasSetField value has fields that may be written by a dot expression (x.f = y). 328 // 329 // An implementation of SetField may return a NoSuchAttrError, 330 // in which case the runtime may augment the error message to 331 // warn of possible misspelling. 332 type HasSetField interface { 333 HasAttrs 334 SetField(name string, val Value) error 335 } 336 337 // A NoSuchAttrError may be returned by an implementation of 338 // HasAttrs.Attr or HasSetField.SetField to indicate that no such field 339 // exists. In that case the runtime may augment the error message to 340 // warn of possible misspelling. 341 type NoSuchAttrError string 342 343 func (e NoSuchAttrError) Error() string { return string(e) } 344 345 // NoneType is the type of None. Its only legal value is None. 346 // (We represent it as a number, not struct{}, so that None may be constant.) 347 type NoneType byte 348 349 const None = NoneType(0) 350 351 func (NoneType) String() string { return "None" } 352 func (NoneType) Type() string { return "NoneType" } 353 func (NoneType) Freeze() {} // immutable 354 func (NoneType) Truth() Bool { return False } 355 func (NoneType) Hash() (uint32, error) { return 0, nil } 356 func (NoneType) CompareSameType(op syntax.Token, y Value, depth int) (bool, error) { 357 return threeway(op, 0), nil 358 } 359 360 // Bool is the type of a Starlark bool. 361 type Bool bool 362 363 const ( 364 False Bool = false 365 True Bool = true 366 ) 367 368 func (b Bool) String() string { 369 if b { 370 return "True" 371 } else { 372 return "False" 373 } 374 } 375 func (b Bool) Type() string { return "bool" } 376 func (b Bool) Freeze() {} // immutable 377 func (b Bool) Truth() Bool { return b } 378 func (b Bool) Hash() (uint32, error) { return uint32(b2i(bool(b))), nil } 379 func (x Bool) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) { 380 y := y_.(Bool) 381 return threeway(op, b2i(bool(x))-b2i(bool(y))), nil 382 } 383 384 // Float is the type of a Starlark float. 385 type Float float64 386 387 func (f Float) String() string { return strconv.FormatFloat(float64(f), 'g', 6, 64) } 388 func (f Float) Type() string { return "float" } 389 func (f Float) Freeze() {} // immutable 390 func (f Float) Truth() Bool { return f != 0.0 } 391 func (f Float) Hash() (uint32, error) { 392 // Equal float and int values must yield the same hash. 393 // TODO(adonovan): opt: if f is non-integral, and thus not equal 394 // to any Int, we can avoid the Int conversion and use a cheaper hash. 395 if isFinite(float64(f)) { 396 return finiteFloatToInt(f).Hash() 397 } 398 return 1618033, nil // NaN, +/-Inf 399 } 400 401 func floor(f Float) Float { return Float(math.Floor(float64(f))) } 402 403 // isFinite reports whether f represents a finite rational value. 404 // It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0). 405 func isFinite(f float64) bool { 406 return math.Abs(f) <= math.MaxFloat64 407 } 408 409 func (x Float) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) { 410 y := y_.(Float) 411 switch op { 412 case syntax.EQL: 413 return x == y, nil 414 case syntax.NEQ: 415 return x != y, nil 416 case syntax.LE: 417 return x <= y, nil 418 case syntax.LT: 419 return x < y, nil 420 case syntax.GE: 421 return x >= y, nil 422 case syntax.GT: 423 return x > y, nil 424 } 425 panic(op) 426 } 427 428 func (f Float) rational() *big.Rat { return new(big.Rat).SetFloat64(float64(f)) } 429 430 // AsFloat returns the float64 value closest to x. 431 // The f result is undefined if x is not a float or int. 432 func AsFloat(x Value) (f float64, ok bool) { 433 switch x := x.(type) { 434 case Float: 435 return float64(x), true 436 case Int: 437 return float64(x.Float()), true 438 } 439 return 0, false 440 } 441 442 func (x Float) Mod(y Float) Float { return Float(math.Mod(float64(x), float64(y))) } 443 444 // Unary implements the operations +float and -float. 445 func (f Float) Unary(op syntax.Token) (Value, error) { 446 switch op { 447 case syntax.MINUS: 448 return -f, nil 449 case syntax.PLUS: 450 return +f, nil 451 } 452 return nil, nil 453 } 454 455 // String is the type of a Starlark string. 456 // 457 // A String encapsulates an an immutable sequence of bytes, 458 // but strings are not directly iterable. Instead, iterate 459 // over the result of calling one of these four methods: 460 // codepoints, codepoint_ords, elems, elem_ords. 461 // 462 // Warning: the contract of the Value interface's String method is that 463 // it returns the value printed in Starlark notation, 464 // so s.String() or fmt.Sprintf("%s", s) returns a quoted string. 465 // Use string(s) or s.GoString() or fmt.Sprintf("%#v", s) to obtain the raw contents 466 // of a Starlark string as a Go string. 467 type String string 468 469 func (s String) String() string { return strconv.Quote(string(s)) } 470 func (s String) GoString() string { return string(s) } 471 func (s String) Type() string { return "string" } 472 func (s String) Freeze() {} // immutable 473 func (s String) Truth() Bool { return len(s) > 0 } 474 func (s String) Hash() (uint32, error) { return hashString(string(s)), nil } 475 func (s String) Len() int { return len(s) } // bytes 476 func (s String) Index(i int) Value { return s[i : i+1] } 477 478 func (s String) Slice(start, end, step int) Value { 479 if step == 1 { 480 return s[start:end] 481 } 482 483 sign := signum(step) 484 var str []byte 485 for i := start; signum(end-i) == sign; i += step { 486 str = append(str, s[i]) 487 } 488 return String(str) 489 } 490 491 func (s String) Attr(name string) (Value, error) { return builtinAttr(s, name, stringMethods) } 492 func (s String) AttrNames() []string { return builtinAttrNames(stringMethods) } 493 494 func (x String) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) { 495 y := y_.(String) 496 return threeway(op, strings.Compare(string(x), string(y))), nil 497 } 498 499 func AsString(x Value) (string, bool) { v, ok := x.(String); return string(v), ok } 500 501 // A stringIterable is an iterable whose iterator yields a sequence of 502 // either Unicode code points or elements (bytes), 503 // either numerically or as successive substrings. 504 type stringIterable struct { 505 s String 506 ords bool 507 codepoints bool 508 } 509 510 var _ Iterable = (*stringIterable)(nil) 511 512 func (si stringIterable) String() string { 513 var etype string 514 if si.codepoints { 515 etype = "codepoint" 516 } else { 517 etype = "elem" 518 } 519 if si.ords { 520 return si.s.String() + "." + etype + "_ords()" 521 } else { 522 return si.s.String() + "." + etype + "s()" 523 } 524 } 525 func (si stringIterable) Type() string { 526 if si.codepoints { 527 return "codepoints" 528 } else { 529 return "elems" 530 } 531 } 532 func (si stringIterable) Freeze() {} // immutable 533 func (si stringIterable) Truth() Bool { return True } 534 func (si stringIterable) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", si.Type()) } 535 func (si stringIterable) Iterate() Iterator { return &stringIterator{si, 0} } 536 537 type stringIterator struct { 538 si stringIterable 539 i int 540 } 541 542 func (it *stringIterator) Next(p *Value) bool { 543 s := it.si.s[it.i:] 544 if s == "" { 545 return false 546 } 547 if it.si.codepoints { 548 r, sz := utf8.DecodeRuneInString(string(s)) 549 if !it.si.ords { 550 *p = s[:sz] 551 } else { 552 *p = MakeInt(int(r)) 553 } 554 it.i += sz 555 } else { 556 b := int(s[0]) 557 if !it.si.ords { 558 *p = s[:1] 559 } else { 560 *p = MakeInt(b) 561 } 562 it.i += 1 563 } 564 return true 565 } 566 567 func (*stringIterator) Done() {} 568 569 // A Function is a function defined by a Starlark def statement or lambda expression. 570 // The initialization behavior of a Starlark module is also represented by a Function. 571 type Function struct { 572 funcode *compile.Funcode 573 module *module 574 defaults Tuple 575 freevars Tuple 576 } 577 578 // A module is the dynamic counterpart to a Program. 579 // All functions in the same program share a module. 580 type module struct { 581 program *compile.Program 582 predeclared StringDict 583 globals []Value 584 constants []Value 585 } 586 587 // makeGlobalDict returns a new, unfrozen StringDict containing all global 588 // variables so far defined in the module. 589 func (m *module) makeGlobalDict() StringDict { 590 r := make(StringDict, len(m.program.Globals)) 591 for i, id := range m.program.Globals { 592 if v := m.globals[i]; v != nil { 593 r[id.Name] = v 594 } 595 } 596 return r 597 } 598 599 func (fn *Function) Name() string { return fn.funcode.Name } // "lambda" for anonymous functions 600 func (fn *Function) Doc() string { return fn.funcode.Doc } 601 func (fn *Function) Hash() (uint32, error) { return hashString(fn.funcode.Name), nil } 602 func (fn *Function) Freeze() { fn.defaults.Freeze(); fn.freevars.Freeze() } 603 func (fn *Function) String() string { return toString(fn) } 604 func (fn *Function) Type() string { return "function" } 605 func (fn *Function) Truth() Bool { return true } 606 607 // Globals returns a new, unfrozen StringDict containing all global 608 // variables so far defined in the function's module. 609 func (fn *Function) Globals() StringDict { return fn.module.makeGlobalDict() } 610 611 func (fn *Function) Position() syntax.Position { return fn.funcode.Pos } 612 func (fn *Function) NumParams() int { return fn.funcode.NumParams } 613 func (fn *Function) NumKwonlyParams() int { return fn.funcode.NumKwonlyParams } 614 615 // Param returns the name and position of the ith parameter, 616 // where 0 <= i < NumParams(). 617 // The *args and **kwargs parameters are at the end 618 // even if there were optional parameters after *args. 619 func (fn *Function) Param(i int) (string, syntax.Position) { 620 if i >= fn.NumParams() { 621 panic(i) 622 } 623 id := fn.funcode.Locals[i] 624 return id.Name, id.Pos 625 } 626 func (fn *Function) HasVarargs() bool { return fn.funcode.HasVarargs } 627 func (fn *Function) HasKwargs() bool { return fn.funcode.HasKwargs } 628 629 // A Builtin is a function implemented in Go. 630 type Builtin struct { 631 name string 632 fn func(thread *Thread, fn *Builtin, args Tuple, kwargs []Tuple) (Value, error) 633 recv Value // for bound methods (e.g. "".startswith) 634 } 635 636 func (b *Builtin) Name() string { return b.name } 637 func (b *Builtin) Freeze() { 638 if b.recv != nil { 639 b.recv.Freeze() 640 } 641 } 642 func (b *Builtin) Hash() (uint32, error) { 643 h := hashString(b.name) 644 if b.recv != nil { 645 h ^= 5521 646 } 647 return h, nil 648 } 649 func (b *Builtin) Receiver() Value { return b.recv } 650 func (b *Builtin) String() string { return toString(b) } 651 func (b *Builtin) Type() string { return "builtin_function_or_method" } 652 func (b *Builtin) CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error) { 653 return b.fn(thread, b, args, kwargs) 654 } 655 func (b *Builtin) Truth() Bool { return true } 656 657 // NewBuiltin returns a new 'builtin_function_or_method' value with the specified name 658 // and implementation. It compares unequal with all other values. 659 func NewBuiltin(name string, fn func(thread *Thread, fn *Builtin, args Tuple, kwargs []Tuple) (Value, error)) *Builtin { 660 return &Builtin{name: name, fn: fn} 661 } 662 663 // BindReceiver returns a new Builtin value representing a method 664 // closure, that is, a built-in function bound to a receiver value. 665 // 666 // In the example below, the value of f is the string.index 667 // built-in method bound to the receiver value "abc": 668 // 669 // f = "abc".index; f("a"); f("b") 670 // 671 // In the common case, the receiver is bound only during the call, 672 // but this still results in the creation of a temporary method closure: 673 // 674 // "abc".index("a") 675 // 676 func (b *Builtin) BindReceiver(recv Value) *Builtin { 677 return &Builtin{name: b.name, fn: b.fn, recv: recv} 678 } 679 680 // A *Dict represents a Starlark dictionary. 681 // The zero value of Dict is a valid empty dictionary. 682 // If you know the exact final number of entries, 683 // it is more efficient to call NewDict. 684 type Dict struct { 685 ht hashtable 686 } 687 688 // NewDict returns a set with initial space for 689 // at least size insertions before rehashing. 690 func NewDict(size int) *Dict { 691 dict := new(Dict) 692 dict.ht.init(size) 693 return dict 694 } 695 696 func (d *Dict) Clear() error { return d.ht.clear() } 697 func (d *Dict) Delete(k Value) (v Value, found bool, err error) { return d.ht.delete(k) } 698 func (d *Dict) Get(k Value) (v Value, found bool, err error) { return d.ht.lookup(k) } 699 func (d *Dict) Items() []Tuple { return d.ht.items() } 700 func (d *Dict) Keys() []Value { return d.ht.keys() } 701 func (d *Dict) Len() int { return int(d.ht.len) } 702 func (d *Dict) Iterate() Iterator { return d.ht.iterate() } 703 func (d *Dict) SetKey(k, v Value) error { return d.ht.insert(k, v) } 704 func (d *Dict) String() string { return toString(d) } 705 func (d *Dict) Type() string { return "dict" } 706 func (d *Dict) Freeze() { d.ht.freeze() } 707 func (d *Dict) Truth() Bool { return d.Len() > 0 } 708 func (d *Dict) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable type: dict") } 709 710 func (d *Dict) Attr(name string) (Value, error) { return builtinAttr(d, name, dictMethods) } 711 func (d *Dict) AttrNames() []string { return builtinAttrNames(dictMethods) } 712 713 func (x *Dict) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) { 714 y := y_.(*Dict) 715 switch op { 716 case syntax.EQL: 717 ok, err := dictsEqual(x, y, depth) 718 return ok, err 719 case syntax.NEQ: 720 ok, err := dictsEqual(x, y, depth) 721 return !ok, err 722 default: 723 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type()) 724 } 725 } 726 727 func dictsEqual(x, y *Dict, depth int) (bool, error) { 728 if x.Len() != y.Len() { 729 return false, nil 730 } 731 for _, xitem := range x.Items() { 732 key, xval := xitem[0], xitem[1] 733 734 if yval, found, _ := y.Get(key); !found { 735 return false, nil 736 } else if eq, err := EqualDepth(xval, yval, depth-1); err != nil { 737 return false, err 738 } else if !eq { 739 return false, nil 740 } 741 } 742 return true, nil 743 } 744 745 // A *List represents a Starlark list value. 746 type List struct { 747 elems []Value 748 frozen bool 749 itercount uint32 // number of active iterators (ignored if frozen) 750 } 751 752 // NewList returns a list containing the specified elements. 753 // Callers should not subsequently modify elems. 754 func NewList(elems []Value) *List { return &List{elems: elems} } 755 756 func (l *List) Freeze() { 757 if !l.frozen { 758 l.frozen = true 759 for _, elem := range l.elems { 760 elem.Freeze() 761 } 762 } 763 } 764 765 // checkMutable reports an error if the list should not be mutated. 766 // verb+" list" should describe the operation. 767 func (l *List) checkMutable(verb string) error { 768 if l.frozen { 769 return fmt.Errorf("cannot %s frozen list", verb) 770 } 771 if l.itercount > 0 { 772 return fmt.Errorf("cannot %s list during iteration", verb) 773 } 774 return nil 775 } 776 777 func (l *List) String() string { return toString(l) } 778 func (l *List) Type() string { return "list" } 779 func (l *List) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable type: list") } 780 func (l *List) Truth() Bool { return l.Len() > 0 } 781 func (l *List) Len() int { return len(l.elems) } 782 func (l *List) Index(i int) Value { return l.elems[i] } 783 784 func (l *List) Slice(start, end, step int) Value { 785 if step == 1 { 786 elems := append([]Value{}, l.elems[start:end]...) 787 return NewList(elems) 788 } 789 790 sign := signum(step) 791 var list []Value 792 for i := start; signum(end-i) == sign; i += step { 793 list = append(list, l.elems[i]) 794 } 795 return NewList(list) 796 } 797 798 func (l *List) Attr(name string) (Value, error) { return builtinAttr(l, name, listMethods) } 799 func (l *List) AttrNames() []string { return builtinAttrNames(listMethods) } 800 801 func (l *List) Iterate() Iterator { 802 if !l.frozen { 803 l.itercount++ 804 } 805 return &listIterator{l: l} 806 } 807 808 func (x *List) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) { 809 y := y_.(*List) 810 // It's tempting to check x == y as an optimization here, 811 // but wrong because a list containing NaN is not equal to itself. 812 return sliceCompare(op, x.elems, y.elems, depth) 813 } 814 815 func sliceCompare(op syntax.Token, x, y []Value, depth int) (bool, error) { 816 // Fast path: check length. 817 if len(x) != len(y) && (op == syntax.EQL || op == syntax.NEQ) { 818 return op == syntax.NEQ, nil 819 } 820 821 // Find first element that is not equal in both lists. 822 for i := 0; i < len(x) && i < len(y); i++ { 823 if eq, err := EqualDepth(x[i], y[i], depth-1); err != nil { 824 return false, err 825 } else if !eq { 826 switch op { 827 case syntax.EQL: 828 return false, nil 829 case syntax.NEQ: 830 return true, nil 831 default: 832 return CompareDepth(op, x[i], y[i], depth-1) 833 } 834 } 835 } 836 837 return threeway(op, len(x)-len(y)), nil 838 } 839 840 type listIterator struct { 841 l *List 842 i int 843 } 844 845 func (it *listIterator) Next(p *Value) bool { 846 if it.i < it.l.Len() { 847 *p = it.l.elems[it.i] 848 it.i++ 849 return true 850 } 851 return false 852 } 853 854 func (it *listIterator) Done() { 855 if !it.l.frozen { 856 it.l.itercount-- 857 } 858 } 859 860 func (l *List) SetIndex(i int, v Value) error { 861 if err := l.checkMutable("assign to element of"); err != nil { 862 return err 863 } 864 l.elems[i] = v 865 return nil 866 } 867 868 func (l *List) Append(v Value) error { 869 if err := l.checkMutable("append to"); err != nil { 870 return err 871 } 872 l.elems = append(l.elems, v) 873 return nil 874 } 875 876 func (l *List) Clear() error { 877 if err := l.checkMutable("clear"); err != nil { 878 return err 879 } 880 for i := range l.elems { 881 l.elems[i] = nil // aid GC 882 } 883 l.elems = l.elems[:0] 884 return nil 885 } 886 887 // A Tuple represents a Starlark tuple value. 888 type Tuple []Value 889 890 func (t Tuple) Len() int { return len(t) } 891 func (t Tuple) Index(i int) Value { return t[i] } 892 893 func (t Tuple) Slice(start, end, step int) Value { 894 if step == 1 { 895 return t[start:end] 896 } 897 898 sign := signum(step) 899 var tuple Tuple 900 for i := start; signum(end-i) == sign; i += step { 901 tuple = append(tuple, t[i]) 902 } 903 return tuple 904 } 905 906 func (t Tuple) Iterate() Iterator { return &tupleIterator{elems: t} } 907 func (t Tuple) Freeze() { 908 for _, elem := range t { 909 elem.Freeze() 910 } 911 } 912 func (t Tuple) String() string { return toString(t) } 913 func (t Tuple) Type() string { return "tuple" } 914 func (t Tuple) Truth() Bool { return len(t) > 0 } 915 916 func (x Tuple) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) { 917 y := y_.(Tuple) 918 return sliceCompare(op, x, y, depth) 919 } 920 921 func (t Tuple) Hash() (uint32, error) { 922 // Use same algorithm as Python. 923 var x, mult uint32 = 0x345678, 1000003 924 for _, elem := range t { 925 y, err := elem.Hash() 926 if err != nil { 927 return 0, err 928 } 929 x = x ^ y*mult 930 mult += 82520 + uint32(len(t)+len(t)) 931 } 932 return x, nil 933 } 934 935 type tupleIterator struct{ elems Tuple } 936 937 func (it *tupleIterator) Next(p *Value) bool { 938 if len(it.elems) > 0 { 939 *p = it.elems[0] 940 it.elems = it.elems[1:] 941 return true 942 } 943 return false 944 } 945 946 func (it *tupleIterator) Done() {} 947 948 // A Set represents a Starlark set value. 949 // The zero value of Set is a valid empty set. 950 // If you know the exact final number of elements, 951 // it is more efficient to call NewSet. 952 type Set struct { 953 ht hashtable // values are all None 954 } 955 956 // NewSet returns a dictionary with initial space for 957 // at least size insertions before rehashing. 958 func NewSet(size int) *Set { 959 set := new(Set) 960 set.ht.init(size) 961 return set 962 } 963 964 func (s *Set) Delete(k Value) (found bool, err error) { _, found, err = s.ht.delete(k); return } 965 func (s *Set) Clear() error { return s.ht.clear() } 966 func (s *Set) Has(k Value) (found bool, err error) { _, found, err = s.ht.lookup(k); return } 967 func (s *Set) Insert(k Value) error { return s.ht.insert(k, None) } 968 func (s *Set) Len() int { return int(s.ht.len) } 969 func (s *Set) Iterate() Iterator { return s.ht.iterate() } 970 func (s *Set) String() string { return toString(s) } 971 func (s *Set) Type() string { return "set" } 972 func (s *Set) elems() []Value { return s.ht.keys() } 973 func (s *Set) Freeze() { s.ht.freeze() } 974 func (s *Set) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable type: set") } 975 func (s *Set) Truth() Bool { return s.Len() > 0 } 976 977 func (s *Set) Attr(name string) (Value, error) { return builtinAttr(s, name, setMethods) } 978 func (s *Set) AttrNames() []string { return builtinAttrNames(setMethods) } 979 980 func (x *Set) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) { 981 y := y_.(*Set) 982 switch op { 983 case syntax.EQL: 984 ok, err := setsEqual(x, y, depth) 985 return ok, err 986 case syntax.NEQ: 987 ok, err := setsEqual(x, y, depth) 988 return !ok, err 989 default: 990 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type()) 991 } 992 } 993 994 func setsEqual(x, y *Set, depth int) (bool, error) { 995 if x.Len() != y.Len() { 996 return false, nil 997 } 998 for _, elem := range x.elems() { 999 if found, _ := y.Has(elem); !found { 1000 return false, nil 1001 } 1002 } 1003 return true, nil 1004 } 1005 1006 func (s *Set) Union(iter Iterator) (Value, error) { 1007 set := new(Set) 1008 for _, elem := range s.elems() { 1009 set.Insert(elem) // can't fail 1010 } 1011 var x Value 1012 for iter.Next(&x) { 1013 if err := set.Insert(x); err != nil { 1014 return nil, err 1015 } 1016 } 1017 return set, nil 1018 } 1019 1020 // toString returns the string form of value v. 1021 // It may be more efficient than v.String() for larger values. 1022 func toString(v Value) string { 1023 buf := new(strings.Builder) 1024 writeValue(buf, v, nil) 1025 return buf.String() 1026 } 1027 1028 // writeValue writes x to out. 1029 // 1030 // path is used to detect cycles. 1031 // It contains the list of *List and *Dict values we're currently printing. 1032 // (These are the only potentially cyclic structures.) 1033 // Callers should generally pass nil for path. 1034 // It is safe to re-use the same path slice for multiple calls. 1035 func writeValue(out *strings.Builder, x Value, path []Value) { 1036 switch x := x.(type) { 1037 case nil: 1038 out.WriteString("<nil>") // indicates a bug 1039 1040 case NoneType: 1041 out.WriteString("None") 1042 1043 case Int: 1044 out.WriteString(x.String()) 1045 1046 case Bool: 1047 if x { 1048 out.WriteString("True") 1049 } else { 1050 out.WriteString("False") 1051 } 1052 1053 case String: 1054 fmt.Fprintf(out, "%q", string(x)) 1055 1056 case *List: 1057 out.WriteByte('[') 1058 if pathContains(path, x) { 1059 out.WriteString("...") // list contains itself 1060 } else { 1061 for i, elem := range x.elems { 1062 if i > 0 { 1063 out.WriteString(", ") 1064 } 1065 writeValue(out, elem, append(path, x)) 1066 } 1067 } 1068 out.WriteByte(']') 1069 1070 case Tuple: 1071 out.WriteByte('(') 1072 for i, elem := range x { 1073 if i > 0 { 1074 out.WriteString(", ") 1075 } 1076 writeValue(out, elem, path) 1077 } 1078 if len(x) == 1 { 1079 out.WriteByte(',') 1080 } 1081 out.WriteByte(')') 1082 1083 case *Function: 1084 fmt.Fprintf(out, "<function %s>", x.Name()) 1085 1086 case *Builtin: 1087 if x.recv != nil { 1088 fmt.Fprintf(out, "<built-in method %s of %s value>", x.Name(), x.recv.Type()) 1089 } else { 1090 fmt.Fprintf(out, "<built-in function %s>", x.Name()) 1091 } 1092 1093 case *Dict: 1094 out.WriteByte('{') 1095 if pathContains(path, x) { 1096 out.WriteString("...") // dict contains itself 1097 } else { 1098 sep := "" 1099 for _, item := range x.Items() { 1100 k, v := item[0], item[1] 1101 out.WriteString(sep) 1102 writeValue(out, k, path) 1103 out.WriteString(": ") 1104 writeValue(out, v, append(path, x)) // cycle check 1105 sep = ", " 1106 } 1107 } 1108 out.WriteByte('}') 1109 1110 case *Set: 1111 out.WriteString("set([") 1112 for i, elem := range x.elems() { 1113 if i > 0 { 1114 out.WriteString(", ") 1115 } 1116 writeValue(out, elem, path) 1117 } 1118 out.WriteString("])") 1119 1120 default: 1121 out.WriteString(x.String()) 1122 } 1123 } 1124 1125 func pathContains(path []Value, x Value) bool { 1126 for _, y := range path { 1127 if x == y { 1128 return true 1129 } 1130 } 1131 return false 1132 } 1133 1134 const maxdepth = 10 1135 1136 // Equal reports whether two Starlark values are equal. 1137 func Equal(x, y Value) (bool, error) { 1138 if x, ok := x.(String); ok { 1139 return x == y, nil // fast path for an important special case 1140 } 1141 return EqualDepth(x, y, maxdepth) 1142 } 1143 1144 // EqualDepth reports whether two Starlark values are equal. 1145 // 1146 // Recursive comparisons by implementations of Value.CompareSameType 1147 // should use EqualDepth to prevent infinite recursion. 1148 func EqualDepth(x, y Value, depth int) (bool, error) { 1149 return CompareDepth(syntax.EQL, x, y, depth) 1150 } 1151 1152 // Compare compares two Starlark values. 1153 // The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE. 1154 // Compare returns an error if an ordered comparison was 1155 // requested for a type that does not support it. 1156 // 1157 // Recursive comparisons by implementations of Value.CompareSameType 1158 // should use CompareDepth to prevent infinite recursion. 1159 func Compare(op syntax.Token, x, y Value) (bool, error) { 1160 return CompareDepth(op, x, y, maxdepth) 1161 } 1162 1163 // CompareDepth compares two Starlark values. 1164 // The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE. 1165 // CompareDepth returns an error if an ordered comparison was 1166 // requested for a pair of values that do not support it. 1167 // 1168 // The depth parameter limits the maximum depth of recursion 1169 // in cyclic data structures. 1170 func CompareDepth(op syntax.Token, x, y Value, depth int) (bool, error) { 1171 if depth < 1 { 1172 return false, fmt.Errorf("comparison exceeded maximum recursion depth") 1173 } 1174 if sameType(x, y) { 1175 if xcomp, ok := x.(Comparable); ok { 1176 return xcomp.CompareSameType(op, y, depth) 1177 } 1178 1179 // use identity comparison 1180 switch op { 1181 case syntax.EQL: 1182 return x == y, nil 1183 case syntax.NEQ: 1184 return x != y, nil 1185 } 1186 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type()) 1187 } 1188 1189 // different types 1190 1191 // int/float ordered comparisons 1192 switch x := x.(type) { 1193 case Int: 1194 if y, ok := y.(Float); ok { 1195 if y != y { 1196 return false, nil // y is NaN 1197 } 1198 var cmp int 1199 if !math.IsInf(float64(y), 0) { 1200 cmp = x.rational().Cmp(y.rational()) // y is finite 1201 } else if y > 0 { 1202 cmp = -1 // y is +Inf 1203 } else { 1204 cmp = +1 // y is -Inf 1205 } 1206 return threeway(op, cmp), nil 1207 } 1208 case Float: 1209 if y, ok := y.(Int); ok { 1210 if x != x { 1211 return false, nil // x is NaN 1212 } 1213 var cmp int 1214 if !math.IsInf(float64(x), 0) { 1215 cmp = x.rational().Cmp(y.rational()) // x is finite 1216 } else if x > 0 { 1217 cmp = -1 // x is +Inf 1218 } else { 1219 cmp = +1 // x is -Inf 1220 } 1221 return threeway(op, cmp), nil 1222 } 1223 } 1224 1225 // All other values of different types compare unequal. 1226 switch op { 1227 case syntax.EQL: 1228 return false, nil 1229 case syntax.NEQ: 1230 return true, nil 1231 } 1232 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type()) 1233 } 1234 1235 func sameType(x, y Value) bool { 1236 return reflect.TypeOf(x) == reflect.TypeOf(y) || x.Type() == y.Type() 1237 } 1238 1239 // threeway interprets a three-way comparison value cmp (-1, 0, +1) 1240 // as a boolean comparison (e.g. x < y). 1241 func threeway(op syntax.Token, cmp int) bool { 1242 switch op { 1243 case syntax.EQL: 1244 return cmp == 0 1245 case syntax.NEQ: 1246 return cmp != 0 1247 case syntax.LE: 1248 return cmp <= 0 1249 case syntax.LT: 1250 return cmp < 0 1251 case syntax.GE: 1252 return cmp >= 0 1253 case syntax.GT: 1254 return cmp > 0 1255 } 1256 panic(op) 1257 } 1258 1259 func b2i(b bool) int { 1260 if b { 1261 return 1 1262 } else { 1263 return 0 1264 } 1265 } 1266 1267 // Len returns the length of a string or sequence value, 1268 // and -1 for all others. 1269 // 1270 // Warning: Len(x) >= 0 does not imply Iterate(x) != nil. 1271 // A string has a known length but is not directly iterable. 1272 func Len(x Value) int { 1273 switch x := x.(type) { 1274 case String: 1275 return x.Len() 1276 case Sequence: 1277 return x.Len() 1278 } 1279 return -1 1280 } 1281 1282 // Iterate return a new iterator for the value if iterable, nil otherwise. 1283 // If the result is non-nil, the caller must call Done when finished with it. 1284 // 1285 // Warning: Iterate(x) != nil does not imply Len(x) >= 0. 1286 // Some iterables may have unknown length. 1287 func Iterate(x Value) Iterator { 1288 if x, ok := x.(Iterable); ok { 1289 return x.Iterate() 1290 } 1291 return nil 1292 }