github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/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  // 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  }