github.com/pygolin/runtime@v0.0.0-20201208210830-a62e3cd39798/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 runtime 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 }