Python: CG trace: Handle list-comprehension and iteration

Which relies on LOAD_CONST and MAKE_FUNCTION
This commit is contained in:
Rasmus Wriedt Larsen
2020-07-21 19:54:59 +02:00
parent 58f11194a8
commit 4e3ae98ddf
2 changed files with 40 additions and 5 deletions

View File

@@ -0,0 +1,7 @@
for i in range(10):
print(i)
[i + 1 for i in range(10)]
l = list(range(10))
[i + 1 for i in l]
[i + 1 for i in l]

View File

@@ -3,7 +3,7 @@ import dis
import logging
from dis import Instruction
from types import FrameType
from typing import List
from typing import Any, List
LOGGER = logging.getLogger(__name__)
@@ -18,6 +18,16 @@ class BytecodeExpr:
"""
@dataclasses.dataclass(frozen=True, eq=True, order=True)
class BytecodeConst(BytecodeExpr):
"""FOR LOAD_CONST"""
value: Any
def __str__(self):
return repr(self.value)
@dataclasses.dataclass(frozen=True, eq=True, order=True)
class BytecodeVariableName(BytecodeExpr):
name: str
@@ -51,6 +61,16 @@ class BytecodeUnknown(BytecodeExpr):
return f"<{self.opname}>"
@dataclasses.dataclass(frozen=True, eq=True, order=True)
class BytecodeMakeFunction(BytecodeExpr):
"""For MAKE_FUNCTION opcode"""
qualified_name: BytecodeExpr
def __str__(self):
return f"<MAKE_FUNCTION>(qualified_name={self.qualified_name})>"
def expr_that_added_elem_to_stack(
instructions: List[Instruction], start_index: int, stack_pos: int
):
@@ -101,6 +121,9 @@ def expr_from_instruction(instructions: List[Instruction], index: int) -> Byteco
if inst.opname in ["LOAD_GLOBAL", "LOAD_FAST", "LOAD_NAME"]:
return BytecodeVariableName(inst.argval)
elif inst.opname in ["LOAD_CONST"]:
return BytecodeConst(inst.argval)
# https://docs.python.org/3/library/dis.html#opcode-LOAD_METHOD
# https://docs.python.org/3/library/dis.html#opcode-LOAD_ATTR
elif inst.opname in ["LOAD_METHOD", "LOAD_ATTR"]:
@@ -122,11 +145,16 @@ def expr_from_instruction(instructions: List[Instruction], index: int) -> Byteco
)
return BytecodeCall(function=func_expr)
else:
# LOAD_BUILD_CLASS is included here intentionally for now, since I don't really
# know what to do about it.
elif inst.opname in ["MAKE_FUNCTION"]:
name_expr = expr_that_added_elem_to_stack(instructions, index - 1, 0)
assert isinstance(name_expr, BytecodeConst)
return BytecodeMakeFunction(qualified_name=name_expr)
# LOAD_BUILD_CLASS is included here intentionally for now, since I don't really
# know what to do about it.
if inst.opname not in ["LOAD_BUILD_CLASS"]:
LOGGER.warning(f"Don't know how to handle this type of instruction: {inst}")
return BytecodeUnknown(inst.opname)
return BytecodeUnknown(inst.opname)
def expr_from_frame(frame: FrameType) -> BytecodeExpr: