@@ -126,11 +126,8 @@ class Instruction(NamedTuple):
126126 arg: Optional numeric argument to operation (if any). Otherwise, None.
127127
128128 argval: resolved arg value (if known). Otherwise, the same as ``arg``.
129- argrepr: human-readable description of operation argument.
130129
131- tos_str: If not None, a string representation of the top of the stack (TOS).
132- This is obtained by scanning previous instructions and
133- using information there and in their ``tos_str`` fields.
130+ argrepr: human-readable description of operation argument.
134131
135132 positions: Optional dis.Positions object holding the start and end locations that
136133 are covered by this instruction. This not implemented yet.
@@ -148,6 +145,14 @@ class Instruction(NamedTuple):
148145 instruction. Note conditionals are in this category, but
149146 returns, raise, and unconditional jumps are not.
150147
148+ Note: the following fields have to appear in the order below and be at the end.
149+ disassembly may replace (delete and insert) an instruction, and it assumes
150+ the ending fields are as follows:
151+
152+ tos_str: If not None, a string representation of the top of the stack (TOS).
153+ This is obtained by scanning previous instructions and
154+ using information there and in their ``tos_str`` fields.
155+
151156 start_offset: if not None the instruction with the lowest offset that
152157 pushes a stack entry that is consume by this opcode
153158 """
@@ -305,6 +310,7 @@ def disassemble(
305310
306311 # Column: Opcode argument
307312 if self .arg is not None :
313+
308314 argrepr = self .argrepr
309315 # The ``argrepr`` value when the instruction was created
310316 # generally has all the information we require. However,
@@ -337,14 +343,18 @@ def disassemble(
337343 ):
338344 new_instruction = list (self )
339345 new_instruction [- 2 ] = f"To line { line_starts [self .argval ]} "
340- self = Instruction (* new_instruction )
346+ # Here and below we use self.__class__ instead of Instruction
347+ # so that other kinds of compatible namedtuple Instructions
348+ # can be used. In particular, the control-flow project
349+ # defines such an ExtendedInstruction namedtuple
350+ self = self .__class__ (* new_instruction )
341351 del instructions [- 1 ]
342352 instructions .append (self )
343353 elif (
344354 hasattr (opc , "opcode_extended_fmt" )
345- and opc .opname [ opcode ] in opc .opcode_extended_fmt
355+ and self .opname in opc .opcode_extended_fmt
346356 ):
347- new_repr = opc .opcode_extended_fmt [ opc . opname [ opcode ]] (
357+ new_repr = opc .opcode_extended_fmt . get ( self . opname , lambda opc , instr : None ) (
348358 opc , list (reversed (instructions ))
349359 )
350360 start_offset = None
@@ -357,15 +367,17 @@ def disassemble(
357367 new_instruction [- 1 ] = start_offset
358368 new_instruction [- 2 ] = new_repr
359369 del instructions [- 1 ]
360- self = Instruction (* new_instruction )
370+ # See comment above abut the use of self.__class__
371+ self = self .__class__ (* new_instruction )
361372 instructions .append (self )
362373 argrepr = new_repr
363374 elif opcode in opc .nullaryloadop :
364375 new_instruction = list (self )
365376 new_instruction [- 2 ] = self .argrepr
366377 start_offset = new_instruction [- 1 ] = self .offset
367378 del instructions [- 1 ]
368- self = Instruction (* new_instruction )
379+ # See comment above abut the use of self.__class__
380+ self = self .__class__ (* new_instruction )
369381 instructions .append (self )
370382 pass
371383 if not argrepr :
@@ -396,17 +408,18 @@ def disassemble(
396408 elif asm_format in ("extended" , "extended-bytes" ):
397409 if (
398410 hasattr (opc , "opcode_extended_fmt" )
399- and opc .opname [ opcode ] in opc .opcode_extended_fmt
411+ and self .opname in opc .opcode_extended_fmt
400412 ):
401- new_repr , start_offset = opc .opcode_extended_fmt [ opc . opname [ opcode ]] (
413+ new_repr , start_offset = opc .opcode_extended_fmt . get ( self . opname , ( None , 0 )) (
402414 opc , list (reversed (instructions ))
403415 )
404416 if new_repr :
405417 new_instruction = list (self )
406418 new_instruction [- 2 ] = new_repr
407419 new_instruction [- 1 ] = start_offset
408420 del instructions [- 1 ]
409- instructions .append (Instruction (* new_instruction ))
421+ # See comment above abut the use of self.__class__
422+ instructions .append (self .__class__ (* new_instruction ))
410423 argval = self .argval
411424 prefix = "" if argval is None else f"({ argval } ) | "
412425 if self .opcode in opc .operator_set :
@@ -415,7 +428,7 @@ def disassemble(
415428 pass
416429 elif (
417430 hasattr (opc , "opcode_arg_fmt" )
418- and opc .opname [ opcode ] in opc .opcode_arg_fmt
431+ and self .opname in opc .opcode_arg_fmt
419432 ) and self .argrepr is not None :
420433 fields .append (self .argrepr )
421434 pass
0 commit comments