Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/api/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@ def is_number(*p):
return all(i.token in ("NUMBER", "CONST") for i in p)


def is_static_str(*p):
return all(i.token == "STRING" for i in p)


def is_var(*p):
"""Returns True if ALL the arguments are AST nodes
containing ID
Expand Down
3 changes: 2 additions & 1 deletion src/arch/z80/backend/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from src.api import global_, tmp_labels
from src.api.exception import TempAlreadyFreedError
from src.symbols.symbol_ import Symbol

from . import exception
from .exception import InvalidICError as InvalidIC
Expand Down Expand Up @@ -110,7 +111,7 @@ def __init__(self, *args):
if len(args) - 1 != QUADS[args[0]].nargs:
exception.throw_invalid_quad_params(args[0], len(args) - 1, QUADS[args[0]].nargs)

args = tuple([str(x) for x in args]) # Convert it to strings
args = tuple([str(x.t if isinstance(x, Symbol) else x) for x in args]) # Convert it to strings

self.quad = args
self.op = args[0]
Expand Down
42 changes: 18 additions & 24 deletions src/arch/z80/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def visit_LABEL(self, node):
self.ic_label(node.mangled)

def visit_CONST(self, node):
yield node.t
yield node.symbol

def visit_VAR(self, node):
__DEBUG__(
Expand Down Expand Up @@ -977,7 +977,7 @@ def loop_cont_label(self, loop_type):
raise InvalidLoopError(loop_type)

@classmethod
def default_value(cls, type_, expr): # TODO: This function must be moved to api.xx
def default_value(cls, type_: symbols.TYPE, expr) -> list[str]: # TODO: This function must be moved to api.xx
"""Returns a list of bytes (as hexadecimal 2 char string)"""
assert isinstance(type_, symbols.TYPE)
assert type_.is_basic
Expand All @@ -986,44 +986,37 @@ def default_value(cls, type_, expr): # TODO: This function must be moved to api
if expr.token in ("CONSTEXPR", "CONST"): # a constant expression like @label + 1
if type_ in (cls.TYPE(TYPE.float), cls.TYPE(TYPE.string)):
error(expr.lineno, f"Can't convert non-numeric value to {type_.name} at compile time")
return ["<ERROR>"]
return ["<ERROR>"] # dummy placeholder so the compilation continues

val = Translator.traverse_const(expr)
if type_.size == 1: # U/byte
if expr.type_.size != 1:
return ["#({0}) & 0xFF".format(val)]
return [f"#({val}) & 0xFF"]
else:
return ["#{0}".format(val)]
return [f"#{val}"]

if type_.size == 2: # U/integer
if expr.type_.size != 2:
return ["##({0}) & 0xFFFF".format(val)]
return [f"##({val}) & 0xFFFF"]
else:
return ["##{0}".format(val)]
return [f"##{val}"]

if type_ == cls.TYPE(TYPE.fixed):
return ["0000", "##({0}) & 0xFFFF".format(val)]
return ["0000", f"##({val}) & 0xFFFF"]

# U/Long
return ["##({0}) & 0xFFFF".format(val), "##(({0}) >> 16) & 0xFFFF".format(val)]
return [f"##({val}) & 0xFFFF", f"##(({val}) >> 16) & 0xFFFF"]

if type_ == cls.TYPE(TYPE.float):
C, DE, HL = _float(expr.value)
C = C[:-1] # Remove 'h' suffix
if len(C) > 2:
C = C[-2:]
C = C[-2:]

DE = DE[:-1] # Remove 'h' suffix
if len(DE) > 4:
DE = DE[-4:]
elif len(DE) < 3:
DE = "00" + DE
DE = ("00" + DE)[-4:]

HL = HL[:-1] # Remove 'h' suffix
if len(HL) > 4:
HL = HL[-4:]
elif len(HL) < 3:
HL = "00" + HL
HL = ("00" + HL)[-4:]

return [C, DE[-2:], DE[:-2], HL[-2:], HL[:-2]]

Expand All @@ -1032,8 +1025,8 @@ def default_value(cls, type_, expr): # TODO: This function must be moved to api
else:
value = int(expr.value)

result = [value, value >> 8, value >> 16, value >> 24]
result = ["%02X" % (v & 0xFF) for v in result]
values = [value, value >> 8, value >> 16, value >> 24]
result = ["%02X" % (v & 0xFF) for v in values]
return result[: type_.size]

@staticmethod
Expand Down Expand Up @@ -1459,7 +1452,10 @@ def visit_FUNCTION(self, node):
if node.convention == CONVENTION.stdcall:
for local_var in node.local_symbol_table.values():
scope = local_var.scope
if local_var.type_ == self.TYPE(TYPE.string): # Only if it's string we free it
if local_var.type_ == self.TYPE(TYPE.string):
if local_var.class_ == CLASS.const:
continue
# Only if it's string we free it
if local_var.class_ != CLASS.array: # Ok just free it
if scope == SCOPE.local or (scope == SCOPE.parameter and not local_var.byref):
if not preserve_hl:
Expand All @@ -1469,8 +1465,6 @@ def visit_FUNCTION(self, node):
offset = -local_var.offset if scope == SCOPE.local else local_var.offset
self.ic_fpload(TYPE.string, local_var.t, offset)
self.runtime_call(RuntimeLabel.MEM_FREE, 0)
elif local_var.class_ == CLASS.const:
continue
else: # This is an array of strings, we must free it unless it's a by_ref array
if scope == SCOPE.local or (scope == SCOPE.parameter and not local_var.byref):
if not preserve_hl:
Expand Down
8 changes: 6 additions & 2 deletions src/symbols/id_/ref/constref.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ConstRef(SymbolRef):

def __init__(self, parent: SymbolID, default_value: Symbol):
super().__init__(parent)
assert default_value.token in ("CONSTEXPR", "NUMBER", "CONST")
assert default_value.token in ("CONSTEXPR", "NUMBER", "CONST", "STRING")
self._value = default_value

@property
Expand All @@ -26,7 +26,11 @@ def t(self) -> str:

@property
def value(self):
if self._value.token in ("NUMBER", "CONST"):
if self._value.token in ("NUMBER", "CONST", "STRING"):
return self._value.value

return self.t

@property
def symbol(self) -> Symbol:
return self._value
12 changes: 8 additions & 4 deletions src/zxbc/zxbparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
is_number,
is_numeric,
is_static,
is_static_str,
is_string,
is_unsigned,
)
Expand Down Expand Up @@ -365,8 +366,8 @@ def make_call(id_: str, lineno: int, args: sym.ARGLIST):
A "call" is just an ID followed by a list of arguments.
E.g. a(4)
- a(4) can be a function call if 'a' is a function
- a(4) can be a string slice if a is a string variable: a$(4)
- a(4) can be an access to an array if a is an array
- a(4) can be a string slice if 'a' is a string variable: a$(4)
- a(4) can be an access to an array if 'a' is an array

This function will inspect the id_. If it is undeclared then
id_ will be taken as a forwarded function.
Expand Down Expand Up @@ -705,8 +706,11 @@ def p_var_decl_ini(p):
else:
# keyword == "CONST"
if defval is None:
errmsg.syntax_error_not_constant(p.lineno(4))
return
if not is_static_str(value):
errmsg.syntax_error_not_constant(p.lineno(4))
return
else:
defval = value

SYMBOL_TABLE.declare_const(idlist[0].name, idlist[0].lineno, typedef, default_value=defval)

Expand Down
Loading