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