Skip to content

Commit 9536b5b

Browse files
authored
Merge pull request #908 from boriel-basic/feat/unify_bool
Feat/unify bool
2 parents 518068b + 445d4cc commit 9536b5b

5 files changed

Lines changed: 245 additions & 187 deletions

File tree

src/api/check.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ def is_temporary_value(node) -> bool:
406406
return node.token not in ("STRING", "VAR") and node.t[0] not in ("_", "#")
407407

408408

409-
def common_type(a, b):
409+
def common_type(a: symbols.TYPE | Type | None, b: symbols.TYPE | Type | None) -> symbols.TYPE | Type | None:
410410
"""Returns a type which is common for both a and b types.
411411
Returns None if no common types allowed.
412412
"""
@@ -435,7 +435,7 @@ def common_type(a, b):
435435
assert a.is_basic
436436
assert b.is_basic
437437

438-
types = (a, b)
438+
types = a, b
439439

440440
if Type.float_ in types:
441441
return Type.float_

src/arch/z80/backend/common.py

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# vim ts=4:et:sw=4:ai
2-
31
import math
42
import re
5-
from typing import Any, Final
3+
from enum import StrEnum
4+
from types import MappingProxyType
5+
from typing import Final
66

77
from src.api import global_, tmp_labels
88
from src.api.exception import TempAlreadyFreedError
@@ -22,18 +22,46 @@
2222
"strslice.asm",
2323
}
2424

25+
26+
class DataType(StrEnum):
27+
bool = "bool"
28+
u8 = "u8"
29+
u16 = "u16"
30+
u32 = "u32"
31+
i8 = "i8"
32+
i16 = "i16"
33+
i32 = "i32"
34+
f16 = "f16"
35+
f = "f"
36+
37+
38+
# Handy constants, to not having to type long names :-)
39+
BOOL_t: Final[DataType] = DataType.bool
40+
U8_t: Final[DataType] = DataType.u8
41+
U16_t: Final[DataType] = DataType.u16
42+
U32_t: Final[DataType] = DataType.u32
43+
I8_t: Final[DataType] = DataType.i8
44+
I16_t: Final[DataType] = DataType.i16
45+
I32_t: Final[DataType] = DataType.i32
46+
F16_t: Final[DataType] = DataType.f16
47+
F_t: Final[DataType] = DataType.f
48+
49+
2550
# Internal data types definition, with its size in bytes, or -1 if it is variable (string)
2651
# Compound types are only arrays, and have the t
27-
YY_TYPES = {
28-
"u8": 1, # 8 bit unsigned integer
29-
"u16": 2, # 16 bit unsigned integer
30-
"u32": 4, # 32 bit unsigned integer
31-
"i8": 1, # 8 bit SIGNED integer
32-
"i16": 2, # 16 bit SIGNED integer
33-
"i32": 4, # 32 bit SIGNED integer
34-
"f16": 4, # -32768.9999 to 32767.9999 -aprox.- fixed point decimal (step = 1/2^16)
35-
"f": 5, # Floating point
36-
}
52+
YY_TYPES: Final[MappingProxyType[DataType, int]] = MappingProxyType(
53+
{
54+
BOOL_t: 1,
55+
U8_t: 1, # 8 bit unsigned integer
56+
U16_t: 2, # 16 bit unsigned integer
57+
U32_t: 4, # 32 bit unsigned integer
58+
I8_t: 1, # 8 bit SIGNED integer
59+
I16_t: 2, # 16 bit SIGNED integer
60+
I32_t: 4, # 32 bit SIGNED integer
61+
F16_t: 4, # -32768.9999 to 32767.9999 -aprox.- fixed point decimal (step = 1/2^16)
62+
F_t: 5, # Floating point
63+
}
64+
)
3765

3866
# Matches a boolean instruction like 'equ16' or 'andi32'
3967
RE_BOOL: Final[re.Pattern] = re.compile(r"^(eq|ne|lt|le|gt|ge|and|or|xor|not)(([ui](8|16|32))|(f16|f|str))$")
@@ -109,14 +137,14 @@ def is_2n(x: float) -> bool:
109137
return n == int(n)
110138

111139

112-
def tmp_remove(label: str):
140+
def tmp_remove(label: str) -> None:
113141
if label not in TMP_STORAGES:
114142
raise TempAlreadyFreedError(label)
115143

116144
TMP_STORAGES.pop(TMP_STORAGES.index(label))
117145

118146

119-
def runtime_call(label: str):
147+
def runtime_call(label: str) -> str:
120148
assert label in RUNTIME_LABELS, f"Invalid runtime label '{label}'"
121149
if label in LABEL_REQUIRED_MODULES:
122150
REQUIRES.add(LABEL_REQUIRED_MODULES[label])
@@ -129,7 +157,7 @@ def runtime_call(label: str):
129157
# ------------------------------------------------------------------
130158

131159

132-
def is_int(op: Any) -> bool:
160+
def is_int(op: str) -> bool:
133161
"""Returns True if the given operand (string)
134162
contains an integer number
135163
"""
@@ -143,7 +171,7 @@ def is_int(op: Any) -> bool:
143171
return False
144172

145173

146-
def is_float(op: Any) -> bool:
174+
def is_float(op: str) -> bool:
147175
"""Returns True if the given operand (string)
148176
contains a floating point number
149177
"""
@@ -161,7 +189,7 @@ def _int_ops(op1: str, op2: str) -> tuple[str, str | int] | None:
161189
"""Receives a list with two strings (operands).
162190
If none of them contains integers, returns None.
163191
Otherwise, returns a t-uple with (op[0], op[1]),
164-
where op[1] (2nd operan) is always the integer one (the list is swapped)
192+
where op[1] (2nd operand) is always the integer one (the list is swapped)
165193
This cannot be used by non-commutative operations like sub and div used this
166194
because they're not commutative).
167195
@@ -198,7 +226,7 @@ def _f_ops(op1: str, op2: str, *, swap: bool = True) -> tuple[str | float, str |
198226
return None
199227

200228

201-
def is_int_type(stype: str) -> bool:
229+
def is_int_type(stype: DataType) -> bool:
202230
"""Returns whether a given type is integer"""
203231
return stype[0] in ("u", "i")
204232

@@ -268,65 +296,65 @@ def get_bytes_size(elements: list[str]) -> int:
268296
return len(get_bytes(elements))
269297

270298

271-
def to_byte(stype: str) -> list[str]:
299+
def to_byte(stype: DataType) -> list[str]:
272300
"""Returns the instruction sequence for converting from
273301
the given type to byte.
274302
"""
275303
output = []
276304

277-
if stype in ("i8", "u8"):
305+
if stype in (I8_t, U8_t):
278306
return []
279307

280308
if is_int_type(stype):
281309
output.append("ld a, l")
282-
elif stype == "f16":
310+
elif stype == F16_t:
283311
output.append("ld a, e")
284-
elif stype == "f": # Converts C ED LH to byte
312+
elif stype == F_t: # Converts C ED LH to byte
285313
output.append(runtime_call(RuntimeLabel.FTOU32REG))
286314
output.append("ld a, l")
287315

288316
return output
289317

290318

291-
def to_word(stype: str) -> list[str]:
319+
def to_word(stype: DataType) -> list[str]:
292320
"""Returns the instruction sequence for converting the given
293321
type stored in DE,HL to word (unsigned) HL.
294322
"""
295323
output = [] # List of instructions
296324

297-
if stype == "u8": # Byte to word
325+
if stype == U8_t: # Byte to word
298326
output.append("ld l, a")
299327
output.append("ld h, 0")
300328

301-
elif stype == "i8": # Signed byte to word
329+
elif stype == I8_t: # Signed byte to word
302330
output.append("ld l, a")
303331
output.append("add a, a")
304332
output.append("sbc a, a")
305333
output.append("ld h, a")
306334

307-
elif stype == "f16": # Must MOVE HL into DE
335+
elif stype == F16_t: # Must MOVE HL into DE
308336
output.append("ex de, hl")
309337

310-
elif stype == "f":
338+
elif stype == F_t:
311339
output.append(runtime_call(RuntimeLabel.FTOU32REG))
312340

313341
return output
314342

315343

316-
def to_long(stype: str) -> list[str]:
344+
def to_long(stype: DataType) -> list[str]:
317345
"""Returns the instruction sequence for converting the given
318346
type stored in DE,HL to long (DE, HL).
319347
"""
320348
output = [] # List of instructions
321349

322-
if stype in ("i8", "u8", "f16"): # Byte to word
350+
if stype in {I8_t, U8_t, F16_t}: # Byte to word
323351
output = to_word(stype)
324352

325-
if stype != "f16": # If its a byte, just copy H to D,E
353+
if stype != F16_t: # If it's a byte, just copy H to D,E
326354
output.append("ld e, h")
327355
output.append("ld d, h")
328356

329-
if stype in ("i16", "f16"): # Signed byte or fixed to word
357+
if stype in (I16_t, F16_t): # Signed byte or fixed to word
330358
output.append("ld a, h")
331359
output.append("add a, a")
332360
output.append("sbc a, a")
@@ -336,13 +364,13 @@ def to_long(stype: str) -> list[str]:
336364
elif stype == "u16":
337365
output.append("ld de, 0")
338366

339-
elif stype == "f":
367+
elif stype == F_t:
340368
output.append(runtime_call(RuntimeLabel.FTOU32REG))
341369

342370
return output
343371

344372

345-
def to_fixed(stype: str) -> list[str]:
373+
def to_fixed(stype: DataType) -> list[str]:
346374
"""Returns the instruction sequence for converting the given
347375
type stored in DE,HL to fixed DE,HL.
348376
"""
@@ -352,33 +380,33 @@ def to_fixed(stype: str) -> list[str]:
352380
output = to_word(stype)
353381
output.append("ex de, hl")
354382
output.append("ld hl, 0") # 'Truncate' the fixed point
355-
elif stype == "f":
383+
elif stype == F_t:
356384
output.append(runtime_call(RuntimeLabel.FTOF16REG))
357385

358386
return output
359387

360388

361-
def to_float(stype: str) -> list[str]:
389+
def to_float(stype: DataType) -> list[str]:
362390
"""Returns the instruction sequence for converting the given
363391
type stored in DE,HL to fixed DE,HL.
364392
"""
365393
output: list[str] = [] # List of instructions
366394

367-
if stype == "f":
395+
if stype == F_t:
368396
return output # Nothing to do
369397

370-
if stype == "f16":
398+
if stype == F16_t:
371399
output.append(runtime_call(RuntimeLabel.F16TOFREG))
372400
return output
373401

374402
# If we reach this point, it's an integer type
375-
if stype == "u8":
403+
if stype == U8_t:
376404
output.append(runtime_call(RuntimeLabel.U8TOFREG))
377-
elif stype == "i8":
405+
elif stype == I8_t:
378406
output.append(runtime_call(RuntimeLabel.I8TOFREG))
379407
else:
380408
output = to_long(stype)
381-
if stype in ("i16", "i32"):
409+
if stype in (I16_t, I32_t):
382410
output.append(runtime_call(RuntimeLabel.I32TOFREG))
383411
else:
384412
output.append(runtime_call(RuntimeLabel.U32TOFREG))

src/arch/z80/visitor/translator.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from collections import namedtuple
2+
from collections.abc import Callable
3+
from typing import Any
24

35
import src.api.errmsg
46
import src.api.global_ as gl
@@ -145,8 +147,29 @@ def visit_BINARY(self, node):
145147
yield node.right
146148

147149
ins = {"PLUS": "add", "MINUS": "sub"}.get(node.operator, node.operator.lower())
148-
s = self.TSUFFIX(node.left.type_) # Operands type
149-
self.emit(ins + s, node.t, str(node.left.t), str(node.right.t))
150+
ins_t: dict[str, Callable[[TYPE | symbols.BASICTYPE, Any, Any, Any], None]] = {
151+
"add": self.ic_add,
152+
"sub": self.ic_sub,
153+
"mul": self.ic_mul,
154+
"div": self.ic_div,
155+
"or": self.ic_or,
156+
"xor": self.ic_xor,
157+
"and": self.ic_and,
158+
"eq": self.ic_eq,
159+
"ne": self.ic_ne,
160+
"gt": self.ic_gt,
161+
"lt": self.ic_lt,
162+
"le": self.ic_le,
163+
"ge": self.ic_ge,
164+
"band": self.ic_band,
165+
"bor": self.ic_bor,
166+
"bxor": self.ic_bxor,
167+
"shl": self.ic_shl,
168+
"shr": self.ic_shr,
169+
"pow": self.ic_pow,
170+
"mod": self.ic_mod,
171+
}
172+
ins_t[ins](node.left.type_, node.t, str(node.left.t), str(node.right.t))
150173

151174
def visit_TYPECAST(self, node):
152175
yield node.operand

0 commit comments

Comments
 (0)