this repo has no description
at trunk 118 lines 4.0 kB view raw
1# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2class Opcode: 3 CMP_OP = ( 4 "<", 5 "<=", 6 "==", 7 "!=", 8 ">", 9 ">=", 10 "in", 11 "not in", 12 "is", 13 "is not", 14 "exception match", 15 "BAD", 16 ) 17 HAVE_ARGUMENT = 90 # Opcodes from here have an argument: 18 EXTENDED_ARG = 144 19 CODEUNIT_SIZE = 2 20 21 def __init__(self) -> None: 22 self.hasconst: set[int] = set() 23 self.hasname: set[int] = set() 24 self.hasjrel: set[int] = set() 25 self.hasjabs: set[int] = set() 26 self.haslocal: set[int] = set() 27 self.hascompare: set[int] = set() 28 self.hasfree: set[int] = set() 29 self.shadowop: set[int] = set() 30 31 self.opmap: dict[str, int] = {} 32 self.opname: list[str] = ["<%r>" % (op,) for op in range(256)] 33 self.stack_effects: dict[str, object] = {} 34 35 def stack_effect(self, opcode: int, oparg, jump: int) -> int: # pyre-ignore[2] 36 oparg_int = 0 37 if opcode >= self.HAVE_ARGUMENT: 38 if oparg is None: 39 raise ValueError( 40 "stack_effect: opcode requires oparg but oparg was not specified" 41 ) 42 oparg_int = int(oparg) 43 elif oparg is not None: 44 raise ValueError( 45 "stack_effect: opcode does not permit oparg but oparg was specified" 46 ) 47 jump_int = {None: -1, True: 1, False: 0}.get(jump) # pyre-ignore[6] 48 if jump_int is None: 49 raise ValueError("stack_effect: jump must be False, True or None") 50 opname = self.opname[opcode] 51 return self.stack_effect_raw(opname, oparg_int, jump_int) 52 53 def stack_effect_raw(self, opname: str, oparg, jump: int) -> int: # pyre-ignore[2] 54 effect = self.stack_effects.get(opname) 55 if effect is None: 56 raise ValueError( 57 f"Error, opcode {opname} was not found, please update opcode.stack_effects" 58 ) 59 if isinstance(effect, int): 60 return effect 61 else: 62 return effect(oparg, jump) # pyre-ignore[29] 63 64 def def_op(self, name: str, op: int) -> None: 65 self.opname[op] = name 66 self.opmap[name] = op 67 setattr(self, name, op) 68 69 def name_op(self, name: str, op: int) -> None: 70 self.def_op(name, op) 71 self.hasname.add(op) 72 73 def jrel_op(self, name: str, op: int) -> None: 74 self.def_op(name, op) 75 self.hasjrel.add(op) 76 77 def jabs_op(self, name: str, op: int) -> None: 78 self.def_op(name, op) 79 self.hasjabs.add(op) 80 81 def has_jump(self, op: int) -> bool: 82 return op in self.hasjrel or op in self.hasjabs 83 84 def shadow_op(self, name: str, op: int) -> None: 85 self.def_op(name, op) 86 self.shadowop.add(op) 87 88 def remove_op(self, opname: str) -> None: 89 op = self.opmap[opname] 90 self.hasconst.discard(op) 91 self.hasname.discard(op) 92 self.hasjrel.discard(op) 93 self.hasjabs.discard(op) 94 self.haslocal.discard(op) 95 self.hascompare.discard(op) 96 self.hasfree.discard(op) 97 self.shadowop.discard(op) 98 self.opmap.pop(opname) 99 self.opname[op] = None # pyre-ignore[6] 100 self.stack_effects.pop(opname) 101 delattr(self, opname) 102 103 def copy(self) -> "Opcode": 104 result = Opcode() 105 result.hasconst = self.hasconst.copy() 106 result.hasname = self.hasname.copy() 107 result.hasjrel = self.hasjrel.copy() 108 result.hasjabs = self.hasjabs.copy() 109 result.haslocal = self.haslocal.copy() 110 result.hascompare = self.hascompare.copy() 111 result.hasfree = self.hasfree.copy() 112 result.shadowop = self.shadowop.copy() 113 result.opmap = self.opmap.copy() 114 result.opname = self.opname.copy() 115 result.stack_effects = self.stack_effects.copy() 116 for name, op in self.opmap.items(): 117 setattr(result, name, op) 118 return result