github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/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 grumpy
    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  // GT returns the result of operation v > w.
   260  func GT(f *Frame, v, w *Object) (*Object, *BaseException) {
   261  	r, raised := compareRich(f, compareOpGT, v, w)
   262  	if raised != nil {
   263  		return nil, raised
   264  	}
   265  	if r != NotImplemented {
   266  		return r, nil
   267  	}
   268  	return GetBool(compareDefault(f, v, w) > 0).ToObject(), nil
   269  }
   270  
   271  // Hash returns the hash of o according to its __hash__ operator.
   272  func Hash(f *Frame, o *Object) (*Int, *BaseException) {
   273  	hash := o.typ.slots.Hash
   274  	if hash == nil {
   275  		_, raised := hashNotImplemented(f, o)
   276  		return nil, raised
   277  	}
   278  	h, raised := hash.Fn(f, o)
   279  	if raised != nil {
   280  		return nil, raised
   281  	}
   282  	if !h.isInstance(IntType) {
   283  		return nil, f.RaiseType(TypeErrorType, "an integer is required")
   284  	}
   285  	return toIntUnsafe(h), nil
   286  }
   287  
   288  // Hex returns the result of o.__hex__ if defined.
   289  func Hex(f *Frame, o *Object) (*Object, *BaseException) {
   290  	hex := o.typ.slots.Hex
   291  	if hex == nil {
   292  		raised := f.RaiseType(TypeErrorType, "hex() argument can't be converted to hex")
   293  		return nil, raised
   294  	}
   295  	h, raised := hex.Fn(f, o)
   296  	if raised != nil {
   297  		return nil, raised
   298  	}
   299  	if !h.isInstance(StrType) {
   300  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__hex__ returned non-string (type %s)", h.typ.name))
   301  	}
   302  	return h, nil
   303  }
   304  
   305  // IAdd returns the result of v.__iadd__ if defined, otherwise falls back to
   306  // Add.
   307  func IAdd(f *Frame, v, w *Object) (*Object, *BaseException) {
   308  	return inplaceOp(f, v, w, v.typ.slots.IAdd, Add)
   309  }
   310  
   311  // IAnd returns the result of v.__iand__ if defined, otherwise falls back to
   312  // And.
   313  func IAnd(f *Frame, v, w *Object) (*Object, *BaseException) {
   314  	return inplaceOp(f, v, w, v.typ.slots.IAnd, And)
   315  }
   316  
   317  // IDiv returns the result of v.__idiv__ if defined, otherwise falls back to
   318  // div.
   319  func IDiv(f *Frame, v, w *Object) (*Object, *BaseException) {
   320  	return inplaceOp(f, v, w, v.typ.slots.IDiv, Div)
   321  }
   322  
   323  // IFloorDiv returns the result of v.__ifloordiv__ if defined, otherwise falls back to
   324  // floordiv.
   325  func IFloorDiv(f *Frame, v, w *Object) (*Object, *BaseException) {
   326  	return inplaceOp(f, v, w, v.typ.slots.IFloorDiv, FloorDiv)
   327  }
   328  
   329  // ILShift returns the result of v.__ilshift__ if defined, otherwise falls back
   330  // to lshift.
   331  func ILShift(f *Frame, v, w *Object) (*Object, *BaseException) {
   332  	return inplaceOp(f, v, w, v.typ.slots.ILShift, LShift)
   333  }
   334  
   335  // IMod returns the result of v.__imod__ if defined, otherwise falls back to
   336  // mod.
   337  func IMod(f *Frame, v, w *Object) (*Object, *BaseException) {
   338  	return inplaceOp(f, v, w, v.typ.slots.IMod, Mod)
   339  }
   340  
   341  // IMul returns the result of v.__imul__ if defined, otherwise falls back to
   342  // mul.
   343  func IMul(f *Frame, v, w *Object) (*Object, *BaseException) {
   344  	return inplaceOp(f, v, w, v.typ.slots.IMul, Mul)
   345  }
   346  
   347  // Invert returns the result of o.__invert__ and is equivalent to the Python
   348  // expression "~o".
   349  func Invert(f *Frame, o *Object) (*Object, *BaseException) {
   350  	invert := o.typ.slots.Invert
   351  	if invert == nil {
   352  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary ~: '%s'", o.typ.Name()))
   353  	}
   354  	return invert.Fn(f, o)
   355  }
   356  
   357  // IOr returns the result of v.__ior__ if defined, otherwise falls back to Or.
   358  func IOr(f *Frame, v, w *Object) (*Object, *BaseException) {
   359  	return inplaceOp(f, v, w, v.typ.slots.IOr, Or)
   360  }
   361  
   362  // IPow returns the result of v.__pow__ if defined, otherwise falls back to IPow.
   363  func IPow(f *Frame, v, w *Object) (*Object, *BaseException) {
   364  	return inplaceOp(f, v, w, v.typ.slots.IPow, Pow)
   365  }
   366  
   367  // IRShift returns the result of v.__irshift__ if defined, otherwise falls back
   368  // to rshift.
   369  func IRShift(f *Frame, v, w *Object) (*Object, *BaseException) {
   370  	return inplaceOp(f, v, w, v.typ.slots.IRShift, RShift)
   371  }
   372  
   373  // IsInstance returns true if the type o is an instance of classinfo, or an
   374  // instance of an element in classinfo (if classinfo is a tuple). It returns
   375  // false otherwise. The argument classinfo must be a type or a tuple whose
   376  // elements are types like the isinstance() Python builtin.
   377  func IsInstance(f *Frame, o *Object, classinfo *Object) (bool, *BaseException) {
   378  	return IsSubclass(f, o.typ.ToObject(), classinfo)
   379  }
   380  
   381  // IsSubclass returns true if the type o is a subtype of classinfo or a subtype
   382  // of an element in classinfo (if classinfo is a tuple). It returns false
   383  // otherwise. The argument o must be a type and classinfo must be a type or a
   384  // tuple whose elements are types like the issubclass() Python builtin.
   385  func IsSubclass(f *Frame, o *Object, classinfo *Object) (bool, *BaseException) {
   386  	if !o.isInstance(TypeType) {
   387  		return false, f.RaiseType(TypeErrorType, "issubclass() arg 1 must be a class")
   388  	}
   389  	t := toTypeUnsafe(o)
   390  	errorMsg := "classinfo must be a type or tuple of types"
   391  	if classinfo.isInstance(TypeType) {
   392  		return t.isSubclass(toTypeUnsafe(classinfo)), nil
   393  	}
   394  	if !classinfo.isInstance(TupleType) {
   395  		return false, f.RaiseType(TypeErrorType, errorMsg)
   396  	}
   397  	for _, elem := range toTupleUnsafe(classinfo).elems {
   398  		if !elem.isInstance(TypeType) {
   399  			return false, f.RaiseType(TypeErrorType, errorMsg)
   400  		}
   401  		if t.isSubclass(toTypeUnsafe(elem)) {
   402  			return true, nil
   403  		}
   404  	}
   405  	return false, nil
   406  }
   407  
   408  // IsTrue returns the truthiness of o according to the __nonzero__ operator.
   409  func IsTrue(f *Frame, o *Object) (bool, *BaseException) {
   410  	switch o {
   411  	case True.ToObject():
   412  		return true, nil
   413  	case False.ToObject(), None:
   414  		return false, nil
   415  	}
   416  	nonzero := o.typ.slots.NonZero
   417  	if nonzero != nil {
   418  		r, raised := nonzero.Fn(f, o)
   419  		if raised != nil {
   420  			return false, raised
   421  		}
   422  		if r.isInstance(IntType) {
   423  			return toIntUnsafe(r).IsTrue(), nil
   424  		}
   425  		msg := fmt.Sprintf("__nonzero__ should return bool, returned %s", r.typ.Name())
   426  		return false, f.RaiseType(TypeErrorType, msg)
   427  	}
   428  	if o.typ.slots.Len != nil {
   429  		l, raised := Len(f, o)
   430  		if raised != nil {
   431  			return false, raised
   432  		}
   433  		return l.IsTrue(), nil
   434  	}
   435  	return true, nil
   436  }
   437  
   438  // ISub returns the result of v.__isub__ if defined, otherwise falls back to
   439  // sub.
   440  func ISub(f *Frame, v, w *Object) (*Object, *BaseException) {
   441  	if isub := v.typ.slots.ISub; isub != nil {
   442  		return isub.Fn(f, v, w)
   443  	}
   444  	return Sub(f, v, w)
   445  }
   446  
   447  // Iter implements the Python iter() builtin. It returns an iterator for o if
   448  // o is iterable. Otherwise it raises TypeError.
   449  // Note that the iter(f, sentinel) form is not yet supported.
   450  func Iter(f *Frame, o *Object) (*Object, *BaseException) {
   451  	// TODO: Support iter(f, sentinel) usage.
   452  	iter := o.typ.slots.Iter
   453  	if iter != nil {
   454  		return iter.Fn(f, o)
   455  	}
   456  	if o.typ.slots.GetItem != nil {
   457  		return newSeqIterator(o), nil
   458  	}
   459  	return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("'%s' object is not iterable", o.typ.Name()))
   460  }
   461  
   462  // IXor returns the result of v.__ixor__ if defined, otherwise falls back to
   463  // Xor.
   464  func IXor(f *Frame, v, w *Object) (*Object, *BaseException) {
   465  	return inplaceOp(f, v, w, v.typ.slots.IXor, Xor)
   466  }
   467  
   468  // LE returns the result of operation v <= w.
   469  func LE(f *Frame, v, w *Object) (*Object, *BaseException) {
   470  	r, raised := compareRich(f, compareOpLE, v, w)
   471  	if raised != nil {
   472  		return nil, raised
   473  	}
   474  	if r != NotImplemented {
   475  		return r, nil
   476  	}
   477  	return GetBool(compareDefault(f, v, w) <= 0).ToObject(), nil
   478  }
   479  
   480  // Len returns the length of the given sequence object.
   481  func Len(f *Frame, o *Object) (*Int, *BaseException) {
   482  	lenSlot := o.typ.slots.Len
   483  	if lenSlot == nil {
   484  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("object of type '%s' has no len()", o.typ.Name()))
   485  	}
   486  	r, raised := lenSlot.Fn(f, o)
   487  	if raised != nil {
   488  		return nil, raised
   489  	}
   490  	if !r.isInstance(IntType) {
   491  		return nil, f.RaiseType(TypeErrorType, "an integer is required")
   492  	}
   493  	return toIntUnsafe(r), nil
   494  }
   495  
   496  // LShift returns the result of v << w according to the __lshift/rlshift__
   497  // operator.
   498  func LShift(f *Frame, v, w *Object) (*Object, *BaseException) {
   499  	return binaryOp(f, v, w, v.typ.slots.LShift, v.typ.slots.RLShift, w.typ.slots.RLShift, "<<")
   500  }
   501  
   502  // LT returns the result of operation v < w.
   503  func LT(f *Frame, v, w *Object) (*Object, *BaseException) {
   504  	r, raised := compareRich(f, compareOpLT, v, w)
   505  	if raised != nil {
   506  		return nil, raised
   507  	}
   508  	if r != NotImplemented {
   509  		return r, nil
   510  	}
   511  	return GetBool(compareDefault(f, v, w) < 0).ToObject(), nil
   512  }
   513  
   514  // Mod returns the remainder from the division of v by w according to the
   515  // __mod/rmod__ operator.
   516  func Mod(f *Frame, v, w *Object) (*Object, *BaseException) {
   517  	return binaryOp(f, v, w, v.typ.slots.Mod, v.typ.slots.RMod, w.typ.slots.RMod, "%")
   518  }
   519  
   520  // Mul returns the result of multiplying v and w together according to the
   521  // __mul/rmul__ operator.
   522  func Mul(f *Frame, v, w *Object) (*Object, *BaseException) {
   523  	return binaryOp(f, v, w, v.typ.slots.Mul, v.typ.slots.RMul, w.typ.slots.RMul, "*")
   524  }
   525  
   526  // Pow returns the result of x**y, the base-x exponential of y according to the
   527  // __pow/rpow__ operator.
   528  func Pow(f *Frame, v, w *Object) (*Object, *BaseException) {
   529  	return binaryOp(f, v, w, v.typ.slots.Pow, v.typ.slots.RPow, w.typ.slots.RPow, "**")
   530  }
   531  
   532  // Or returns the result of the bitwise or operator v | w according to
   533  // __or/ror__.
   534  func Or(f *Frame, v, w *Object) (*Object, *BaseException) {
   535  	return binaryOp(f, v, w, v.typ.slots.Or, v.typ.slots.ROr, w.typ.slots.ROr, "|")
   536  }
   537  
   538  // Index returns the o converted to a Python int or long according to o's
   539  // __index__ slot.
   540  func Index(f *Frame, o *Object) (*Object, *BaseException) {
   541  	if o.isInstance(IntType) || o.isInstance(LongType) {
   542  		return o, nil
   543  	}
   544  	index := o.typ.slots.Index
   545  	if index == nil {
   546  		return nil, nil
   547  	}
   548  	i, raised := index.Fn(f, o)
   549  	if raised != nil {
   550  		return nil, raised
   551  	}
   552  	if !i.isInstance(IntType) && !i.isInstance(LongType) {
   553  		format := "__index__ returned non-(int,long) (type %s)"
   554  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(format, i.typ.Name()))
   555  	}
   556  	return i, nil
   557  }
   558  
   559  // IndexInt returns the value of o converted to a Go int according to o's
   560  // __index__ slot.
   561  // It raises a TypeError if o doesn't have an __index__ method.
   562  func IndexInt(f *Frame, o *Object) (i int, raised *BaseException) {
   563  	if index := o.typ.slots.Index; index != nil {
   564  		// Unwrap __index__ slot and fall through.
   565  		o, raised = index.Fn(f, o)
   566  		if raised != nil {
   567  			return 0, raised
   568  		}
   569  	}
   570  	if o.isInstance(IntType) {
   571  		return toIntUnsafe(o).Value(), nil
   572  	}
   573  	if o.isInstance(LongType) {
   574  		l := toLongUnsafe(o).Value()
   575  		// Anything bigger than maxIntBig will treat as maxIntBig.
   576  		if !numInIntRange(l) {
   577  			l = maxIntBig
   578  		}
   579  		return int(l.Int64()), nil
   580  	}
   581  	return 0, f.RaiseType(TypeErrorType, errBadSliceIndex)
   582  }
   583  
   584  // Invoke calls the given callable with the positional arguments given by args
   585  // and *varargs, and the keyword arguments by keywords and **kwargs. It first
   586  // packs the arguments into slices for the positional and keyword arguments,
   587  // then it passes those to *Object.Call.
   588  func Invoke(f *Frame, callable *Object, args Args, varargs *Object, keywords KWArgs, kwargs *Object) (*Object, *BaseException) {
   589  	if varargs != nil {
   590  		raised := seqApply(f, varargs, func(elems []*Object, _ bool) *BaseException {
   591  			numArgs := len(args)
   592  			packed := make([]*Object, numArgs+len(elems))
   593  			copy(packed, args)
   594  			copy(packed[numArgs:], elems)
   595  			args = packed
   596  			return nil
   597  		})
   598  		if raised != nil {
   599  			return nil, raised
   600  		}
   601  	}
   602  	if kwargs != nil {
   603  		if !kwargs.isInstance(DictType) {
   604  			format := "argument after ** must be a dict, not %s"
   605  			return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(format, kwargs.typ.Name()))
   606  		}
   607  		kwargsDict := toDictUnsafe(kwargs)
   608  		numKeywords := len(keywords)
   609  		numKwargs, raised := Len(f, kwargs)
   610  		if raised != nil {
   611  			return nil, raised
   612  		}
   613  		// Don't bother synchronizing access to len(kwargs) since it's just a
   614  		// hint and it doesn't matter if it's a little off.
   615  		packed := make(KWArgs, numKeywords, numKeywords+numKwargs.Value())
   616  		copy(packed, keywords)
   617  		raised = seqForEach(f, kwargs, func(o *Object) *BaseException {
   618  			if !o.isInstance(StrType) {
   619  				return f.RaiseType(TypeErrorType, "keywords must be strings")
   620  			}
   621  			s := toStrUnsafe(o).Value()
   622  			// Search for dupes linearly assuming small number of keywords.
   623  			for _, kw := range keywords {
   624  				if kw.Name == s {
   625  					format := "got multiple values for keyword argument '%s'"
   626  					return f.RaiseType(TypeErrorType, fmt.Sprintf(format, s))
   627  				}
   628  			}
   629  			item, raised := kwargsDict.GetItem(f, o)
   630  			if raised != nil {
   631  				return raised
   632  			}
   633  			if item == nil {
   634  				return raiseKeyError(f, o)
   635  			}
   636  			packed = append(packed, KWArg{Name: s, Value: item})
   637  			return nil
   638  		})
   639  		if raised != nil {
   640  			return nil, raised
   641  		}
   642  		keywords = packed
   643  	}
   644  	return callable.Call(f, args, keywords)
   645  }
   646  
   647  // NE returns the non-equality of v and w according to the __ne__ operator.
   648  func NE(f *Frame, v, w *Object) (*Object, *BaseException) {
   649  	r, raised := compareRich(f, compareOpNE, v, w)
   650  	if raised != nil {
   651  		return nil, raised
   652  	}
   653  	if r != NotImplemented {
   654  		return r, nil
   655  	}
   656  	return GetBool(compareDefault(f, v, w) != 0).ToObject(), nil
   657  }
   658  
   659  // Next implements the Python next() builtin. It calls next on the provided
   660  // iterator. It raises TypeError if iter is not an iterator object.
   661  // Note that the next(it, default) form is not yet supported.
   662  func Next(f *Frame, iter *Object) (*Object, *BaseException) {
   663  	// TODO: Support next(it, default) usage.
   664  	next := iter.typ.slots.Next
   665  	if next == nil {
   666  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("%s object is not an iterator", iter.typ.Name()))
   667  	}
   668  	return next.Fn(f, iter)
   669  }
   670  
   671  // Oct returns the result of o.__oct__ if defined.
   672  func Oct(f *Frame, o *Object) (*Object, *BaseException) {
   673  	oct := o.typ.slots.Oct
   674  	if oct == nil {
   675  		raised := f.RaiseType(TypeErrorType, "oct() argument can't be converted to oct")
   676  		return nil, raised
   677  	}
   678  	o, raised := oct.Fn(f, o)
   679  	if raised != nil {
   680  		return nil, raised
   681  	}
   682  	if !o.isInstance(StrType) {
   683  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__oct__ returned non-string (type %s)", o.typ.name))
   684  	}
   685  	return o, nil
   686  }
   687  
   688  // Pos returns the result of o.__pos__ and is equivalent to the Python
   689  // expression "+o".
   690  func Pos(f *Frame, o *Object) (*Object, *BaseException) {
   691  	pos := o.typ.slots.Pos
   692  	if pos == nil {
   693  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary +: '%s'", o.typ.Name()))
   694  	}
   695  	return pos.Fn(f, o)
   696  }
   697  
   698  // Print implements the Python print statement. It calls str() on the given args
   699  // and outputs the results to stdout separated by spaces. Similar to the Python
   700  // print statement.
   701  func Print(f *Frame, args Args, nl bool) *BaseException {
   702  	// TODO: Support outputting to files other than stdout and softspace.
   703  	var end string
   704  	if nl {
   705  		end = "\n"
   706  	} else if len(args) > 0 {
   707  		end = " "
   708  	}
   709  	return pyPrint(f, args, " ", end, Stdout)
   710  }
   711  
   712  // Repr returns a string containing a printable representation of o. This is
   713  // equivalent to the Python expression "repr(o)".
   714  func Repr(f *Frame, o *Object) (*Str, *BaseException) {
   715  	repr := o.typ.slots.Repr
   716  	if repr == nil {
   717  		s, raised := o.typ.FullName(f)
   718  		if raised != nil {
   719  			return nil, raised
   720  		}
   721  		return NewStr(fmt.Sprintf("<%s object at %p>", s, o)), nil
   722  	}
   723  	r, raised := repr.Fn(f, o)
   724  	if raised != nil {
   725  		return nil, raised
   726  	}
   727  	if !r.isInstance(StrType) {
   728  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__repr__ returned non-string (type %s)", r.typ.Name()))
   729  	}
   730  	return toStrUnsafe(r), nil
   731  }
   732  
   733  // ResolveClass resolves name in the class dict given by class, falling back to
   734  // the provided local if it is non-nil, otherwise falling back to globals.
   735  // This is used by the code generator to resolve names in the context of a class
   736  // definition. If the class definition occurs in a closure in which a local of
   737  // the given name is present then local will be non-nil, otherwise it will be
   738  // nil.
   739  func ResolveClass(f *Frame, class *Dict, local *Object, name *Str) (*Object, *BaseException) {
   740  	if value, raised := class.GetItem(f, name.ToObject()); raised != nil || value != nil {
   741  		return value, raised
   742  	}
   743  	if local != nil {
   744  		if raised := CheckLocal(f, local, name.Value()); raised != nil {
   745  			return nil, raised
   746  		}
   747  		return local, nil
   748  	}
   749  	return ResolveGlobal(f, name)
   750  }
   751  
   752  // ResolveGlobal looks up name in the frame's dict of global variables or in
   753  // the Builtins dict if absent. It raises NameError when absent from both.
   754  func ResolveGlobal(f *Frame, name *Str) (*Object, *BaseException) {
   755  	if value, raised := f.Globals().GetItem(f, name.ToObject()); raised != nil || value != nil {
   756  		return value, raised
   757  	}
   758  	value, raised := Builtins.GetItem(f, name.ToObject())
   759  	if raised != nil {
   760  		return nil, raised
   761  	}
   762  	if value == nil {
   763  		return nil, f.RaiseType(NameErrorType, fmt.Sprintf("name '%s' is not defined", name.Value()))
   764  	}
   765  	return value, nil
   766  }
   767  
   768  // RShift returns the result of v >> w according to the __rshift/rrshift__
   769  // operator.
   770  func RShift(f *Frame, v, w *Object) (*Object, *BaseException) {
   771  	return binaryOp(f, v, w, v.typ.slots.RShift, v.typ.slots.RRShift, w.typ.slots.RRShift, ">>")
   772  }
   773  
   774  // CheckLocal validates that the local variable with the given name and value
   775  // has been bound and raises UnboundLocalError if not.
   776  func CheckLocal(f *Frame, value *Object, name string) *BaseException {
   777  	if value == UnboundLocal {
   778  		format := "local variable '%s' referenced before assignment"
   779  		return f.RaiseType(UnboundLocalErrorType, fmt.Sprintf(format, name))
   780  	}
   781  	return nil
   782  }
   783  
   784  // SetAttr sets the attribute of o given by name to value. Equivalent to the
   785  // Python expression setattr(o, name, value).
   786  func SetAttr(f *Frame, o *Object, name *Str, value *Object) *BaseException {
   787  	setAttr := o.typ.slots.SetAttr
   788  	if setAttr == nil {
   789  		return f.RaiseType(SystemErrorType, fmt.Sprintf("'%s' object has no __setattr__ method", o.typ.Name()))
   790  	}
   791  	return setAttr.Fn(f, o, name, value)
   792  }
   793  
   794  // SetItem performs the operation o[key] = value.
   795  func SetItem(f *Frame, o, key, value *Object) *BaseException {
   796  	setItem := o.typ.slots.SetItem
   797  	if setItem == nil {
   798  		return f.RaiseType(TypeErrorType, fmt.Sprintf("'%s' object has no attribute '__setitem__'", o.typ.Name()))
   799  	}
   800  	return setItem.Fn(f, o, key, value)
   801  }
   802  
   803  // StartThread runs callable in a new goroutine.
   804  func StartThread(callable *Object) {
   805  	go func() {
   806  		atomic.AddInt64(&ThreadCount, 1)
   807  		defer atomic.AddInt64(&ThreadCount, -1)
   808  		f := NewRootFrame()
   809  		_, raised := callable.Call(f, nil, nil)
   810  		if raised != nil {
   811  			Stderr.writeString(FormatExc(f))
   812  		}
   813  	}()
   814  }
   815  
   816  // Sub returns the result of subtracting v from w according to the
   817  // __sub/rsub__ operator.
   818  func Sub(f *Frame, v, w *Object) (*Object, *BaseException) {
   819  	return binaryOp(f, v, w, v.typ.slots.Sub, v.typ.slots.RSub, w.typ.slots.RSub, "-")
   820  }
   821  
   822  // TieTarget is a data structure used to facilitate iterator unpacking in
   823  // assignment statements. A TieTarget should have one of Target or Children
   824  // populated but not both.
   825  //
   826  // As an example, the targets in the Python assignment 'foo, bar = ...'
   827  // could be represented as:
   828  //
   829  // 	TieTarget{
   830  // 		Children: []TieTarget{{Target: &foo}, {Target: &bar}},
   831  // 	}
   832  type TieTarget struct {
   833  	// Target is a destination pointer where an unpacked value will be
   834  	// stored.
   835  	Target **Object
   836  	// Children contains a sequence of TieTargets that should be unpacked
   837  	// into.
   838  	Children []TieTarget
   839  }
   840  
   841  // Tie takes a (possibly nested) TieTarget and recursively unpacks the
   842  // elements of o by iteration, assigning the results to the Target fields of t.
   843  // If the structure of o is not suitable to be unpacked into t, then an
   844  // exception is raised.
   845  func Tie(f *Frame, t TieTarget, o *Object) *BaseException {
   846  	if t.Target != nil {
   847  		*t.Target = o
   848  		return nil
   849  	}
   850  	iter, raised := Iter(f, o)
   851  	if raised != nil {
   852  		return raised
   853  	}
   854  	for i, child := range t.Children {
   855  		if value, raised := Next(f, iter); raised == nil {
   856  			if raised := Tie(f, child, value); raised != nil {
   857  				return raised
   858  			}
   859  		} else if raised.isInstance(StopIterationType) {
   860  			return f.RaiseType(ValueErrorType, fmt.Sprintf("need more than %d values to unpack", i))
   861  		} else {
   862  			return raised
   863  		}
   864  	}
   865  	_, raised = Next(f, iter)
   866  	if raised == nil {
   867  		return f.RaiseType(ValueErrorType, "too many values to unpack")
   868  	}
   869  	if !raised.isInstance(StopIterationType) {
   870  		return raised
   871  	}
   872  	f.RestoreExc(nil, nil)
   873  	return nil
   874  }
   875  
   876  // ToInt converts o to an integer type according to the __int__ slot. If the
   877  // result is not an int or long, then an exception is raised.
   878  func ToInt(f *Frame, o *Object) (*Object, *BaseException) {
   879  	if o.typ == IntType || o.typ == LongType {
   880  		return o, nil
   881  	}
   882  	intSlot := o.typ.slots.Int
   883  	if intSlot == nil {
   884  		return nil, f.RaiseType(TypeErrorType, "an integer is required")
   885  	}
   886  	i, raised := intSlot.Fn(f, o)
   887  	if raised != nil {
   888  		return nil, raised
   889  	}
   890  	if i.isInstance(IntType) || i.isInstance(LongType) {
   891  		return i, nil
   892  	}
   893  	return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__int__ returned non-int (type %s)", i.typ.Name()))
   894  }
   895  
   896  // ToIntValue converts o to an integer according to the __int__ slot. If the
   897  // result is not an int or long, or if the long value is too large to fit into
   898  // an int, then an exception is raised.
   899  func ToIntValue(f *Frame, o *Object) (int, *BaseException) {
   900  	i, raised := ToInt(f, o)
   901  	if raised != nil {
   902  		return 0, raised
   903  	}
   904  	if i.isInstance(IntType) {
   905  		return toIntUnsafe(i).Value(), nil
   906  	}
   907  	return toLongUnsafe(i).IntValue(f)
   908  }
   909  
   910  // ToNative converts o to a native Go object according to the __native__
   911  // operator.
   912  func ToNative(f *Frame, o *Object) (reflect.Value, *BaseException) {
   913  	if native := o.typ.slots.Native; native != nil {
   914  		return native.Fn(f, o)
   915  	}
   916  	return reflect.ValueOf(o), nil
   917  }
   918  
   919  // ToStr is a convenience function for calling "str(o)".
   920  func ToStr(f *Frame, o *Object) (*Str, *BaseException) {
   921  	result, raised := StrType.Call(f, []*Object{o}, nil)
   922  	if raised != nil {
   923  		return nil, raised
   924  	}
   925  	if !result.isInstance(StrType) {
   926  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("__str__ returned non-string (type %s)", result.typ.Name()))
   927  	}
   928  	return toStrUnsafe(result), nil
   929  }
   930  
   931  // Neg returns the result of o.__neg__ and is equivalent to the Python
   932  // expression "-o".
   933  func Neg(f *Frame, o *Object) (*Object, *BaseException) {
   934  	neg := o.typ.slots.Neg
   935  	if neg == nil {
   936  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary -: '%s'", o.typ.Name()))
   937  	}
   938  	return neg.Fn(f, o)
   939  }
   940  
   941  // Xor returns the result of the bitwise xor operator v ^ w according to
   942  // __xor/rxor__.
   943  func Xor(f *Frame, v, w *Object) (*Object, *BaseException) {
   944  	return binaryOp(f, v, w, v.typ.slots.Xor, v.typ.slots.RXor, w.typ.slots.RXor, "^")
   945  }
   946  
   947  const (
   948  	errResultTooLarge     = "result too large"
   949  	errUnsupportedOperand = "unsupported operand type(s) for %s: '%s' and '%s'"
   950  )
   951  
   952  // binaryOp picks an appropriate operator method (op or rop) from v or w and
   953  // returns its result. It raises TypeError if no appropriate method is found.
   954  // It is similar to CPython's binary_op1 function from abstract.c.
   955  func binaryOp(f *Frame, v, w *Object, op, vrop, wrop *binaryOpSlot, opName string) (*Object, *BaseException) {
   956  	if v.typ != w.typ && w.typ.isSubclass(v.typ) {
   957  		// w is an instance of a subclass of type(v), so prefer w's more
   958  		// specific rop, but only if it is overridden (wrop != vrop).
   959  		if wrop != nil && wrop != vrop {
   960  			r, raised := wrop.Fn(f, w, v)
   961  			if raised != nil {
   962  				return nil, raised
   963  			}
   964  			if r != NotImplemented {
   965  				return r, nil
   966  			}
   967  		}
   968  	}
   969  	if op != nil {
   970  		r, raised := op.Fn(f, v, w)
   971  		if raised != nil {
   972  			return nil, raised
   973  		}
   974  		if r != NotImplemented {
   975  			return r, nil
   976  		}
   977  	}
   978  	if wrop != nil {
   979  		r, raised := wrop.Fn(f, w, v)
   980  		if raised != nil {
   981  			return nil, raised
   982  		}
   983  		if r != NotImplemented {
   984  			return r, nil
   985  		}
   986  	}
   987  	return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(errUnsupportedOperand, opName, v.typ.Name(), w.typ.Name()))
   988  }
   989  
   990  func inplaceOp(f *Frame, v, w *Object, slot *binaryOpSlot, fallback binaryOpFunc) (*Object, *BaseException) {
   991  	if slot != nil {
   992  		return slot.Fn(f, v, w)
   993  	}
   994  	return fallback(f, v, w)
   995  }
   996  
   997  type compareOp int
   998  
   999  const (
  1000  	compareOpLT compareOp = iota
  1001  	compareOpLE
  1002  	compareOpEq
  1003  	compareOpNE
  1004  	compareOpGE
  1005  	compareOpGT
  1006  )
  1007  
  1008  var compareOpSwapped = []compareOp{
  1009  	compareOpGT,
  1010  	compareOpGE,
  1011  	compareOpEq,
  1012  	compareOpNE,
  1013  	compareOpLE,
  1014  	compareOpLT,
  1015  }
  1016  
  1017  func (op compareOp) swapped() compareOp {
  1018  	return compareOpSwapped[op]
  1019  }
  1020  
  1021  func (op compareOp) slot(t *Type) *binaryOpSlot {
  1022  	switch op {
  1023  	case compareOpLT:
  1024  		return t.slots.LT
  1025  	case compareOpLE:
  1026  		return t.slots.LE
  1027  	case compareOpEq:
  1028  		return t.slots.Eq
  1029  	case compareOpNE:
  1030  		return t.slots.NE
  1031  	case compareOpGE:
  1032  		return t.slots.GE
  1033  	case compareOpGT:
  1034  		return t.slots.GT
  1035  	}
  1036  	panic(fmt.Sprintf("invalid compareOp value: %d", op))
  1037  }
  1038  
  1039  func compareRich(f *Frame, op compareOp, v, w *Object) (*Object, *BaseException) {
  1040  	r, raised := tryRichCompare(f, op, v, w)
  1041  	if raised != nil {
  1042  		return nil, raised
  1043  	}
  1044  	if r != NotImplemented {
  1045  		return r, nil
  1046  	}
  1047  	return try3wayToRichCompare(f, op, v, w)
  1048  }
  1049  
  1050  // convert3wayToObject converts the integer results from a 3-way
  1051  // comparison to a suitable boolean value for the given rich
  1052  // comparison op.
  1053  func convert3wayToObject(op compareOp, c int) *Object {
  1054  	b := false
  1055  	switch op {
  1056  	case compareOpLT:
  1057  		b = c < 0
  1058  	case compareOpLE:
  1059  		b = c <= 0
  1060  	case compareOpEq:
  1061  		b = c == 0
  1062  	case compareOpNE:
  1063  		b = c != 0
  1064  	case compareOpGE:
  1065  		b = c >= 0
  1066  	case compareOpGT:
  1067  		b = c > 0
  1068  	}
  1069  	return GetBool(b).ToObject()
  1070  }
  1071  
  1072  // try3wayToRichCompare tries to perform a rich comparison operation on the given objects
  1073  // with the given comparison op using 3-way comparison. It closely resembles the behavior
  1074  // of CPython's try_3way_to_rich_compare in object.c.
  1075  func try3wayToRichCompare(f *Frame, op compareOp, v, w *Object) (*Object, *BaseException) {
  1076  	r, raised := try3wayCompare(f, v, w)
  1077  	if raised != nil {
  1078  		return nil, raised
  1079  	}
  1080  	c := 0
  1081  	if r == NotImplemented {
  1082  		c = compareDefault(f, v, w)
  1083  	} else {
  1084  		c = toIntUnsafe(r).Value()
  1085  	}
  1086  	return convert3wayToObject(op, c), nil
  1087  }
  1088  
  1089  // tryRichCompare tries to perform a rich comparison operation on the given
  1090  // objects with the given comparison op using the rich comparison methods.
  1091  // It closely resembles the behavior of CPython's try_rich_compare in object.c.
  1092  func tryRichCompare(f *Frame, op compareOp, v, w *Object) (*Object, *BaseException) {
  1093  	if v.typ != w.typ && w.typ.isSubclass(v.typ) {
  1094  		// type(w) is a subclass of type(v) so try to use w's
  1095  		// comparison operators since they're more specific.
  1096  		slot := op.swapped().slot(w.typ)
  1097  		if slot != nil {
  1098  			r, raised := slot.Fn(f, w, v)
  1099  			if raised != nil {
  1100  				return nil, raised
  1101  			}
  1102  			if r != NotImplemented {
  1103  				return r, nil
  1104  			}
  1105  		}
  1106  	}
  1107  	slot := op.slot(v.typ)
  1108  	if slot != nil {
  1109  		r, raised := slot.Fn(f, v, w)
  1110  		if raised != nil {
  1111  			return nil, raised
  1112  		}
  1113  		if r != NotImplemented {
  1114  			return r, nil
  1115  		}
  1116  	}
  1117  	slot = op.swapped().slot(w.typ)
  1118  	if slot != nil {
  1119  		return slot.Fn(f, w, v)
  1120  	}
  1121  	return NotImplemented, nil
  1122  }
  1123  
  1124  // compareDefault returns is the fallback logic for object comparison. It
  1125  // closely resembles the behavior of CPython's default_3way_compare in object.c.
  1126  func compareDefault(f *Frame, v, w *Object) int {
  1127  	if v.typ == w.typ {
  1128  		pv, pw := uintptr(v.toPointer()), uintptr(w.toPointer())
  1129  		if pv < pw {
  1130  			return -1
  1131  		}
  1132  		if pv == pw {
  1133  			return 0
  1134  		}
  1135  		return 1
  1136  	}
  1137  	if v == None {
  1138  		return -1
  1139  	}
  1140  	if w == None {
  1141  		return 1
  1142  	}
  1143  	// TODO: In default_3way_compare, the number type name is the empty
  1144  	// string so it evaluates less than non-number types. Once Grumpy
  1145  	// supports the concept of number types, add this behavior.
  1146  	if v.typ.Name() < w.typ.Name() {
  1147  		return -1
  1148  	}
  1149  	if v.typ.Name() != w.typ.Name() {
  1150  		return 1
  1151  	}
  1152  	if uintptr(v.typ.toPointer()) < uintptr(w.typ.toPointer()) {
  1153  		return -1
  1154  	}
  1155  	return 1
  1156  }
  1157  
  1158  // tryRichCompareBool tries a rich comparison with the given comparison op and
  1159  // returns a bool indicating if the relation is true. It closely resembles the
  1160  // behavior of CPython's try_rich_compare_bool in object.c.
  1161  func tryRichCompareBool(f *Frame, op compareOp, v, w *Object) (bool, *BaseException) {
  1162  	r, raised := tryRichCompare(f, op, v, w)
  1163  	if raised != nil {
  1164  		return false, raised
  1165  	}
  1166  	if r == NotImplemented {
  1167  		return false, nil
  1168  	}
  1169  	br, raised := IsTrue(f, r)
  1170  	if raised != nil {
  1171  		return false, raised
  1172  	}
  1173  	return br, raised
  1174  }
  1175  
  1176  // halfCompare tries a comparison with the __cmp__ slot, ensures the result
  1177  // is an integer, and returns it. It closely resembles the behavior of CPython's
  1178  // half_compare in typeobject.c.
  1179  func halfCompare(f *Frame, v, w *Object) (*Object, *BaseException) {
  1180  	cmp := v.typ.slots.Cmp
  1181  	r, raised := cmp.Fn(f, v, w)
  1182  	if raised != nil {
  1183  		return nil, raised
  1184  	}
  1185  	if !r.isInstance(IntType) {
  1186  		return nil, f.RaiseType(TypeErrorType, "an integer is required")
  1187  	}
  1188  	return r, nil
  1189  }
  1190  
  1191  // try3wayCompare tries a comparison with the __cmp__ slot with the given
  1192  // arguments. It first tries to use the __cmp__ slot on v and if that fails
  1193  // on w. It closely resembles the behavior of CPython's try_3way_compare in
  1194  // object.c.
  1195  func try3wayCompare(f *Frame, v, w *Object) (*Object, *BaseException) {
  1196  	cmp := v.typ.slots.Cmp
  1197  	if cmp != nil {
  1198  		return halfCompare(f, v, w)
  1199  	}
  1200  	cmp = w.typ.slots.Cmp
  1201  	if cmp != nil {
  1202  		r, raised := halfCompare(f, w, v)
  1203  		if raised != nil {
  1204  			return nil, raised
  1205  		}
  1206  		return intNeg(f, r)
  1207  	}
  1208  	return NotImplemented, nil
  1209  }
  1210  
  1211  // tryRichTo3wayCompare tries to compute a 3-way comparison in terms of
  1212  // the rich comparison operators (if they exist). It closely resembles
  1213  // the behavior of CPython's try_rich_to_3way_compare in object.c.
  1214  func tryRichTo3wayCompare(f *Frame, v, w *Object) (*Object, *BaseException) {
  1215  	var tries = []struct {
  1216  		op      compareOp
  1217  		outcome int
  1218  	}{
  1219  		{compareOpEq, 0},
  1220  		{compareOpLT, -1},
  1221  		{compareOpGT, 1},
  1222  	}
  1223  	for _, try := range tries {
  1224  		r, raised := tryRichCompareBool(f, try.op, v, w)
  1225  		if raised != nil {
  1226  			return nil, raised
  1227  		}
  1228  		if r {
  1229  			return NewInt(try.outcome).ToObject(), nil
  1230  		}
  1231  	}
  1232  	return NotImplemented, nil
  1233  }
  1234  
  1235  func checkFunctionArgs(f *Frame, function string, args Args, types ...*Type) *BaseException {
  1236  	if len(args) != len(types) {
  1237  		msg := fmt.Sprintf("'%s' requires %d arguments", function, len(types))
  1238  		return f.RaiseType(TypeErrorType, msg)
  1239  	}
  1240  	for i, t := range types {
  1241  		if !args[i].isInstance(t) {
  1242  			format := "'%s' requires a '%s' object but received a %q"
  1243  			return f.RaiseType(TypeErrorType, fmt.Sprintf(format, function, t.Name(), args[i].typ.Name()))
  1244  		}
  1245  	}
  1246  	return nil
  1247  }
  1248  
  1249  func checkFunctionVarArgs(f *Frame, function string, args Args, types ...*Type) *BaseException {
  1250  	if len(args) <= len(types) {
  1251  		return checkFunctionArgs(f, function, args, types...)
  1252  	}
  1253  	return checkFunctionArgs(f, function, args[:len(types)], types...)
  1254  }
  1255  
  1256  func checkMethodArgs(f *Frame, method string, args Args, types ...*Type) *BaseException {
  1257  	if len(args) != len(types) {
  1258  		msg := fmt.Sprintf("'%s' of '%s' requires %d arguments", method, types[0].Name(), len(types))
  1259  		return f.RaiseType(TypeErrorType, msg)
  1260  	}
  1261  	for i, t := range types {
  1262  		if !args[i].isInstance(t) {
  1263  			format := "'%s' requires a '%s' object but received a '%s'"
  1264  			return f.RaiseType(TypeErrorType, fmt.Sprintf(format, method, t.Name(), args[i].typ.Name()))
  1265  		}
  1266  	}
  1267  	return nil
  1268  }
  1269  
  1270  func checkMethodVarArgs(f *Frame, method string, args Args, types ...*Type) *BaseException {
  1271  	if len(args) <= len(types) {
  1272  		return checkMethodArgs(f, method, args, types...)
  1273  	}
  1274  	return checkMethodArgs(f, method, args[:len(types)], types...)
  1275  }
  1276  
  1277  func hashNotImplemented(f *Frame, o *Object) (*Object, *BaseException) {
  1278  	return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("unhashable type: '%s'", o.typ.Name()))
  1279  }
  1280  
  1281  // pyPrint encapsulates the logic of the Python print function.
  1282  func pyPrint(f *Frame, args Args, sep, end string, file *File) *BaseException {
  1283  	for i, arg := range args {
  1284  		if i > 0 {
  1285  			err := file.writeString(sep)
  1286  			if err != nil {
  1287  				return f.RaiseType(IOErrorType, err.Error())
  1288  			}
  1289  		}
  1290  
  1291  		s, raised := ToStr(f, arg)
  1292  		if raised != nil {
  1293  			return raised
  1294  		}
  1295  
  1296  		err := file.writeString(s.Value())
  1297  		if err != nil {
  1298  			return f.RaiseType(IOErrorType, err.Error())
  1299  		}
  1300  	}
  1301  
  1302  	err := file.writeString(end)
  1303  	if err != nil {
  1304  		return f.RaiseType(IOErrorType, err.Error())
  1305  	}
  1306  
  1307  	return nil
  1308  }