github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/set.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  	"reflect"
    20  )
    21  
    22  var (
    23  	// FrozenSetType is the object representing the Python 'set' type.
    24  	FrozenSetType = newBasisType("frozenset", reflect.TypeOf(FrozenSet{}), toFrozenSetUnsafe, ObjectType)
    25  	// SetType is the object representing the Python 'set' type.
    26  	SetType = newBasisType("set", reflect.TypeOf(Set{}), toSetUnsafe, ObjectType)
    27  )
    28  
    29  type setBase struct {
    30  	Object
    31  	dict *Dict
    32  }
    33  
    34  func (s *setBase) contains(f *Frame, key *Object) (bool, *BaseException) {
    35  	item, raised := s.dict.GetItem(f, key)
    36  	if raised != nil {
    37  		return false, raised
    38  	}
    39  	return item != nil, nil
    40  }
    41  
    42  func (s *setBase) isSubset(f *Frame, o *Object) (*Object, *BaseException) {
    43  	s2, raised := setFromSeq(f, o)
    44  	if raised != nil {
    45  		return nil, raised
    46  	}
    47  	return setCompare(f, compareOpLE, s, &s2.Object)
    48  }
    49  
    50  func (s *setBase) isSuperset(f *Frame, o *Object) (*Object, *BaseException) {
    51  	s2, raised := setFromSeq(f, o)
    52  	if raised != nil {
    53  		return nil, raised
    54  	}
    55  	return setCompare(f, compareOpGE, s, &s2.Object)
    56  }
    57  
    58  func (s *setBase) repr(f *Frame) (*Object, *BaseException) {
    59  	if f.reprEnter(&s.Object) {
    60  		return NewStr(fmt.Sprintf("%s(...)", s.typ.Name())).ToObject(), nil
    61  	}
    62  	repr, raised := Repr(f, s.dict.Keys(f).ToObject())
    63  	f.reprLeave(&s.Object)
    64  	if raised != nil {
    65  		return nil, raised
    66  	}
    67  	return NewStr(fmt.Sprintf("%s(%s)", s.typ.Name(), repr.Value())).ToObject(), nil
    68  }
    69  
    70  // Set represents Python 'set' objects.
    71  type Set setBase
    72  
    73  // NewSet returns an empty Set.
    74  func NewSet() *Set {
    75  	return &Set{Object{typ: SetType}, NewDict()}
    76  }
    77  
    78  func toSetUnsafe(o *Object) *Set {
    79  	return (*Set)(o.toPointer())
    80  }
    81  
    82  // Add inserts key into s. If key already exists then does nothing.
    83  func (s *Set) Add(f *Frame, key *Object) (bool, *BaseException) {
    84  	origin, raised := s.dict.putItem(f, key, None, true)
    85  	if raised != nil {
    86  		return false, raised
    87  	}
    88  	return origin == nil, nil
    89  }
    90  
    91  // Contains returns true if key exists in s.
    92  func (s *Set) Contains(f *Frame, key *Object) (bool, *BaseException) {
    93  	return (*setBase)(s).contains(f, key)
    94  }
    95  
    96  // Remove erases key from s. If key is not in s then raises KeyError.
    97  func (s *Set) Remove(f *Frame, key *Object) (bool, *BaseException) {
    98  	return s.dict.DelItem(f, key)
    99  }
   100  
   101  // ToObject upcasts s to an Object.
   102  func (s *Set) ToObject() *Object {
   103  	return &s.Object
   104  }
   105  
   106  // Update inserts all elements in the iterable o into s.
   107  func (s *Set) Update(f *Frame, o *Object) *BaseException {
   108  	raised := seqForEach(f, o, func(key *Object) *BaseException {
   109  		return s.dict.SetItem(f, key, None)
   110  	})
   111  	return raised
   112  }
   113  
   114  func setAdd(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   115  	if raised := checkMethodArgs(f, "add", args, SetType, ObjectType); raised != nil {
   116  		return nil, raised
   117  	}
   118  	if _, raised := toSetUnsafe(args[0]).Add(f, args[1]); raised != nil {
   119  		return nil, raised
   120  	}
   121  	return None, nil
   122  }
   123  
   124  func setContains(f *Frame, seq, value *Object) (*Object, *BaseException) {
   125  	contains, raised := toSetUnsafe(seq).Contains(f, value)
   126  	if raised != nil {
   127  		return nil, raised
   128  	}
   129  	return GetBool(contains).ToObject(), nil
   130  }
   131  
   132  func setDiscard(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   133  	if raised := checkMethodArgs(f, "discard", args, SetType, ObjectType); raised != nil {
   134  		return nil, raised
   135  	}
   136  	if _, raised := toSetUnsafe(args[0]).Remove(f, args[1]); raised != nil {
   137  		return nil, raised
   138  	}
   139  	return None, nil
   140  }
   141  
   142  func setEq(f *Frame, v, w *Object) (*Object, *BaseException) {
   143  	return setCompare(f, compareOpEq, (*setBase)(toSetUnsafe(v)), w)
   144  }
   145  
   146  func setGE(f *Frame, v, w *Object) (*Object, *BaseException) {
   147  	return setCompare(f, compareOpGE, (*setBase)(toSetUnsafe(v)), w)
   148  }
   149  
   150  func setGT(f *Frame, v, w *Object) (*Object, *BaseException) {
   151  	return setCompare(f, compareOpGT, (*setBase)(toSetUnsafe(v)), w)
   152  }
   153  
   154  func setInit(f *Frame, o *Object, args Args, _ KWArgs) (*Object, *BaseException) {
   155  	argc := len(args)
   156  	if argc > 1 {
   157  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("set expected at most 1 arguments, got %d", argc))
   158  	}
   159  	s := toSetUnsafe(o)
   160  	if argc == 1 {
   161  		if raised := s.Update(f, args[0]); raised != nil {
   162  			return nil, raised
   163  		}
   164  	}
   165  	return None, nil
   166  }
   167  
   168  func setIsSubset(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   169  	if raised := checkMethodArgs(f, "issubset", args, SetType, ObjectType); raised != nil {
   170  		return nil, raised
   171  	}
   172  	return (*setBase)(toSetUnsafe(args[0])).isSubset(f, args[1])
   173  }
   174  
   175  func setIsSuperset(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   176  	if raised := checkMethodArgs(f, "issuperset", args, SetType, ObjectType); raised != nil {
   177  		return nil, raised
   178  	}
   179  	return (*setBase)(toSetUnsafe(args[0])).isSuperset(f, args[1])
   180  }
   181  
   182  func setIter(f *Frame, o *Object) (*Object, *BaseException) {
   183  	s := toSetUnsafe(o)
   184  	s.dict.mutex.Lock(f)
   185  	iter := &newDictKeyIterator(s.dict).Object
   186  	s.dict.mutex.Unlock(f)
   187  	return iter, nil
   188  }
   189  
   190  func setLE(f *Frame, v, w *Object) (*Object, *BaseException) {
   191  	return setCompare(f, compareOpLE, (*setBase)(toSetUnsafe(v)), w)
   192  }
   193  
   194  func setLen(f *Frame, o *Object) (*Object, *BaseException) {
   195  	return NewInt(toSetUnsafe(o).dict.Len()).ToObject(), nil
   196  }
   197  
   198  func setLT(f *Frame, v, w *Object) (*Object, *BaseException) {
   199  	return setCompare(f, compareOpLT, (*setBase)(toSetUnsafe(v)), w)
   200  }
   201  
   202  func setNE(f *Frame, v, w *Object) (*Object, *BaseException) {
   203  	return setCompare(f, compareOpNE, (*setBase)(toSetUnsafe(v)), w)
   204  }
   205  
   206  func setNew(f *Frame, t *Type, _ Args, _ KWArgs) (*Object, *BaseException) {
   207  	s := toSetUnsafe(newObject(t))
   208  	s.dict = NewDict()
   209  	return s.ToObject(), nil
   210  }
   211  
   212  func setRemove(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   213  	if raised := checkMethodArgs(f, "remove", args, SetType, ObjectType); raised != nil {
   214  		return nil, raised
   215  	}
   216  	key := args[1]
   217  	if removed, raised := toSetUnsafe(args[0]).Remove(f, key); raised != nil {
   218  		return nil, raised
   219  	} else if !removed {
   220  		return nil, raiseKeyError(f, key)
   221  	}
   222  	return None, nil
   223  }
   224  
   225  func setRepr(f *Frame, o *Object) (*Object, *BaseException) {
   226  	return (*setBase)(toSetUnsafe(o)).repr(f)
   227  }
   228  
   229  func setUpdate(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   230  	if raised := checkMethodArgs(f, "update", args, SetType, ObjectType); raised != nil {
   231  		return nil, raised
   232  	}
   233  	if raised := toSetUnsafe(args[0]).Update(f, args[1]); raised != nil {
   234  		return nil, raised
   235  	}
   236  	return None, nil
   237  }
   238  
   239  func initSetType(dict map[string]*Object) {
   240  	dict["add"] = newBuiltinFunction("add", setAdd).ToObject()
   241  	dict["discard"] = newBuiltinFunction("discard", setDiscard).ToObject()
   242  	dict["issubset"] = newBuiltinFunction("issubset", setIsSubset).ToObject()
   243  	dict["issuperset"] = newBuiltinFunction("issuperset", setIsSuperset).ToObject()
   244  	dict["remove"] = newBuiltinFunction("remove", setRemove).ToObject()
   245  	dict["update"] = newBuiltinFunction("update", setUpdate).ToObject()
   246  	SetType.slots.Contains = &binaryOpSlot{setContains}
   247  	SetType.slots.Eq = &binaryOpSlot{setEq}
   248  	SetType.slots.GE = &binaryOpSlot{setGE}
   249  	SetType.slots.GT = &binaryOpSlot{setGT}
   250  	SetType.slots.Hash = &unaryOpSlot{hashNotImplemented}
   251  	SetType.slots.Init = &initSlot{setInit}
   252  	SetType.slots.Iter = &unaryOpSlot{setIter}
   253  	SetType.slots.LE = &binaryOpSlot{setLE}
   254  	SetType.slots.Len = &unaryOpSlot{setLen}
   255  	SetType.slots.LT = &binaryOpSlot{setLT}
   256  	SetType.slots.NE = &binaryOpSlot{setNE}
   257  	SetType.slots.New = &newSlot{setNew}
   258  	SetType.slots.Repr = &unaryOpSlot{setRepr}
   259  }
   260  
   261  // FrozenSet represents Python 'set' objects.
   262  type FrozenSet setBase
   263  
   264  func toFrozenSetUnsafe(o *Object) *FrozenSet {
   265  	return (*FrozenSet)(o.toPointer())
   266  }
   267  
   268  // Contains returns true if key exists in s.
   269  func (s *FrozenSet) Contains(f *Frame, key *Object) (bool, *BaseException) {
   270  	return (*setBase)(s).contains(f, key)
   271  }
   272  
   273  // ToObject upcasts s to an Object.
   274  func (s *FrozenSet) ToObject() *Object {
   275  	return &s.Object
   276  }
   277  
   278  func frozenSetContains(f *Frame, seq, value *Object) (*Object, *BaseException) {
   279  	contains, raised := toFrozenSetUnsafe(seq).Contains(f, value)
   280  	if raised != nil {
   281  		return nil, raised
   282  	}
   283  	return GetBool(contains).ToObject(), nil
   284  }
   285  
   286  func frozenSetEq(f *Frame, v, w *Object) (*Object, *BaseException) {
   287  	return setCompare(f, compareOpEq, (*setBase)(toFrozenSetUnsafe(v)), w)
   288  }
   289  
   290  func frozenSetGE(f *Frame, v, w *Object) (*Object, *BaseException) {
   291  	return setCompare(f, compareOpGE, (*setBase)(toFrozenSetUnsafe(v)), w)
   292  }
   293  
   294  func frozenSetGT(f *Frame, v, w *Object) (*Object, *BaseException) {
   295  	return setCompare(f, compareOpGT, (*setBase)(toFrozenSetUnsafe(v)), w)
   296  }
   297  
   298  func frozenSetIsSubset(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   299  	if raised := checkMethodArgs(f, "issubset", args, FrozenSetType, ObjectType); raised != nil {
   300  		return nil, raised
   301  	}
   302  	return (*setBase)(toFrozenSetUnsafe(args[0])).isSubset(f, args[1])
   303  }
   304  
   305  func frozenSetIsSuperset(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   306  	if raised := checkMethodArgs(f, "issuperset", args, FrozenSetType, ObjectType); raised != nil {
   307  		return nil, raised
   308  	}
   309  	return (*setBase)(toFrozenSetUnsafe(args[0])).isSuperset(f, args[1])
   310  }
   311  
   312  func frozenSetIter(f *Frame, o *Object) (*Object, *BaseException) {
   313  	s := toFrozenSetUnsafe(o)
   314  	s.dict.mutex.Lock(f)
   315  	iter := &newDictKeyIterator(s.dict).Object
   316  	s.dict.mutex.Unlock(f)
   317  	return iter, nil
   318  }
   319  
   320  func frozenSetLE(f *Frame, v, w *Object) (*Object, *BaseException) {
   321  	return setCompare(f, compareOpLE, (*setBase)(toFrozenSetUnsafe(v)), w)
   322  }
   323  
   324  func frozenSetLen(f *Frame, o *Object) (*Object, *BaseException) {
   325  	return NewInt(toFrozenSetUnsafe(o).dict.Len()).ToObject(), nil
   326  }
   327  
   328  func frozenSetLT(f *Frame, v, w *Object) (*Object, *BaseException) {
   329  	return setCompare(f, compareOpLT, (*setBase)(toFrozenSetUnsafe(v)), w)
   330  }
   331  
   332  func frozenSetNE(f *Frame, v, w *Object) (*Object, *BaseException) {
   333  	return setCompare(f, compareOpNE, (*setBase)(toFrozenSetUnsafe(v)), w)
   334  }
   335  
   336  func frozenSetNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) {
   337  	argc := len(args)
   338  	if argc > 1 {
   339  		format := "frozenset expected at most 1 arguments, got %d"
   340  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(format, argc))
   341  	}
   342  	s := toFrozenSetUnsafe(newObject(t))
   343  	s.dict = NewDict()
   344  	if argc == 1 {
   345  		raised := seqForEach(f, args[0], func(o *Object) *BaseException {
   346  			return s.dict.SetItem(f, o, None)
   347  		})
   348  		if raised != nil {
   349  			return nil, raised
   350  		}
   351  	}
   352  	return s.ToObject(), nil
   353  }
   354  
   355  func frozenSetRepr(f *Frame, o *Object) (*Object, *BaseException) {
   356  	return (*setBase)(toFrozenSetUnsafe(o)).repr(f)
   357  }
   358  
   359  func initFrozenSetType(dict map[string]*Object) {
   360  	dict["issubset"] = newBuiltinFunction("issubset", frozenSetIsSubset).ToObject()
   361  	dict["issuperset"] = newBuiltinFunction("issuperset", frozenSetIsSuperset).ToObject()
   362  	FrozenSetType.slots.Contains = &binaryOpSlot{frozenSetContains}
   363  	FrozenSetType.slots.Eq = &binaryOpSlot{frozenSetEq}
   364  	FrozenSetType.slots.GE = &binaryOpSlot{frozenSetGE}
   365  	FrozenSetType.slots.GT = &binaryOpSlot{frozenSetGT}
   366  	// TODO: Implement hash for frozenset.
   367  	FrozenSetType.slots.Hash = &unaryOpSlot{hashNotImplemented}
   368  	FrozenSetType.slots.Iter = &unaryOpSlot{frozenSetIter}
   369  	FrozenSetType.slots.LE = &binaryOpSlot{frozenSetLE}
   370  	FrozenSetType.slots.Len = &unaryOpSlot{frozenSetLen}
   371  	FrozenSetType.slots.LT = &binaryOpSlot{frozenSetLT}
   372  	FrozenSetType.slots.NE = &binaryOpSlot{frozenSetNE}
   373  	FrozenSetType.slots.New = &newSlot{frozenSetNew}
   374  	FrozenSetType.slots.Repr = &unaryOpSlot{frozenSetRepr}
   375  }
   376  
   377  func setCompare(f *Frame, op compareOp, v *setBase, w *Object) (*Object, *BaseException) {
   378  	var s2 *setBase
   379  	switch {
   380  	case w.isInstance(SetType):
   381  		s2 = (*setBase)(toSetUnsafe(w))
   382  	case w.isInstance(FrozenSetType):
   383  		s2 = (*setBase)(toFrozenSetUnsafe(w))
   384  	default:
   385  		return NotImplemented, nil
   386  	}
   387  	if op == compareOpGE || op == compareOpGT {
   388  		op = op.swapped()
   389  		v, s2 = s2, v
   390  	}
   391  	v.dict.mutex.Lock(f)
   392  	iter := newDictEntryIterator(v.dict)
   393  	g1 := newDictVersionGuard(v.dict)
   394  	len1 := v.dict.Len()
   395  	v.dict.mutex.Unlock(f)
   396  	s2.dict.mutex.Lock(f)
   397  	g2 := newDictVersionGuard(s2.dict)
   398  	len2 := s2.dict.Len()
   399  	s2.dict.mutex.Unlock(f)
   400  	result := (op != compareOpNE)
   401  	switch op {
   402  	case compareOpLT:
   403  		if len1 >= len2 {
   404  			return False.ToObject(), nil
   405  		}
   406  	case compareOpLE:
   407  		if len1 > len2 {
   408  			return False.ToObject(), nil
   409  		}
   410  	case compareOpEq, compareOpNE:
   411  		if len1 != len2 {
   412  			return GetBool(!result).ToObject(), nil
   413  		}
   414  	}
   415  	for key, _ := iter.next(); key != nil; key, _ = iter.next() {
   416  		contains, raised := s2.contains(f, key)
   417  		if raised != nil {
   418  			return nil, raised
   419  		}
   420  		if !contains {
   421  			result = !result
   422  			break
   423  		}
   424  	}
   425  	if !g1.check() || !g2.check() {
   426  		return nil, f.RaiseType(RuntimeErrorType, "set changed during iteration")
   427  	}
   428  	return GetBool(result).ToObject(), nil
   429  }
   430  
   431  func setFromSeq(f *Frame, seq *Object) (*setBase, *BaseException) {
   432  	switch {
   433  	case seq.isInstance(SetType):
   434  		return (*setBase)(toSetUnsafe(seq)), nil
   435  	case seq.isInstance(FrozenSetType):
   436  		return (*setBase)(toFrozenSetUnsafe(seq)), nil
   437  	}
   438  	o, raised := SetType.Call(f, Args{seq}, nil)
   439  	if raised != nil {
   440  		return nil, raised
   441  	}
   442  	return (*setBase)(toSetUnsafe(o)), nil
   443  }