1- # vim ts=4:et:sw=4:ai
2-
31import math
42import re
5- from typing import Any , Final
3+ from enum import StrEnum
4+ from types import MappingProxyType
5+ from typing import Final
66
77from src .api import global_ , tmp_labels
88from src .api .exception import TempAlreadyFreedError
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'
3967RE_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 ))
0 commit comments