Skip to content

Commit cce39c7

Browse files
borielJose Rodriguez
authored andcommitted
typing: improve typing
1 parent a381116 commit cce39c7

5 files changed

Lines changed: 52 additions & 53 deletions

File tree

src/api/global_.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
# This program is Free Software and is released under the terms of
99
# the GNU General License
1010
# ----------------------------------------------------------------------
11-
from typing import Dict, List, NamedTuple, Optional, Set
11+
from typing import Dict, List, NamedTuple, Optional, Set, Final
1212

1313
from src.api.constants import TYPE, LoopType
1414
from src.api.opcodestemps import OpcodesTemps
1515

16+
1617
# ----------------------------------------------------------------------
1718
# Simple global container for internal constants.
1819
# Internal constants might be architecture dependant. They're set
@@ -117,34 +118,34 @@ class LoopInfo(NamedTuple):
117118
# ----------------------------------------------------------------------
118119
# Data type used for elements size. Must be an integral
119120
# ----------------------------------------------------------------------
120-
SIZE_TYPE: TYPE = TYPE.ubyte
121+
SIZE_TYPE: Final[TYPE] = TYPE.ubyte
121122

122123
# ----------------------------------------------------------------------
123124
# CORE namespace (for core runtime library, like FP Calc)
124125
# ----------------------------------------------------------------------
125-
CORE_NAMESPACE = ".core"
126+
CORE_NAMESPACE: Final[str] = ".core"
126127

127128
# ----------------------------------------------------------------------
128129
# DATA Labels namespace
129130
# ----------------------------------------------------------------------
130-
DATAS_NAMESPACE = ".DATA"
131+
DATAS_NAMESPACE: Final[str] = ".DATA"
131132

132133
# ----------------------------------------------------------------------
133134
# LABEL Labels namespace
134135
# ----------------------------------------------------------------------
135-
LABELS_NAMESPACE = ".LABEL" # *MUST* start with a DOT (.)
136+
LABELS_NAMESPACE: Final[str] = ".LABEL" # *MUST* start with a DOT (.)
136137

137138
# ----------------------------------------------------------------------
138139
# USER DATA LABELS
139140
# ----------------------------------------------------------------------
140-
ZXBASIC_USER_DATA = f"{CORE_NAMESPACE}.ZXBASIC_USER_DATA"
141-
ZXBASIC_USER_DATA_LEN = f"{CORE_NAMESPACE}.ZXBASIC_USER_DATA_LEN"
141+
ZXBASIC_USER_DATA: Final[str] = f"{CORE_NAMESPACE}.ZXBASIC_USER_DATA"
142+
ZXBASIC_USER_DATA_LEN: Final[str] = f"{CORE_NAMESPACE}.ZXBASIC_USER_DATA_LEN"
142143

143144

144145
# ----------------------------------------------------------------------
145146
# Data Type used for string chars index. Must be an integral
146147
# ----------------------------------------------------------------------
147-
STR_INDEX_TYPE: TYPE = TYPE.uinteger
148+
STR_INDEX_TYPE: Final[TYPE] = TYPE.uinteger
148149

149150
# ----------------------------------------------------------------------
150151
# MIN and MAX str slice index
@@ -160,18 +161,18 @@ class LoopInfo(NamedTuple):
160161
# ----------------------------------------------------------------------
161162
# Character used for name mangling. Usually '_' or '.'
162163
# ----------------------------------------------------------------------
163-
MANGLE_CHR = "_"
164-
NAMESPACE_SEPARATOR = "."
164+
MANGLE_CHR: Final[str] = "_"
165+
NAMESPACE_SEPARATOR: Final[str] = "."
165166

166167
# ----------------------------------------------------------------------
167168
# Prefix used in labels to mark the beginning of array data
168169
# ----------------------------------------------------------------------
169-
ARRAY_DATA_PREFIX = "__DATA__"
170+
ARRAY_DATA_PREFIX: Final[str] = "__DATA__"
170171

171172
# ----------------------------------------------------------------------
172173
# Default optimization level
173174
# ----------------------------------------------------------------------
174-
DEFAULT_OPTIMIZATION_LEVEL = 2 # Optimization level. Higher -> more optimized
175+
DEFAULT_OPTIMIZATION_LEVEL: Final[int] = 2 # Optimization level. Higher -> more optimized
175176

176177
# ----------------------------------------------------------------------
177178
# DATA blocks

src/arch/z80/optimizer/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
from .main import init, optimize # noqa
1+
from .main import init, optimize
2+
3+
__all__ = "init", "optimize"

src/arch/z80/optimizer/helpers.py

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3-
from typing import Optional, TypeVar
3+
from typing import TypeVar, Any, Iterable
44

55
from . import common, patterns
66

@@ -60,7 +60,7 @@ def new_tmp_val16_from_label(label: str) -> str:
6060
return f"{UNKNOWN_PREFIX}H_{label}{HL_SEP}{UNKNOWN_PREFIX}L_{label}"
6161

6262

63-
def is_unknown(x) -> bool:
63+
def is_unknown(x: int | str | None) -> bool:
6464
if x is None:
6565
return True
6666

@@ -75,7 +75,7 @@ def is_unknown(x) -> bool:
7575
return any(x.startswith(UNKNOWN_PREFIX) for x in xx)
7676

7777

78-
def is_unknown8(x) -> bool:
78+
def is_unknown8(x: Any) -> bool:
7979
if x is None:
8080
return True
8181

@@ -85,7 +85,7 @@ def is_unknown8(x) -> bool:
8585
return len(x.split(HL_SEP)) == 1
8686

8787

88-
def is_unknown16(x) -> bool:
88+
def is_unknown16(x: Any) -> bool:
8989
if x is None:
9090
return True
9191

@@ -95,7 +95,7 @@ def is_unknown16(x) -> bool:
9595
return len(x.split(HL_SEP)) == 2
9696

9797

98-
def get_orig_label_from_unknown16(x: str) -> Optional[str]:
98+
def get_orig_label_from_unknown16(x: str) -> str | None:
9999
if not is_unknown16(x):
100100
return None
101101

@@ -114,33 +114,33 @@ def get_orig_label_from_unknown16(x: str) -> Optional[str]:
114114
return None if hi != lo else hi
115115

116116

117-
def get_L_from_unknown_value(tmp_val):
117+
def get_L_from_unknown_value(tmp_val: str) -> str:
118118
"""Given a 16bit *UNKNOWN value, returns it's lower part, which is the same 2nd part,
119119
after splitting by HL_SEP. If the parameter is None, a new tmp_value will be generated.
120120
If the value is a composed one (xxxH | yyyL) returns yyyL.
121121
"""
122-
assert is_unknown(tmp_val), "Malformed unknown value '{}'".format(tmp_val)
122+
assert is_unknown(tmp_val), f"Malformed unknown value '{tmp_val}'"
123123

124124
if tmp_val is None:
125125
tmp_val = new_tmp_val16()
126126

127127
return tmp_val.split(HL_SEP)[-1]
128128

129129

130-
def get_H_from_unknown_value(tmp_val):
130+
def get_H_from_unknown_value(tmp_val: str) -> str:
131131
"""Given a 16bit *UNKNOWN value, returns it's higher part, which is the same 1st part,
132132
after splitting by HL_SEP. If the parameter is None, a new tmp_value will be generated.
133133
If the value is a composed one (xxxH | yyyL) returns yyyH.
134134
"""
135-
assert is_unknown(tmp_val), "Malformed unknown value '{}'".format(tmp_val)
135+
assert is_unknown(tmp_val), f"Malformed unknown value '{tmp_val}'"
136136

137137
if tmp_val is None:
138138
tmp_val = new_tmp_val16()
139139

140140
return tmp_val.split(HL_SEP)[0]
141141

142142

143-
def is_mem_access(arg):
143+
def is_mem_access(arg: str) -> bool:
144144
"""Returns if a given string is a memory access, that is
145145
if it matches the form (...)
146146
"""
@@ -149,7 +149,7 @@ def is_mem_access(arg):
149149

150150

151151
# TODO: to be rewritten
152-
def is_number(x) -> bool:
152+
def is_number(x: Any) -> bool:
153153
"""Returns whether X is a numeric representation"""
154154
if x is None or x == "":
155155
return False
@@ -167,21 +167,17 @@ def is_number(x) -> bool:
167167
tmp = eval(x, {}, {})
168168
if isinstance(tmp, (int, float)):
169169
return True
170-
except NameError:
171-
pass
172-
except SyntaxError:
173-
pass
174-
except ValueError:
170+
except (Exception,):
175171
pass
176172

177173
return patterns.RE_NUMBER.match(str(x)) is not None
178174

179175

180-
def is_label(x) -> bool:
176+
def is_label(x: Any) -> bool:
181177
return str(x)[:1] in "._"
182178

183179

184-
def valnum(x):
180+
def valnum(x: Any) -> int | None:
185181
"""If x is a numeric value (int, float) or it's a string
186182
representation of a number (hexa, binary), returns it numeric value.
187183
Otherwise returns None
@@ -206,7 +202,7 @@ def valnum(x):
206202
return int(eval(x, {}, {}))
207203

208204

209-
def simplify_arg(arg):
205+
def simplify_arg(arg: str) -> str:
210206
"""Given an asm operand (str), if it can be evaluated to a single 16 bit integer number it will be done so.
211207
Memory addresses will preserve their parenthesis. If the string can not be simplified, it will be
212208
returned as is.
@@ -240,10 +236,10 @@ def simplify_arg(arg):
240236
if not is_mem_access(arg):
241237
return result
242238

243-
return "({})".format(result)
239+
return f"({result})"
244240

245241

246-
def simplify_asm_args(asm):
242+
def simplify_asm_args(asm: str) -> str:
247243
"""Given an asm instruction try to simplify its args."""
248244
chunks = [x for x in asm.split(" ", 1)]
249245
if len(chunks) != 2:
@@ -253,36 +249,36 @@ def simplify_asm_args(asm):
253249
return "{} {}".format(chunks[0], ", ".join(args))
254250

255251

256-
def is_register(x):
257-
"""True if x is a register."""
252+
def is_register(x: Any) -> bool:
253+
"""True if x is a register in a str."""
258254
if not isinstance(x, str):
259255
return False
260256

261257
return x.lower() in REGS_OPER_SET
262258

263259

264-
def is_8bit_normal_register(x):
260+
def is_8bit_normal_register(x: str) -> bool:
265261
"""Returns whether the given string x is a "normal" 8 bit register. Those are 8 bit registers
266262
which belongs to the normal (documented) Z80 instruction set as operands (so a', f', ixh, etc
267263
are excluded).
268264
"""
269265
return x.lower() in {"a", "b", "c", "d", "e", "i", "h", "l"}
270266

271267

272-
def is_8bit_idx_register(x):
268+
def is_8bit_idx_register(x: str) -> bool:
273269
"""Returns whether the given string x one of the undocumented IX, IY 8 bit registers."""
274270
return x.lower() in {"ixh", "ixl", "iyh", "iyl"}
275271

276272

277-
def is_8bit_oper_register(x):
273+
def is_8bit_oper_register(x: str) -> bool:
278274
"""Returns whether the given string x is an 8 bit register that can be used as an
279275
instruction operand. This included those of the undocumented Z80 instruction set as
280276
operands (ixh, ixl, etc) but not h', f'.
281277
"""
282278
return x.lower() in {"a", "b", "c", "d", "e", "i", "h", "l", "ixh", "ixl", "iyh", "iyl"}
283279

284280

285-
def is_16bit_normal_register(x):
281+
def is_16bit_normal_register(x: str) -> bool:
286282
"""Returns whether the given string x is a "normal" 16 bit register. Those are 16 bit registers
287283
which belongs to the normal (documented) Z80 instruction set as operands which can be operated
288284
directly (i.e. load a value directly), and not for indexation (IX + n, for example).
@@ -291,24 +287,24 @@ def is_16bit_normal_register(x):
291287
return x.lower() in {"bc", "de", "hl"}
292288

293289

294-
def is_16bit_idx_register(x):
290+
def is_16bit_idx_register(x: str) -> bool:
295291
"""Returns whether the given string x is a indexable (i.e. IX + n) 16 bit register."""
296292
return x.lower() in {"ix", "iy"}
297293

298294

299-
def is_16bit_composed_register(x):
295+
def is_16bit_composed_register(x: str) -> bool:
300296
"""A 16bit register that can be decomposed into a high H16 and low L16 part"""
301297
return x.lower() in {"af", "af'", "bc", "de", "hl", "ix", "iy"}
302298

303299

304-
def is_16bit_oper_register(x):
300+
def is_16bit_oper_register(x: str) -> bool:
305301
"""Returns whether the given string x is a 16 bit register. These are any 16 bit register
306302
which belongs to the normal (documented) Z80 instruction set as operands.
307303
"""
308304
return x.lower() in {"af", "af'", "bc", "de", "hl", "ix", "iy", "sp"}
309305

310306

311-
def LO16(x):
307+
def LO16(x: str) -> str:
312308
"""Given a 16-bit register (lowercase string), returns the low 8 bit register of it.
313309
The string *must* be a 16 bit lowercase register. SP register is not "decomposable" as
314310
two 8-bit registers and this is considered an error.
@@ -323,7 +319,7 @@ def LO16(x):
323319
return x[1] + ("'" if "'" in x else "")
324320

325321

326-
def HI16(x):
322+
def HI16(x: str) -> str:
327323
"""Given a 16-bit register (lowercase string), returns the high 8 bit register of it.
328324
The string *must* be a 16 bit lowercase register. SP register is not "decomposable" as
329325
two 8-bit registers and this is considered an error.
@@ -338,7 +334,7 @@ def HI16(x):
338334
return x[0] + ("'" if "'" in x else "")
339335

340336

341-
def single_registers(op):
337+
def single_registers(op: str | Iterable[str]) -> list[str]:
342338
"""Given an iterable (set, list) of registers like ['a', 'bc', "af'", 'h', 'hl'] returns
343339
a list of single registers: ['a', "a'", "f'", 'b', 'c', 'h', 'l'].
344340
Non register parameters (like numbers) will be ignored.
@@ -348,7 +344,7 @@ def single_registers(op):
348344
- IX and IY will be returned as {'ixh', 'ixl'} and {'iyh', 'iyl'} respectively
349345
"""
350346
result = set()
351-
if not isinstance(op, (list, set)):
347+
if isinstance(op, str):
352348
op = [op]
353349

354350
for x in op:
@@ -362,7 +358,7 @@ def single_registers(op):
362358
return sorted(result)
363359

364360

365-
def idx_args(x):
361+
def idx_args(x: str) -> tuple[str, str, str] | None:
366362
"""Given an argument x (string), returns None if it's not an index operation "ix/iy + n"
367363
Otherwise return a tuple (reg, oper, offset). It's case insensitive and the register is always returned
368364
in lowercase.
@@ -381,7 +377,7 @@ def idx_args(x):
381377
return reg.lower(), sign, args
382378

383379

384-
def LO16_val(x):
380+
def LO16_val(x: int | str | None) -> str:
385381
"""Given an x value, it must be None, unknown, or an integer.
386382
Then returns it lower part. If it's none, a new tmp will be returned.
387383
"""
@@ -397,7 +393,7 @@ def LO16_val(x):
397393
return x.split(HL_SEP)[-1]
398394

399395

400-
def HI16_val(x):
396+
def HI16_val(x: int | str | None) -> str:
401397
"""Given an x value, it must be None, unknown, or an integer.
402398
Then returns it upper part. If it's None, a new tmp will be returned.
403399
It it's an unknown8, return 0, because it's considered an 8 bit value.

src/arch/zx48k/backend/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
emit_start,
1919
)
2020

21-
__all__ = [
21+
__all__ = (
2222
"_fpop",
2323
"HI16",
2424
"INITS",
@@ -32,7 +32,7 @@
3232
"emit",
3333
"emit_end",
3434
"emit_start",
35-
]
35+
)
3636

3737

3838
# ZXNext asm enabled by default for this arch

tests/arch/zx48k/optimizer/test_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3-
import src.arch.z80.optimizer.helpers as helpers
3+
from src.arch.z80.optimizer import helpers
44

55

66
def test_new_tmp_val():

0 commit comments

Comments
 (0)