github.com/pygolin/runtime@v0.0.0-20201208210830-a62e3cd39798/core.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package runtime 16 17 import ( 18 "fmt" 19 "log" 20 "reflect" 21 "sync/atomic" 22 ) 23 24 var ( 25 logFatal = func(msg string) { log.Fatal(msg) } 26 // ThreadCount is the number of goroutines started with StartThread that 27 // have not yet joined. 28 ThreadCount int64 29 ) 30 31 // Abs returns the result of o.__abs__ and is equivalent to the Python 32 // expression "abs(o)". 33 func Abs(f *Frame, o *Object) (*Object, *BaseException) { 34 abs := o.typ.slots.Abs 35 if abs == nil { 36 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for abs(): '%s'", o.typ.Name())) 37 } 38 return abs.Fn(f, o) 39 } 40 41 // Add returns the result of adding v and w together according to the 42 // __add/radd__ operator. 43 func Add(f *Frame, v, w *Object) (*Object, *BaseException) { 44 return binaryOp(f, v, w, v.typ.slots.Add, v.typ.slots.RAdd, w.typ.slots.RAdd, "+") 45 } 46 47 // And returns the result of the bitwise and operator v & w according to 48 // __and/rand__. 49 func And(f *Frame, v, w *Object) (*Object, *BaseException) { 50 return binaryOp(f, v, w, v.typ.slots.And, v.typ.slots.RAnd, w.typ.slots.RAnd, "&") 51 } 52 53 // Assert raises an AssertionError if the given cond does not evaluate to true. 54 // If msg is not nil, it is converted to a string via ToStr() and passed as args 55 // to the raised exception. 56 func Assert(f *Frame, cond *Object, msg *Object) *BaseException { 57 result, raised := IsTrue(f, cond) 58 if raised == nil && !result { 59 if msg == nil { 60 raised = f.Raise(AssertionErrorType.ToObject(), nil, nil) 61 } else { 62 var s *Str 63 s, raised = ToStr(f, msg) 64 if raised == nil { 65 raised = f.RaiseType(AssertionErrorType, s.Value()) 66 } 67 } 68 } 69 return raised 70 } 71 72 // Compare implements a 3-way comparison which returns: 73 // 74 // -1 if v < w 75 // 0 if v == w 76 // 1 if v > w 77 // 78 // It closely resembles the behavior of CPython's do_cmp in object.c. 79 func Compare(f *Frame, v, w *Object) (*Object, *BaseException) { 80 cmp := v.typ.slots.Cmp 81 if v.typ == w.typ && cmp != nil { 82 return cmp.Fn(f, v, w) 83 } 84 r, raised := tryRichTo3wayCompare(f, v, w) 85 if r != NotImplemented { 86 return r, raised 87 } 88 r, raised = try3wayCompare(f, v, w) 89 if r != NotImplemented { 90 return r, raised 91 } 92 return NewInt(compareDefault(f, v, w)).ToObject(), nil 93 } 94 95 // Contains checks whether value is present in seq. It first checks the 96 // __contains__ method of seq and, if that is not available, attempts to find 97 // value by iteration over seq. It is equivalent to the Python expression 98 // "value in seq". 99 func Contains(f *Frame, seq, value *Object) (bool, *BaseException) { 100 if contains := seq.typ.slots.Contains; contains != nil { 101 ret, raised := contains.Fn(f, seq, value) 102 if raised != nil { 103 return false, raised 104 } 105 return IsTrue(f, ret) 106 } 107 iter, raised := Iter(f, seq) 108 if raised != nil { 109 return false, raised 110 } 111 o, raised := Next(f, iter) 112 for ; raised == nil; o, raised = Next(f, iter) { 113 eq, raised := Eq(f, o, value) 114 if raised != nil { 115 return false, raised 116 } 117 if ret, raised := IsTrue(f, eq); raised != nil { 118 return false, raised 119 } else if ret { 120 return true, nil 121 } 122 } 123 if !raised.isInstance(StopIterationType) { 124 return false, raised 125 } 126 f.RestoreExc(nil, nil) 127 return false, nil 128 } 129 130 // DelAttr removes the attribute of o given by name. Equivalent to the Python 131 // expression delattr(o, name). 132 func DelAttr(f *Frame, o *Object, name *Str) *BaseException { 133 delAttr := o.typ.slots.DelAttr 134 if delAttr == nil { 135 return f.RaiseType(SystemErrorType, fmt.Sprintf("'%s' object has no __delattr__ method", o.typ.Name())) 136 } 137 return delAttr.Fn(f, o, name) 138 } 139 140 // DelVar removes the named variable from the given namespace dictionary such 141 // as a module globals dict. 142 func DelVar(f *Frame, namespace *Dict, name *Str) *BaseException { 143 deleted, raised := namespace.DelItem(f, name.ToObject()) 144 if raised != nil { 145 return raised 146 } 147 if !deleted { 148 return f.RaiseType(NameErrorType, fmt.Sprintf("name '%s' is not defined", name.Value())) 149 } 150 return nil 151 } 152 153 // DelItem performs the operation del o[key]. 154 func DelItem(f *Frame, o, key *Object) *BaseException { 155 delItem := o.typ.slots.DelItem 156 if delItem == nil { 157 return f.RaiseType(TypeErrorType, fmt.Sprintf("'%s' object does not support item deletion", o.typ.Name())) 158 } 159 return delItem.Fn(f, o, key) 160 } 161 162 // Div returns the result of dividing v by w according to the __div/rdiv__ 163 // operator. 164 func Div(f *Frame, v, w *Object) (*Object, *BaseException) { 165 return binaryOp(f, v, w, v.typ.slots.Div, v.typ.slots.RDiv, w.typ.slots.RDiv, "/") 166 } 167 168 // DivMod returns the result (quotient and remainder tuple) of dividing v by w 169 // according to the __divmod/rdivmod__ operator. 170 func DivMod(f *Frame, v, w *Object) (*Object, *BaseException) { 171 return binaryOp(f, v, w, v.typ.slots.DivMod, v.typ.slots.RDivMod, w.typ.slots.RDivMod, "divmod()") 172 } 173 174 // Eq returns the equality of v and w according to the __eq__ operator. 175 func Eq(f *Frame, v, w *Object) (*Object, *BaseException) { 176 r, raised := compareRich(f, compareOpEq, v, w) 177 if raised != nil { 178 return nil, raised 179 } 180 if r != NotImplemented { 181 return r, nil 182 } 183 return GetBool(compareDefault(f, v, w) == 0).ToObject(), nil 184 } 185 186 // FloorDiv returns the equality of v and w according to the __floordiv/rfloordiv__ operator. 187 func FloorDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 188 return binaryOp(f, v, w, v.typ.slots.FloorDiv, v.typ.slots.RFloorDiv, w.typ.slots.RFloorDiv, "//") 189 } 190 191 // FormatExc calls traceback.format_exc, falling back to the single line 192 // exception message if that fails, e.g. "NameError: name 'x' is not defined\n". 193 func FormatExc(f *Frame) (s string) { 194 exc, tb := f.ExcInfo() 195 defer func() { 196 if s == "" { 197 strResult, raised := ToStr(f, exc.ToObject()) 198 if raised == nil && strResult.Value() != "" { 199 s = fmt.Sprintf("%s: %s\n", exc.typ.Name(), strResult.Value()) 200 } else { 201 s = exc.typ.Name() + "\n" 202 } 203 } 204 f.RestoreExc(exc, tb) 205 }() 206 tbMod, raised := SysModules.GetItemString(f, "traceback") 207 if raised != nil || tbMod == nil { 208 return 209 } 210 formatExc, raised := GetAttr(f, tbMod, NewStr("format_exc"), nil) 211 if raised != nil { 212 return 213 } 214 result, raised := formatExc.Call(f, nil, nil) 215 if raised != nil || !result.isInstance(StrType) { 216 return 217 } 218 return toStrUnsafe(result).Value() 219 } 220 221 // GE returns the result of operation v >= w. 222 func GE(f *Frame, v, w *Object) (*Object, *BaseException) { 223 r, raised := compareRich(f, compareOpGE, v, w) 224 if raised != nil { 225 return nil, raised 226 } 227 if r != NotImplemented { 228 return r, nil 229 } 230 return GetBool(compareDefault(f, v, w) >= 0).ToObject(), nil 231 } 232 233 // GetItem returns the result of operation o[key]. 234 func GetItem(f *Frame, o, key *Object) (*Object, *BaseException) { 235 getItem := o.typ.slots.GetItem 236 if getItem == nil { 237 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("'%s' object has no attribute '__getitem__'", o.typ.Name())) 238 } 239 return getItem.Fn(f, o, key) 240 } 241 242 // GetAttr returns the named attribute of o. Equivalent to the Python expression 243 // getattr(o, name, def). 244 func GetAttr(f *Frame, o *Object, name *Str, def *Object) (*Object, *BaseException) { 245 // TODO: Fall back to __getattr__. 246 getAttribute := o.typ.slots.GetAttribute 247 if getAttribute == nil { 248 msg := fmt.Sprintf("'%s' has no attribute '%s'", o.typ.Name(), name.Value()) 249 return nil, f.RaiseType(AttributeErrorType, msg) 250 } 251 result, raised := getAttribute.Fn(f, o, name) 252 if raised != nil && raised.isInstance(AttributeErrorType) && def != nil { 253 f.RestoreExc(nil, nil) 254 result, raised = def, nil 255 } 256 return result, raised 257 } 258 259 // GetAttrImport behaves as GetAttr, but errors raises ImportError instead of 260 // AttributeError 261 func GetAttrImport(f *Frame, o *Object, name *Str) (*Object, *BaseException) { 262 result, raised := GetAttr(f, o, name, nil) 263 if raised != nil && raised.isInstance(AttributeErrorType) { 264 msg := fmt.Sprintf("cannot import name %s", name.Value()) 265 return nil, f.RaiseType(ImportErrorType, msg) 266 } 267 return result, raised 268 } 269 270 // GT returns the result of operation v > w. 271 func GT(f *Frame, v, w *Object) (*Object, *BaseException) { 272 r, raised := compareRich(f, compareOpGT, v, w) 273 if raised != nil { 274 return nil, raised 275 } 276 if r != NotImplemented { 277 return r, nil 278 } 279 return GetBool(compareDefault(f, v, w) > 0).ToObject(), nil 280 } 281 282 // Hash returns the hash of o according to its __hash__ operator. 283 func Hash(f *Frame, o *Object) (*Int, *BaseException) { 284 hash := o.typ.slots.Hash 285 if hash == nil { 286 _, raised := hashNotImplemented(f, o) 287 return nil, raised 288 } 289 h, raised := hash.Fn(f, o) 290 if raised != nil { 291 return nil, raised 292 } 293 if !h.isInstance(IntType) { 294 return nil, f.RaiseType(TypeErrorType, "an integer is required") 295 } 296 return toIntUnsafe(h), nil 297 } 298 299 // Hex returns the result of o.__hex__ if defined. 300 func Hex(f *Frame, o *Object) (*Object, *BaseException) { 301 hex := o.typ.slots.Hex 302 if hex == nil { 303 raised := f.RaiseType(TypeErrorType, "hex() argument can't be converted to hex") 304 return nil, raised 305 } 306 h, raised := hex.Fn(f, o) 307 if raised != nil { 308 return nil, raised 309 } 310 if !h.isInstance(StrType) { 311 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__hex__ returned non-string (type %s)", h.typ.name)) 312 } 313 return h, nil 314 } 315 316 // IAdd returns the result of v.__iadd__ if defined, otherwise falls back to 317 // Add. 318 func IAdd(f *Frame, v, w *Object) (*Object, *BaseException) { 319 return inplaceOp(f, v, w, v.typ.slots.IAdd, Add) 320 } 321 322 // IAnd returns the result of v.__iand__ if defined, otherwise falls back to 323 // And. 324 func IAnd(f *Frame, v, w *Object) (*Object, *BaseException) { 325 return inplaceOp(f, v, w, v.typ.slots.IAnd, And) 326 } 327 328 // IDiv returns the result of v.__idiv__ if defined, otherwise falls back to 329 // div. 330 func IDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 331 return inplaceOp(f, v, w, v.typ.slots.IDiv, Div) 332 } 333 334 // IFloorDiv returns the result of v.__ifloordiv__ if defined, otherwise falls back to 335 // floordiv. 336 func IFloorDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 337 return inplaceOp(f, v, w, v.typ.slots.IFloorDiv, FloorDiv) 338 } 339 340 // ILShift returns the result of v.__ilshift__ if defined, otherwise falls back 341 // to lshift. 342 func ILShift(f *Frame, v, w *Object) (*Object, *BaseException) { 343 return inplaceOp(f, v, w, v.typ.slots.ILShift, LShift) 344 } 345 346 // IMod returns the result of v.__imod__ if defined, otherwise falls back to 347 // mod. 348 func IMod(f *Frame, v, w *Object) (*Object, *BaseException) { 349 return inplaceOp(f, v, w, v.typ.slots.IMod, Mod) 350 } 351 352 // IMul returns the result of v.__imul__ if defined, otherwise falls back to 353 // mul. 354 func IMul(f *Frame, v, w *Object) (*Object, *BaseException) { 355 return inplaceOp(f, v, w, v.typ.slots.IMul, Mul) 356 } 357 358 // Invert returns the result of o.__invert__ and is equivalent to the Python 359 // expression "~o". 360 func Invert(f *Frame, o *Object) (*Object, *BaseException) { 361 invert := o.typ.slots.Invert 362 if invert == nil { 363 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary ~: '%s'", o.typ.Name())) 364 } 365 return invert.Fn(f, o) 366 } 367 368 // IOr returns the result of v.__ior__ if defined, otherwise falls back to Or. 369 func IOr(f *Frame, v, w *Object) (*Object, *BaseException) { 370 return inplaceOp(f, v, w, v.typ.slots.IOr, Or) 371 } 372 373 // IPow returns the result of v.__pow__ if defined, otherwise falls back to IPow. 374 func IPow(f *Frame, v, w *Object) (*Object, *BaseException) { 375 return inplaceOp(f, v, w, v.typ.slots.IPow, Pow) 376 } 377 378 // IRShift returns the result of v.__irshift__ if defined, otherwise falls back 379 // to rshift. 380 func IRShift(f *Frame, v, w *Object) (*Object, *BaseException) { 381 return inplaceOp(f, v, w, v.typ.slots.IRShift, RShift) 382 } 383 384 // IsInstance returns true if the type o is an instance of classinfo, or an 385 // instance of an element in classinfo (if classinfo is a tuple). It returns 386 // false otherwise. The argument classinfo must be a type or a tuple whose 387 // elements are types like the isinstance() Python builtin. 388 func IsInstance(f *Frame, o *Object, classinfo *Object) (bool, *BaseException) { 389 return IsSubclass(f, o.typ.ToObject(), classinfo) 390 } 391 392 // IsSubclass returns true if the type o is a subtype of classinfo or a subtype 393 // of an element in classinfo (if classinfo is a tuple). It returns false 394 // otherwise. The argument o must be a type and classinfo must be a type or a 395 // tuple whose elements are types like the issubclass() Python builtin. 396 func IsSubclass(f *Frame, o *Object, classinfo *Object) (bool, *BaseException) { 397 if !o.isInstance(TypeType) { 398 return false, f.RaiseType(TypeErrorType, "issubclass() arg 1 must be a class") 399 } 400 t := toTypeUnsafe(o) 401 errorMsg := "classinfo must be a type or tuple of types" 402 if classinfo.isInstance(TypeType) { 403 return t.isSubclass(toTypeUnsafe(classinfo)), nil 404 } 405 if !classinfo.isInstance(TupleType) { 406 return false, f.RaiseType(TypeErrorType, errorMsg) 407 } 408 for _, elem := range toTupleUnsafe(classinfo).elems { 409 if !elem.isInstance(TypeType) { 410 return false, f.RaiseType(TypeErrorType, errorMsg) 411 } 412 if t.isSubclass(toTypeUnsafe(elem)) { 413 return true, nil 414 } 415 } 416 return false, nil 417 } 418 419 // IsTrue returns the truthiness of o according to the __nonzero__ operator. 420 func IsTrue(f *Frame, o *Object) (bool, *BaseException) { 421 switch o { 422 case True.ToObject(): 423 return true, nil 424 case False.ToObject(), None: 425 return false, nil 426 } 427 nonzero := o.typ.slots.NonZero 428 if nonzero != nil { 429 r, raised := nonzero.Fn(f, o) 430 if raised != nil { 431 return false, raised 432 } 433 if r.isInstance(IntType) { 434 return toIntUnsafe(r).IsTrue(), nil 435 } 436 msg := fmt.Sprintf("__nonzero__ should return bool, returned %s", r.typ.Name()) 437 return false, f.RaiseType(TypeErrorType, msg) 438 } 439 if o.typ.slots.Len != nil { 440 l, raised := Len(f, o) 441 if raised != nil { 442 return false, raised 443 } 444 return l.IsTrue(), nil 445 } 446 return true, nil 447 } 448 449 // ISub returns the result of v.__isub__ if defined, otherwise falls back to 450 // sub. 451 func ISub(f *Frame, v, w *Object) (*Object, *BaseException) { 452 if isub := v.typ.slots.ISub; isub != nil { 453 return isub.Fn(f, v, w) 454 } 455 return Sub(f, v, w) 456 } 457 458 // Iter implements the Python iter() builtin. It returns an iterator for o if 459 // o is iterable. Otherwise it raises TypeError. 460 // Note that the iter(f, sentinel) form is implemented by IterCallable. 461 func Iter(f *Frame, o *Object) (*Object, *BaseException) { 462 iter := o.typ.slots.Iter 463 if iter != nil { 464 return iter.Fn(f, o) 465 } 466 if o.typ.slots.GetItem != nil { 467 return newSeqIterator(o), nil 468 } 469 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("'%s' object is not iterable", o.typ.Name())) 470 } 471 472 // IterCallable implements the Python iter(f, sentintel) builtin. 473 // The iterator created in this case will call o with no arguments for each call to its next() method; 474 // if the value returned is equal to sentinel, StopIteration will be raised, otherwise the value will be returned. 475 // It raises TypeError if o is not callable. 476 func IterCallable(f *Frame, o *Object, sentinel *Object) (*Object, *BaseException) { 477 call := o.typ.slots.Call 478 if call == nil { 479 return nil, f.RaiseType(TypeErrorType, "iter(v, w): v must be callable") 480 } 481 return newCallableIterator(o, sentinel), nil 482 } 483 484 // IXor returns the result of v.__ixor__ if defined, otherwise falls back to 485 // Xor. 486 func IXor(f *Frame, v, w *Object) (*Object, *BaseException) { 487 return inplaceOp(f, v, w, v.typ.slots.IXor, Xor) 488 } 489 490 // LE returns the result of operation v <= w. 491 func LE(f *Frame, v, w *Object) (*Object, *BaseException) { 492 r, raised := compareRich(f, compareOpLE, v, w) 493 if raised != nil { 494 return nil, raised 495 } 496 if r != NotImplemented { 497 return r, nil 498 } 499 return GetBool(compareDefault(f, v, w) <= 0).ToObject(), nil 500 } 501 502 // Len returns the length of the given sequence object. 503 func Len(f *Frame, o *Object) (*Int, *BaseException) { 504 lenSlot := o.typ.slots.Len 505 if lenSlot == nil { 506 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("object of type '%s' has no len()", o.typ.Name())) 507 } 508 r, raised := lenSlot.Fn(f, o) 509 if raised != nil { 510 return nil, raised 511 } 512 if !r.isInstance(IntType) { 513 return nil, f.RaiseType(TypeErrorType, "an integer is required") 514 } 515 return toIntUnsafe(r), nil 516 } 517 518 // LShift returns the result of v << w according to the __lshift/rlshift__ 519 // operator. 520 func LShift(f *Frame, v, w *Object) (*Object, *BaseException) { 521 return binaryOp(f, v, w, v.typ.slots.LShift, v.typ.slots.RLShift, w.typ.slots.RLShift, "<<") 522 } 523 524 // LT returns the result of operation v < w. 525 func LT(f *Frame, v, w *Object) (*Object, *BaseException) { 526 r, raised := compareRich(f, compareOpLT, v, w) 527 if raised != nil { 528 return nil, raised 529 } 530 if r != NotImplemented { 531 return r, nil 532 } 533 return GetBool(compareDefault(f, v, w) < 0).ToObject(), nil 534 } 535 536 // Mod returns the remainder from the division of v by w according to the 537 // __mod/rmod__ operator. 538 func Mod(f *Frame, v, w *Object) (*Object, *BaseException) { 539 return binaryOp(f, v, w, v.typ.slots.Mod, v.typ.slots.RMod, w.typ.slots.RMod, "%") 540 } 541 542 // Mul returns the result of multiplying v and w together according to the 543 // __mul/rmul__ operator. 544 func Mul(f *Frame, v, w *Object) (*Object, *BaseException) { 545 return binaryOp(f, v, w, v.typ.slots.Mul, v.typ.slots.RMul, w.typ.slots.RMul, "*") 546 } 547 548 // Pow returns the result of x**y, the base-x exponential of y according to the 549 // __pow/rpow__ operator. 550 func Pow(f *Frame, v, w *Object) (*Object, *BaseException) { 551 return binaryOp(f, v, w, v.typ.slots.Pow, v.typ.slots.RPow, w.typ.slots.RPow, "**") 552 } 553 554 // Or returns the result of the bitwise or operator v | w according to 555 // __or/ror__. 556 func Or(f *Frame, v, w *Object) (*Object, *BaseException) { 557 return binaryOp(f, v, w, v.typ.slots.Or, v.typ.slots.ROr, w.typ.slots.ROr, "|") 558 } 559 560 // Index returns the o converted to a Python int or long according to o's 561 // __index__ slot. 562 func Index(f *Frame, o *Object) (*Object, *BaseException) { 563 if o.isInstance(IntType) || o.isInstance(LongType) { 564 return o, nil 565 } 566 index := o.typ.slots.Index 567 if index == nil { 568 return nil, nil 569 } 570 i, raised := index.Fn(f, o) 571 if raised != nil { 572 return nil, raised 573 } 574 if !i.isInstance(IntType) && !i.isInstance(LongType) { 575 format := "__index__ returned non-(int,long) (type %s)" 576 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(format, i.typ.Name())) 577 } 578 return i, nil 579 } 580 581 // IndexInt returns the value of o converted to a Go int according to o's 582 // __index__ slot. 583 // It raises a TypeError if o doesn't have an __index__ method. 584 func IndexInt(f *Frame, o *Object) (i int, raised *BaseException) { 585 if index := o.typ.slots.Index; index != nil { 586 // Unwrap __index__ slot and fall through. 587 o, raised = index.Fn(f, o) 588 if raised != nil { 589 return 0, raised 590 } 591 } 592 if o.isInstance(IntType) { 593 return toIntUnsafe(o).Value(), nil 594 } 595 if o.isInstance(LongType) { 596 l := toLongUnsafe(o).Value() 597 // Anything bigger than maxIntBig will treat as maxIntBig. 598 if !numInIntRange(l) { 599 l = maxIntBig 600 } 601 return int(l.Int64()), nil 602 } 603 return 0, f.RaiseType(TypeErrorType, errBadSliceIndex) 604 } 605 606 // Invoke calls the given callable with the positional arguments given by args 607 // and *varargs, and the keyword arguments by keywords and **kwargs. It first 608 // packs the arguments into slices for the positional and keyword arguments, 609 // then it passes those to *Object.Call. 610 func Invoke(f *Frame, callable *Object, args Args, varargs *Object, keywords KWArgs, kwargs *Object) (*Object, *BaseException) { 611 if varargs != nil { 612 raised := seqApply(f, varargs, func(elems []*Object, _ bool) *BaseException { 613 numArgs := len(args) 614 packed := make([]*Object, numArgs+len(elems)) 615 copy(packed, args) 616 copy(packed[numArgs:], elems) 617 args = packed 618 return nil 619 }) 620 if raised != nil { 621 return nil, raised 622 } 623 } 624 if kwargs != nil { 625 if !kwargs.isInstance(DictType) { 626 format := "argument after ** must be a dict, not %s" 627 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(format, kwargs.typ.Name())) 628 } 629 kwargsDict := toDictUnsafe(kwargs) 630 numKeywords := len(keywords) 631 numKwargs, raised := Len(f, kwargs) 632 if raised != nil { 633 return nil, raised 634 } 635 // Don't bother synchronizing access to len(kwargs) since it's just a 636 // hint and it doesn't matter if it's a little off. 637 packed := make(KWArgs, numKeywords, numKeywords+numKwargs.Value()) 638 copy(packed, keywords) 639 raised = seqForEach(f, kwargs, func(o *Object) *BaseException { 640 if !o.isInstance(StrType) { 641 return f.RaiseType(TypeErrorType, "keywords must be strings") 642 } 643 s := toStrUnsafe(o).Value() 644 // Search for dupes linearly assuming small number of keywords. 645 for _, kw := range keywords { 646 if kw.Name == s { 647 format := "got multiple values for keyword argument '%s'" 648 return f.RaiseType(TypeErrorType, fmt.Sprintf(format, s)) 649 } 650 } 651 item, raised := kwargsDict.GetItem(f, o) 652 if raised != nil { 653 return raised 654 } 655 if item == nil { 656 return raiseKeyError(f, o) 657 } 658 packed = append(packed, KWArg{Name: s, Value: item}) 659 return nil 660 }) 661 if raised != nil { 662 return nil, raised 663 } 664 keywords = packed 665 } 666 return callable.Call(f, args, keywords) 667 } 668 669 // NE returns the non-equality of v and w according to the __ne__ operator. 670 func NE(f *Frame, v, w *Object) (*Object, *BaseException) { 671 r, raised := compareRich(f, compareOpNE, v, w) 672 if raised != nil { 673 return nil, raised 674 } 675 if r != NotImplemented { 676 return r, nil 677 } 678 return GetBool(compareDefault(f, v, w) != 0).ToObject(), nil 679 } 680 681 // Next implements the Python next() builtin. It calls next on the provided 682 // iterator. It raises TypeError if iter is not an iterator object. 683 // Note that the next(it, default) form is not yet supported. 684 func Next(f *Frame, iter *Object) (*Object, *BaseException) { 685 // TODO: Support next(it, default) usage. 686 next := iter.typ.slots.Next 687 if next == nil { 688 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("%s object is not an iterator", iter.typ.Name())) 689 } 690 return next.Fn(f, iter) 691 } 692 693 // Oct returns the result of o.__oct__ if defined. 694 func Oct(f *Frame, o *Object) (*Object, *BaseException) { 695 oct := o.typ.slots.Oct 696 if oct == nil { 697 raised := f.RaiseType(TypeErrorType, "oct() argument can't be converted to oct") 698 return nil, raised 699 } 700 o, raised := oct.Fn(f, o) 701 if raised != nil { 702 return nil, raised 703 } 704 if !o.isInstance(StrType) { 705 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__oct__ returned non-string (type %s)", o.typ.name)) 706 } 707 return o, nil 708 } 709 710 // Pos returns the result of o.__pos__ and is equivalent to the Python 711 // expression "+o". 712 func Pos(f *Frame, o *Object) (*Object, *BaseException) { 713 pos := o.typ.slots.Pos 714 if pos == nil { 715 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary +: '%s'", o.typ.Name())) 716 } 717 return pos.Fn(f, o) 718 } 719 720 // Print implements the Python print statement. It calls str() on the given args 721 // and outputs the results to stdout separated by spaces. Similar to the Python 722 // print statement. 723 func Print(f *Frame, args Args, nl bool) *BaseException { 724 // TODO: Support outputting to files other than stdout and softspace. 725 var end string 726 if nl { 727 end = "\n" 728 } else if len(args) > 0 { 729 end = " " 730 } 731 return pyPrint(f, args, " ", end, Stdout) 732 } 733 734 // Repr returns a string containing a printable representation of o. This is 735 // equivalent to the Python expression "repr(o)". 736 func Repr(f *Frame, o *Object) (*Str, *BaseException) { 737 repr := o.typ.slots.Repr 738 if repr == nil { 739 s, raised := o.typ.FullName(f) 740 if raised != nil { 741 return nil, raised 742 } 743 return NewStr(fmt.Sprintf("<%s object at %p>", s, o)), nil 744 } 745 r, raised := repr.Fn(f, o) 746 if raised != nil { 747 return nil, raised 748 } 749 if !r.isInstance(StrType) { 750 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__repr__ returned non-string (type %s)", r.typ.Name())) 751 } 752 return toStrUnsafe(r), nil 753 } 754 755 // ResolveClass resolves name in the class dict given by class, falling back to 756 // the provided local if it is non-nil, otherwise falling back to globals. 757 // This is used by the code generator to resolve names in the context of a class 758 // definition. If the class definition occurs in a closure in which a local of 759 // the given name is present then local will be non-nil, otherwise it will be 760 // nil. 761 func ResolveClass(f *Frame, class *Dict, local *Object, name *Str) (*Object, *BaseException) { 762 if value, raised := class.GetItem(f, name.ToObject()); raised != nil || value != nil { 763 return value, raised 764 } 765 if local != nil { 766 if raised := CheckLocal(f, local, name.Value()); raised != nil { 767 return nil, raised 768 } 769 return local, nil 770 } 771 return ResolveGlobal(f, name) 772 } 773 774 // ResolveGlobal looks up name in the frame's dict of global variables or in 775 // the Builtins dict if absent. It raises NameError when absent from both. 776 func ResolveGlobal(f *Frame, name *Str) (*Object, *BaseException) { 777 if value, raised := f.Globals().GetItem(f, name.ToObject()); raised != nil || value != nil { 778 return value, raised 779 } 780 value, raised := Builtins.GetItem(f, name.ToObject()) 781 if raised != nil { 782 return nil, raised 783 } 784 if value == nil { 785 return nil, f.RaiseType(NameErrorType, fmt.Sprintf("name '%s' is not defined", name.Value())) 786 } 787 return value, nil 788 } 789 790 // RShift returns the result of v >> w according to the __rshift/rrshift__ 791 // operator. 792 func RShift(f *Frame, v, w *Object) (*Object, *BaseException) { 793 return binaryOp(f, v, w, v.typ.slots.RShift, v.typ.slots.RRShift, w.typ.slots.RRShift, ">>") 794 } 795 796 // CheckLocal validates that the local variable with the given name and value 797 // has been bound and raises UnboundLocalError if not. 798 func CheckLocal(f *Frame, value *Object, name string) *BaseException { 799 if value == UnboundLocal { 800 format := "local variable '%s' referenced before assignment" 801 return f.RaiseType(UnboundLocalErrorType, fmt.Sprintf(format, name)) 802 } 803 return nil 804 } 805 806 // SetAttr sets the attribute of o given by name to value. Equivalent to the 807 // Python expression setattr(o, name, value). 808 func SetAttr(f *Frame, o *Object, name *Str, value *Object) *BaseException { 809 setAttr := o.typ.slots.SetAttr 810 if setAttr == nil { 811 return f.RaiseType(SystemErrorType, fmt.Sprintf("'%s' object has no __setattr__ method", o.typ.Name())) 812 } 813 return setAttr.Fn(f, o, name, value) 814 } 815 816 // SetItem performs the operation o[key] = value. 817 func SetItem(f *Frame, o, key, value *Object) *BaseException { 818 setItem := o.typ.slots.SetItem 819 if setItem == nil { 820 return f.RaiseType(TypeErrorType, fmt.Sprintf("'%s' object has no attribute '__setitem__'", o.typ.Name())) 821 } 822 return setItem.Fn(f, o, key, value) 823 } 824 825 // StartThread runs callable in a new goroutine. 826 func StartThread(callable *Object) { 827 go func() { 828 atomic.AddInt64(&ThreadCount, 1) 829 defer atomic.AddInt64(&ThreadCount, -1) 830 f := NewRootFrame() 831 _, raised := callable.Call(f, nil, nil) 832 if raised != nil { 833 Stderr.writeString(FormatExc(f)) 834 } 835 }() 836 } 837 838 // Sub returns the result of subtracting v from w according to the 839 // __sub/rsub__ operator. 840 func Sub(f *Frame, v, w *Object) (*Object, *BaseException) { 841 return binaryOp(f, v, w, v.typ.slots.Sub, v.typ.slots.RSub, w.typ.slots.RSub, "-") 842 } 843 844 // TieTarget is a data structure used to facilitate iterator unpacking in 845 // assignment statements. A TieTarget should have one of Target or Children 846 // populated but not both. 847 // 848 // As an example, the targets in the Python assignment 'foo, bar = ...' 849 // could be represented as: 850 // 851 // TieTarget{ 852 // Children: []TieTarget{{Target: &foo}, {Target: &bar}}, 853 // } 854 type TieTarget struct { 855 // Target is a destination pointer where an unpacked value will be 856 // stored. 857 Target **Object 858 // Children contains a sequence of TieTargets that should be unpacked 859 // into. 860 Children []TieTarget 861 } 862 863 // Tie takes a (possibly nested) TieTarget and recursively unpacks the 864 // elements of o by iteration, assigning the results to the Target fields of t. 865 // If the structure of o is not suitable to be unpacked into t, then an 866 // exception is raised. 867 func Tie(f *Frame, t TieTarget, o *Object) *BaseException { 868 if t.Target != nil { 869 *t.Target = o 870 return nil 871 } 872 iter, raised := Iter(f, o) 873 if raised != nil { 874 return raised 875 } 876 for i, child := range t.Children { 877 if value, raised := Next(f, iter); raised == nil { 878 if raised := Tie(f, child, value); raised != nil { 879 return raised 880 } 881 } else if raised.isInstance(StopIterationType) { 882 return f.RaiseType(ValueErrorType, fmt.Sprintf("need more than %d values to unpack", i)) 883 } else { 884 return raised 885 } 886 } 887 _, raised = Next(f, iter) 888 if raised == nil { 889 return f.RaiseType(ValueErrorType, "too many values to unpack") 890 } 891 if !raised.isInstance(StopIterationType) { 892 return raised 893 } 894 f.RestoreExc(nil, nil) 895 return nil 896 } 897 898 // ToInt converts o to an integer type according to the __int__ slot. If the 899 // result is not an int or long, then an exception is raised. 900 func ToInt(f *Frame, o *Object) (*Object, *BaseException) { 901 if o.typ == IntType || o.typ == LongType { 902 return o, nil 903 } 904 intSlot := o.typ.slots.Int 905 if intSlot == nil { 906 return nil, f.RaiseType(TypeErrorType, "an integer is required") 907 } 908 i, raised := intSlot.Fn(f, o) 909 if raised != nil { 910 return nil, raised 911 } 912 if i.isInstance(IntType) || i.isInstance(LongType) { 913 return i, nil 914 } 915 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__int__ returned non-int (type %s)", i.typ.Name())) 916 } 917 918 // ToIntValue converts o to an integer according to the __int__ slot. If the 919 // result is not an int or long, or if the long value is too large to fit into 920 // an int, then an exception is raised. 921 func ToIntValue(f *Frame, o *Object) (int, *BaseException) { 922 i, raised := ToInt(f, o) 923 if raised != nil { 924 return 0, raised 925 } 926 if i.isInstance(IntType) { 927 return toIntUnsafe(i).Value(), nil 928 } 929 return toLongUnsafe(i).IntValue(f) 930 } 931 932 // ToNative converts o to a native Go object according to the __native__ 933 // operator. 934 func ToNative(f *Frame, o *Object) (reflect.Value, *BaseException) { 935 if native := o.typ.slots.Native; native != nil { 936 return native.Fn(f, o) 937 } 938 return reflect.ValueOf(o), nil 939 } 940 941 // ToStr is a convenience function for calling "str(o)". 942 func ToStr(f *Frame, o *Object) (*Str, *BaseException) { 943 result, raised := StrType.Call(f, []*Object{o}, nil) 944 if raised != nil { 945 return nil, raised 946 } 947 if !result.isInstance(StrType) { 948 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__str__ returned non-string (type %s)", result.typ.Name())) 949 } 950 return toStrUnsafe(result), nil 951 } 952 953 // Neg returns the result of o.__neg__ and is equivalent to the Python 954 // expression "-o". 955 func Neg(f *Frame, o *Object) (*Object, *BaseException) { 956 neg := o.typ.slots.Neg 957 if neg == nil { 958 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary -: '%s'", o.typ.Name())) 959 } 960 return neg.Fn(f, o) 961 } 962 963 // Xor returns the result of the bitwise xor operator v ^ w according to 964 // __xor/rxor__. 965 func Xor(f *Frame, v, w *Object) (*Object, *BaseException) { 966 return binaryOp(f, v, w, v.typ.slots.Xor, v.typ.slots.RXor, w.typ.slots.RXor, "^") 967 } 968 969 const ( 970 errResultTooLarge = "result too large" 971 errUnsupportedOperand = "unsupported operand type(s) for %s: '%s' and '%s'" 972 ) 973 974 // binaryOp picks an appropriate operator method (op or rop) from v or w and 975 // returns its result. It raises TypeError if no appropriate method is found. 976 // It is similar to CPython's binary_op1 function from abstract.c. 977 func binaryOp(f *Frame, v, w *Object, op, vrop, wrop *binaryOpSlot, opName string) (*Object, *BaseException) { 978 if v.typ != w.typ && w.typ.isSubclass(v.typ) { 979 // w is an instance of a subclass of type(v), so prefer w's more 980 // specific rop, but only if it is overridden (wrop != vrop). 981 if wrop != nil && wrop != vrop { 982 r, raised := wrop.Fn(f, w, v) 983 if raised != nil { 984 return nil, raised 985 } 986 if r != NotImplemented { 987 return r, nil 988 } 989 } 990 } 991 if op != nil { 992 r, raised := op.Fn(f, v, w) 993 if raised != nil { 994 return nil, raised 995 } 996 if r != NotImplemented { 997 return r, nil 998 } 999 } 1000 if wrop != nil { 1001 r, raised := wrop.Fn(f, w, v) 1002 if raised != nil { 1003 return nil, raised 1004 } 1005 if r != NotImplemented { 1006 return r, nil 1007 } 1008 } 1009 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(errUnsupportedOperand, opName, v.typ.Name(), w.typ.Name())) 1010 } 1011 1012 func inplaceOp(f *Frame, v, w *Object, slot *binaryOpSlot, fallback binaryOpFunc) (*Object, *BaseException) { 1013 if slot != nil { 1014 return slot.Fn(f, v, w) 1015 } 1016 return fallback(f, v, w) 1017 } 1018 1019 type compareOp int 1020 1021 const ( 1022 compareOpLT compareOp = iota 1023 compareOpLE 1024 compareOpEq 1025 compareOpNE 1026 compareOpGE 1027 compareOpGT 1028 ) 1029 1030 var compareOpSwapped = []compareOp{ 1031 compareOpGT, 1032 compareOpGE, 1033 compareOpEq, 1034 compareOpNE, 1035 compareOpLE, 1036 compareOpLT, 1037 } 1038 1039 func (op compareOp) swapped() compareOp { 1040 return compareOpSwapped[op] 1041 } 1042 1043 func (op compareOp) slot(t *Type) *binaryOpSlot { 1044 switch op { 1045 case compareOpLT: 1046 return t.slots.LT 1047 case compareOpLE: 1048 return t.slots.LE 1049 case compareOpEq: 1050 return t.slots.Eq 1051 case compareOpNE: 1052 return t.slots.NE 1053 case compareOpGE: 1054 return t.slots.GE 1055 case compareOpGT: 1056 return t.slots.GT 1057 } 1058 panic(fmt.Sprintf("invalid compareOp value: %d", op)) 1059 } 1060 1061 func compareRich(f *Frame, op compareOp, v, w *Object) (*Object, *BaseException) { 1062 r, raised := tryRichCompare(f, op, v, w) 1063 if raised != nil { 1064 return nil, raised 1065 } 1066 if r != NotImplemented { 1067 return r, nil 1068 } 1069 return try3wayToRichCompare(f, op, v, w) 1070 } 1071 1072 // convert3wayToObject converts the integer results from a 3-way 1073 // comparison to a suitable boolean value for the given rich 1074 // comparison op. 1075 func convert3wayToObject(op compareOp, c int) *Object { 1076 b := false 1077 switch op { 1078 case compareOpLT: 1079 b = c < 0 1080 case compareOpLE: 1081 b = c <= 0 1082 case compareOpEq: 1083 b = c == 0 1084 case compareOpNE: 1085 b = c != 0 1086 case compareOpGE: 1087 b = c >= 0 1088 case compareOpGT: 1089 b = c > 0 1090 } 1091 return GetBool(b).ToObject() 1092 } 1093 1094 // try3wayToRichCompare tries to perform a rich comparison operation on the given objects 1095 // with the given comparison op using 3-way comparison. It closely resembles the behavior 1096 // of CPython's try_3way_to_rich_compare in object.c. 1097 func try3wayToRichCompare(f *Frame, op compareOp, v, w *Object) (*Object, *BaseException) { 1098 r, raised := try3wayCompare(f, v, w) 1099 if raised != nil { 1100 return nil, raised 1101 } 1102 c := 0 1103 if r == NotImplemented { 1104 c = compareDefault(f, v, w) 1105 } else { 1106 c = toIntUnsafe(r).Value() 1107 } 1108 return convert3wayToObject(op, c), nil 1109 } 1110 1111 // tryRichCompare tries to perform a rich comparison operation on the given 1112 // objects with the given comparison op using the rich comparison methods. 1113 // It closely resembles the behavior of CPython's try_rich_compare in object.c. 1114 func tryRichCompare(f *Frame, op compareOp, v, w *Object) (*Object, *BaseException) { 1115 if v.typ != w.typ && w.typ.isSubclass(v.typ) { 1116 // type(w) is a subclass of type(v) so try to use w's 1117 // comparison operators since they're more specific. 1118 slot := op.swapped().slot(w.typ) 1119 if slot != nil { 1120 r, raised := slot.Fn(f, w, v) 1121 if raised != nil { 1122 return nil, raised 1123 } 1124 if r != NotImplemented { 1125 return r, nil 1126 } 1127 } 1128 } 1129 slot := op.slot(v.typ) 1130 if slot != nil { 1131 r, raised := slot.Fn(f, v, w) 1132 if raised != nil { 1133 return nil, raised 1134 } 1135 if r != NotImplemented { 1136 return r, nil 1137 } 1138 } 1139 slot = op.swapped().slot(w.typ) 1140 if slot != nil { 1141 return slot.Fn(f, w, v) 1142 } 1143 return NotImplemented, nil 1144 } 1145 1146 // compareDefault returns is the fallback logic for object comparison. It 1147 // closely resembles the behavior of CPython's default_3way_compare in object.c. 1148 func compareDefault(f *Frame, v, w *Object) int { 1149 if v.typ == w.typ { 1150 pv, pw := uintptr(v.toPointer()), uintptr(w.toPointer()) 1151 if pv < pw { 1152 return -1 1153 } 1154 if pv == pw { 1155 return 0 1156 } 1157 return 1 1158 } 1159 if v == None { 1160 return -1 1161 } 1162 if w == None { 1163 return 1 1164 } 1165 // TODO: In default_3way_compare, the number type name is the empty 1166 // string so it evaluates less than non-number types. Once Grumpy 1167 // supports the concept of number types, add this behavior. 1168 if v.typ.Name() < w.typ.Name() { 1169 return -1 1170 } 1171 if v.typ.Name() != w.typ.Name() { 1172 return 1 1173 } 1174 if uintptr(v.typ.toPointer()) < uintptr(w.typ.toPointer()) { 1175 return -1 1176 } 1177 return 1 1178 } 1179 1180 // tryRichCompareBool tries a rich comparison with the given comparison op and 1181 // returns a bool indicating if the relation is true. It closely resembles the 1182 // behavior of CPython's try_rich_compare_bool in object.c. 1183 func tryRichCompareBool(f *Frame, op compareOp, v, w *Object) (bool, *BaseException) { 1184 r, raised := tryRichCompare(f, op, v, w) 1185 if raised != nil { 1186 return false, raised 1187 } 1188 if r == NotImplemented { 1189 return false, nil 1190 } 1191 br, raised := IsTrue(f, r) 1192 if raised != nil { 1193 return false, raised 1194 } 1195 return br, raised 1196 } 1197 1198 // halfCompare tries a comparison with the __cmp__ slot, ensures the result 1199 // is an integer, and returns it. It closely resembles the behavior of CPython's 1200 // half_compare in typeobject.c. 1201 func halfCompare(f *Frame, v, w *Object) (*Object, *BaseException) { 1202 cmp := v.typ.slots.Cmp 1203 r, raised := cmp.Fn(f, v, w) 1204 if raised != nil { 1205 return nil, raised 1206 } 1207 if !r.isInstance(IntType) { 1208 return nil, f.RaiseType(TypeErrorType, "an integer is required") 1209 } 1210 return r, nil 1211 } 1212 1213 // try3wayCompare tries a comparison with the __cmp__ slot with the given 1214 // arguments. It first tries to use the __cmp__ slot on v and if that fails 1215 // on w. It closely resembles the behavior of CPython's try_3way_compare in 1216 // object.c. 1217 func try3wayCompare(f *Frame, v, w *Object) (*Object, *BaseException) { 1218 cmp := v.typ.slots.Cmp 1219 if cmp != nil { 1220 return halfCompare(f, v, w) 1221 } 1222 cmp = w.typ.slots.Cmp 1223 if cmp != nil { 1224 r, raised := halfCompare(f, w, v) 1225 if raised != nil { 1226 return nil, raised 1227 } 1228 return intNeg(f, r) 1229 } 1230 return NotImplemented, nil 1231 } 1232 1233 // tryRichTo3wayCompare tries to compute a 3-way comparison in terms of 1234 // the rich comparison operators (if they exist). It closely resembles 1235 // the behavior of CPython's try_rich_to_3way_compare in object.c. 1236 func tryRichTo3wayCompare(f *Frame, v, w *Object) (*Object, *BaseException) { 1237 var tries = []struct { 1238 op compareOp 1239 outcome int 1240 }{ 1241 {compareOpEq, 0}, 1242 {compareOpLT, -1}, 1243 {compareOpGT, 1}, 1244 } 1245 for _, try := range tries { 1246 r, raised := tryRichCompareBool(f, try.op, v, w) 1247 if raised != nil { 1248 return nil, raised 1249 } 1250 if r { 1251 return NewInt(try.outcome).ToObject(), nil 1252 } 1253 } 1254 return NotImplemented, nil 1255 } 1256 1257 func checkFunctionArgs(f *Frame, function string, args Args, types ...*Type) *BaseException { 1258 if len(args) != len(types) { 1259 msg := fmt.Sprintf("'%s' requires %d arguments", function, len(types)) 1260 return f.RaiseType(TypeErrorType, msg) 1261 } 1262 for i, t := range types { 1263 if !args[i].isInstance(t) { 1264 format := "'%s' requires a '%s' object but received a %q" 1265 return f.RaiseType(TypeErrorType, fmt.Sprintf(format, function, t.Name(), args[i].typ.Name())) 1266 } 1267 } 1268 return nil 1269 } 1270 1271 func checkFunctionVarArgs(f *Frame, function string, args Args, types ...*Type) *BaseException { 1272 if len(args) <= len(types) { 1273 return checkFunctionArgs(f, function, args, types...) 1274 } 1275 return checkFunctionArgs(f, function, args[:len(types)], types...) 1276 } 1277 1278 func checkMethodArgs(f *Frame, method string, args Args, types ...*Type) *BaseException { 1279 if len(args) != len(types) { 1280 msg := fmt.Sprintf("'%s' of '%s' requires %d arguments", method, types[0].Name(), len(types)) 1281 return f.RaiseType(TypeErrorType, msg) 1282 } 1283 for i, t := range types { 1284 if !args[i].isInstance(t) { 1285 format := "'%s' requires a '%s' object but received a '%s'" 1286 return f.RaiseType(TypeErrorType, fmt.Sprintf(format, method, t.Name(), args[i].typ.Name())) 1287 } 1288 } 1289 return nil 1290 } 1291 1292 func checkMethodVarArgs(f *Frame, method string, args Args, types ...*Type) *BaseException { 1293 if len(args) <= len(types) { 1294 return checkMethodArgs(f, method, args, types...) 1295 } 1296 return checkMethodArgs(f, method, args[:len(types)], types...) 1297 } 1298 1299 func hashNotImplemented(f *Frame, o *Object) (*Object, *BaseException) { 1300 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("unhashable type: '%s'", o.typ.Name())) 1301 } 1302 1303 // pyPrint encapsulates the logic of the Python print function. 1304 func pyPrint(f *Frame, args Args, sep, end string, file *File) *BaseException { 1305 for i, arg := range args { 1306 if i > 0 { 1307 err := file.writeString(sep) 1308 if err != nil { 1309 return f.RaiseType(IOErrorType, err.Error()) 1310 } 1311 } 1312 1313 s, raised := ToStr(f, arg) 1314 if raised != nil { 1315 return raised 1316 } 1317 1318 err := file.writeString(s.Value()) 1319 if err != nil { 1320 return f.RaiseType(IOErrorType, err.Error()) 1321 } 1322 } 1323 1324 err := file.writeString(end) 1325 if err != nil { 1326 return f.RaiseType(IOErrorType, err.Error()) 1327 } 1328 1329 return nil 1330 }