11import re
22
3+ from typing import Dict
4+ from typing import Tuple
5+ from typing import Optional
6+ from typing import List
7+
38from .patterns import RE_OUTC , RE_INDIR16
49from .helpers import single_registers
510from src .libzxbasm import z80
611
712# Dict of patterns to normalized instructions. I.e. 'ld a, 5' -> 'LD A,N'
8- Z80_PATTERN = {}
13+ Z80_PATTERN : Dict [ re . Pattern , z80 . Opcode ] = {}
914
1015
11- class Asm ( object ) :
16+ class Asm :
1217 """ Defines an asm instruction
1318 """
14- def __init__ (self , asm ):
15- assert isinstance (asm , str )
19+ def __init__ (self , asm : str ):
1620 asm = asm .strip ()
1721 assert asm , "Empty instruction '{}'" .format (asm )
18- self .inst = Asm .inst (asm )
22+ self .inst = Asm .instruction (asm )
1923 self .oper = Asm .opers (asm )
2024 self .asm = '{} {}' .format (self .inst , ' ' .join (asm .split (' ' , 1 )[1 :])).strip ()
2125 self .cond = Asm .condition (asm )
2226 self .output = Asm .result (asm )
23- self ._bytes = None
27+ self ._bytes : Optional [ Tuple [ str ]] = None
2428 self ._max_tstates = None
2529 self .is_label = self .inst [- 1 ] == ':'
2630
@@ -31,7 +35,7 @@ def _compute_bytes(self):
3135 self ._max_tstates = opcode_data .T
3236 return
3337
34- self ._bytes = tuple ()
38+ self ._bytes = bytearray ()
3539 self ._max_tstates = 0
3640
3741 @property
@@ -58,19 +62,18 @@ def max_tstates(self):
5862 return self ._max_tstates
5963
6064 @staticmethod
61- def inst (asm ) :
65+ def instruction (asm : str ) -> str :
6266 tmp = asm .strip (' \t \n ' ).split (' ' , 1 )[0 ]
6367 return tmp .lower () if tmp .upper () in z80 .Z80INSTR else tmp
6468
6569 @staticmethod
66- def opers (inst ) :
70+ def opers (inst : str ) -> List [ str ] :
6771 """ Returns operands of an ASM instruction.
6872 Even "indirect" operands, like SP if RET or CALL is used.
6973 """
70- i = inst .strip (' \t \n ' ).split (' ' , 1 )
71- I = i [0 ].lower () # Instruction
72- i = '' .join (i [1 :])
73- op = [x .strip () for x in i .split (',' )]
74+ car , cdr = (inst .strip (' \t \n ' ) + ' ' ).split (' ' , 1 )
75+ I = car .lower () # Instruction
76+ op = [x .strip () for x in cdr .split (',' )]
7477
7578 if I in {'call' , 'jp' , 'jr' } and len (op ) > 1 :
7679 op = op [1 :] + ['f' ]
@@ -111,7 +114,7 @@ def opers(inst):
111114 op += ['sp' ]
112115
113116 elif I == 'out' :
114- if len ( op ) and RE_OUTC .match (op [0 ]):
117+ if op and RE_OUTC .match (op [0 ]):
115118 op [0 ] = 'c'
116119 else :
117120 op .pop (0 )
@@ -122,8 +125,8 @@ def opers(inst):
122125 else :
123126 op .pop (1 )
124127
125- for i in range ( len ( op ) ):
126- tmp = RE_INDIR16 .match (op [ i ] )
128+ for i , o in enumerate ( op ):
129+ tmp = RE_INDIR16 .match (o )
127130 if tmp is not None :
128131 op [i ] = '(' + op [i ].strip ()[1 :- 1 ].strip ().lower () + ')' # ' ( dE ) ' => '(de)'
129132
@@ -138,7 +141,7 @@ def condition(asm):
138141 condition flag (it always execute) whilst RET C does.
139142 DJNZ has condition flag NZ
140143 """
141- i = Asm .inst (asm )
144+ i = Asm .instruction (asm )
142145
143146 if i not in {'call' , 'jp' , 'jr' , 'ret' , 'djnz' }:
144147 return None # This instruction always execute
@@ -162,7 +165,7 @@ def result(asm):
162165 """ Returns which 8-bit registers (and SP for INC SP, DEC SP, etc.) are used by an asm
163166 instruction to return a result.
164167 """
165- ins = Asm .inst (asm )
168+ ins = Asm .instruction (asm )
166169 op = Asm .opers (asm )
167170
168171 if ins in ('or' , 'and' ) and op == ['a' ]:
0 commit comments