33import logging
44from dis import Instruction
55from types import FrameType
6- from typing import List
6+ from typing import Any , List
77
88LOGGER = logging .getLogger (__name__ )
99
@@ -18,6 +18,16 @@ class BytecodeExpr:
1818 """
1919
2020
21+ @dataclasses .dataclass (frozen = True , eq = True , order = True )
22+ class BytecodeConst (BytecodeExpr ):
23+ """FOR LOAD_CONST"""
24+
25+ value : Any
26+
27+ def __str__ (self ):
28+ return repr (self .value )
29+
30+
2131@dataclasses .dataclass (frozen = True , eq = True , order = True )
2232class BytecodeVariableName (BytecodeExpr ):
2333 name : str
@@ -51,6 +61,16 @@ def __str__(self):
5161 return f"<{ self .opname } >"
5262
5363
64+ @dataclasses .dataclass (frozen = True , eq = True , order = True )
65+ class BytecodeMakeFunction (BytecodeExpr ):
66+ """For MAKE_FUNCTION opcode"""
67+
68+ qualified_name : BytecodeExpr
69+
70+ def __str__ (self ):
71+ return f"<MAKE_FUNCTION>(qualified_name={ self .qualified_name } )>"
72+
73+
5474def expr_that_added_elem_to_stack (
5575 instructions : List [Instruction ], start_index : int , stack_pos : int
5676):
@@ -101,6 +121,9 @@ def expr_from_instruction(instructions: List[Instruction], index: int) -> Byteco
101121 if inst .opname in ["LOAD_GLOBAL" , "LOAD_FAST" , "LOAD_NAME" ]:
102122 return BytecodeVariableName (inst .argval )
103123
124+ elif inst .opname in ["LOAD_CONST" ]:
125+ return BytecodeConst (inst .argval )
126+
104127 # https://docs.python.org/3/library/dis.html#opcode-LOAD_METHOD
105128 # https://docs.python.org/3/library/dis.html#opcode-LOAD_ATTR
106129 elif inst .opname in ["LOAD_METHOD" , "LOAD_ATTR" ]:
@@ -122,11 +145,16 @@ def expr_from_instruction(instructions: List[Instruction], index: int) -> Byteco
122145 )
123146 return BytecodeCall (function = func_expr )
124147
125- else :
126- # LOAD_BUILD_CLASS is included here intentionally for now, since I don't really
127- # know what to do about it.
148+ elif inst .opname in ["MAKE_FUNCTION" ]:
149+ name_expr = expr_that_added_elem_to_stack (instructions , index - 1 , 0 )
150+ assert isinstance (name_expr , BytecodeConst )
151+ return BytecodeMakeFunction (qualified_name = name_expr )
152+
153+ # LOAD_BUILD_CLASS is included here intentionally for now, since I don't really
154+ # know what to do about it.
155+ if inst .opname not in ["LOAD_BUILD_CLASS" ]:
128156 LOGGER .warning (f"Don't know how to handle this type of instruction: { inst } " )
129- return BytecodeUnknown (inst .opname )
157+ return BytecodeUnknown (inst .opname )
130158
131159
132160def expr_from_frame (frame : FrameType ) -> BytecodeExpr :
0 commit comments