55from typing import Final
66
77from src .api import global_ , tmp_labels
8+ from src .api .config import OPTIONS , OptimizationStrategy
89from src .api .exception import TempAlreadyFreedError
910
1011from .runtime import LABEL_REQUIRED_MODULES , NAMESPACE , RUNTIME_LABELS
@@ -296,12 +297,52 @@ def get_bytes_size(elements: list[str]) -> int:
296297 return len (get_bytes (elements ))
297298
298299
300+ def to_bool (stype : DataType ) -> list [str ]:
301+ """Returns the instruction sequence for converting the number given number (in the stack)
302+ to boolean (just 0 (False) or non-zero (True))."""
303+
304+ if stype in (U8_t , I8_t ):
305+ return []
306+
307+ if stype in (U16_t , I16_t ):
308+ return [
309+ "ld a, h" "or l" ,
310+ ]
311+
312+ if stype in (U32_t , I32_t , F16_t ):
313+ return ["ld a, h" "or l" "or d" , "or e," ]
314+
315+ if stype == F_t :
316+ return [
317+ "or b" ,
318+ "or c" ,
319+ "or d" ,
320+ "or e" ,
321+ ]
322+
323+ raise NotImplementedError (f"type conversion from { stype } to bool is undefined" )
324+
325+
326+ def normalize_boolean () -> list [str ]:
327+ if OPTIONS .opt_strategy == OptimizationStrategy .Size :
328+ return [runtime_call (RuntimeLabel .NORMALIZE_BOOLEAN )]
329+
330+ return [
331+ "sub 1" , # Carry if A = 0
332+ "sbc a, a" , # 0xFF if A was 0, 0 otherwise
333+ "inc a" , # 0 if A was 0, 1 otherwise
334+ ]
335+
336+
299337def to_byte (stype : DataType ) -> list [str ]:
300338 """Returns the instruction sequence for converting from
301339 the given type to byte.
302340 """
303341 output = []
304342
343+ if stype == BOOL_t :
344+ return normalize_boolean ()
345+
305346 if stype in (I8_t , U8_t ):
306347 return []
307348
@@ -322,7 +363,10 @@ def to_word(stype: DataType) -> list[str]:
322363 """
323364 output = [] # List of instructions
324365
325- if stype == U8_t : # Byte to word
366+ if stype == BOOL_t :
367+ output .extend (normalize_boolean ())
368+
369+ if stype in (BOOL_t , U8_t ): # Byte to word
326370 output .append ("ld l, a" )
327371 output .append ("ld h, 0" )
328372
@@ -347,25 +391,39 @@ def to_long(stype: DataType) -> list[str]:
347391 """
348392 output = [] # List of instructions
349393
394+ if stype == BOOL_t :
395+ output = normalize_boolean ()
396+ output .extend (
397+ [
398+ "ld l, a" ,
399+ "ld h, 0" ,
400+ "ld e, h" ,
401+ "ld d, h" ,
402+ ]
403+ )
404+ return output
405+
350406 if stype in {I8_t , U8_t , F16_t }: # Byte to word
351407 output = to_word (stype )
352408
353409 if stype != F16_t : # If it's a byte, just copy H to D,E
354410 output .append ("ld e, h" )
355411 output .append ("ld d, h" )
356412
357- if stype in (I16_t , F16_t ): # Signed byte or fixed to word
413+ elif stype in (I16_t , F16_t ): # Signed byte or fixed to word
358414 output .append ("ld a, h" )
359415 output .append ("add a, a" )
360416 output .append ("sbc a, a" )
361417 output .append ("ld e, a" )
362418 output .append ("ld d, a" )
363419
364- elif stype == "u16" :
420+ elif stype == U16_t :
365421 output .append ("ld de, 0" )
366422
367423 elif stype == F_t :
368424 output .append (runtime_call (RuntimeLabel .FTOU32REG ))
425+ else :
426+ raise NotImplementedError (f"type conversion from { stype } to long is undefined" )
369427
370428 return output
371429
@@ -374,16 +432,30 @@ def to_fixed(stype: DataType) -> list[str]:
374432 """Returns the instruction sequence for converting the given
375433 type stored in DE,HL to fixed DE,HL.
376434 """
377- output = [] # List of instructions
435+ if stype == BOOL_t :
436+ output = to_word (stype )
437+ output .extend (
438+ [
439+ "ex de, hl" ,
440+ "ld hl, 0" , # 'Truncate' the fixed point
441+ ]
442+ )
443+ return output
378444
379445 if is_int_type (stype ):
380446 output = to_word (stype )
381- output .append ("ex de, hl" )
382- output .append ("ld hl, 0" ) # 'Truncate' the fixed point
383- elif stype == F_t :
384- output .append (runtime_call (RuntimeLabel .FTOF16REG ))
447+ output .extend (
448+ [
449+ "ex de, hl" ,
450+ "ld hl, 0" , # 'Truncate' the fixed point
451+ ]
452+ )
453+ return output
385454
386- return output
455+ if stype == F_t :
456+ return [runtime_call (RuntimeLabel .FTOF16REG )]
457+
458+ raise NotImplementedError (f"type conversion from { stype } to fixed" )
387459
388460
389461def to_float (stype : DataType ) -> list [str ]:
@@ -399,17 +471,22 @@ def to_float(stype: DataType) -> list[str]:
399471 output .append (runtime_call (RuntimeLabel .F16TOFREG ))
400472 return output
401473
474+ if stype == BOOL_t :
475+ output .extend (normalize_boolean ())
476+
402477 # If we reach this point, it's an integer type
403- if stype == U8_t :
478+ if stype in ( BOOL_t , U8_t ): # The ZX Spectrum ROM FP-Calc already returns 0 or 1 for Booleans
404479 output .append (runtime_call (RuntimeLabel .U8TOFREG ))
405480 elif stype == I8_t :
406481 output .append (runtime_call (RuntimeLabel .I8TOFREG ))
407- else :
482+ elif stype in { I16_t , I32_t , U16_t , U32_t } :
408483 output = to_long (stype )
409484 if stype in (I16_t , I32_t ):
410485 output .append (runtime_call (RuntimeLabel .I32TOFREG ))
411486 else :
412487 output .append (runtime_call (RuntimeLabel .U32TOFREG ))
488+ else :
489+ raise NotImplementedError (f"type conversion from { stype } to float is undefined" )
413490
414491 return output
415492
0 commit comments