Skip to content

Commit

Permalink
Merge pull request #2 from P403n1x87/feat/handle-pseudo-instructions
Browse files Browse the repository at this point in the history
feat: handle pseudo-instructions
  • Loading branch information
P403n1x87 authored Oct 3, 2023
2 parents 803d72c + a3f5fa0 commit 7017b3b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
16 changes: 15 additions & 1 deletion spasm/asm.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ def relocate(instrs: bc.Bytecode, lineno: int) -> bc.Bytecode:
return new_instrs


def transform_instruction(opcode: str, arg: t.Any = bc.UNSET) -> t.Tuple[str, t.Any]:
if sys.version_info >= (3, 12):
if opcode.upper() == "LOAD_METHOD":
opcode = "LOAD_ATTR"
arg = (True, arg)
elif opcode.upper() == "LOAD_ATTR" and not isinstance(arg, tuple):
arg = (False, arg)

return opcode, arg


class BaseOpArg(bc.Label):
# We cannot have arbitrary objects in Bytecode, so we subclass Label
def __init__(self, name: str, arg: str, lineno: t.Optional[int] = None) -> None:
Expand Down Expand Up @@ -236,7 +247,10 @@ def _parse_instruction(self, line: str) -> t.Optional[t.Union[bc.Instr, BindOpAr

return entry

return bc.Instr(self._parse_opcode(opcode), *map(self._parse_opcode_arg, args), lineno=self._lineno)
return bc.Instr(
*transform_instruction(self._parse_opcode(opcode), *map(self._parse_opcode_arg, args)),
lineno=self._lineno,
)

def _parse_code_begin(self, line: str) -> t.Optional[CodeBegin]:
try:
Expand Down
25 changes: 25 additions & 0 deletions tests/test_asm.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,28 @@ def test_assembly_sub_code():
exec(asm.compile(), _globals) # noqa: S102

assert _globals["greet"]("World") == "World"


@pytest.mark.skipif(sys.version_info[:2] < (3, 12), reason="CPython 3.12+ bytecode only")
def test_assembly_load_attr_transformation():
asm = Assembly()

asm.parse(
r"""
resume 0
load_const {arg}
load_method $foo
load_const {arg}
load_attr $foo
build_tuple 3
return_value
"""
)

class Foo:
def foo(self):
pass

f = Foo()

assert eval(asm.compile({"arg": f})) == (Foo.foo, f, f.foo) # noqa: S307

0 comments on commit 7017b3b

Please sign in to comment.