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
9 changes: 6 additions & 3 deletions src/api/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ def is_null(*symbols_):
return True


def is_SYMBOL(token, *symbols_):
def is_SYMBOL(token: str, *symbols_: symbols.SYMBOL):
"""Returns True if ALL the given argument are AST nodes
of the given token (e.g. 'BINARY')
"""
Expand All @@ -291,7 +291,10 @@ def is_LABEL(*p):


def is_string(*p):
return is_SYMBOL("STRING", *p)
"""Returns True if ALL the arguments are AST nodes
containing STRING or string CONSTANTS
"""
return all(is_SYMBOL("STRING", x) or is_const(x) and is_type(Type.string, x) for x in p)


def is_const(*p):
Expand All @@ -317,7 +320,7 @@ def is_number(*p):
"""Returns True if ALL the arguments are AST nodes
containing NUMBER or numeric CONSTANTS
"""
return all(i.token in ("NUMBER", "CONST") for i in p)
return all(i.token in ("NUMBER", "CONST") and Type.is_numeric(i.type_) for i in p)


def is_static_str(*p):
Expand Down
7 changes: 3 additions & 4 deletions src/api/string_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,23 @@
a mapping of constant Strings to Labels.
"""
from collections import defaultdict
from typing import Final

from src.api import tmp_labels

STRING_LABELS: dict[str, str] = defaultdict(tmp_labels.tmp_label)
STRING_LABELS: Final[dict[str, str]] = defaultdict(tmp_labels.tmp_label)


def reset():
"""Initializes this module"""
global STRING_LABELS
STRING_LABELS.clear()


def add_string_label(string: str) -> str:
"""Maps ("folds") the given string, returning an unique label ID.
"""Maps ("folds") the given string, returning a unique label ID.
This allows several constant labels to be initialized to the same address
thus saving memory space.
:param string: the string to map
:return: the unique label ID
"""
global STRING_LABELS
return STRING_LABELS[string]
2 changes: 1 addition & 1 deletion src/symbols/binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None):
a, b = left, right # short form names
# Check for constant non-numeric operations
c_type = check.common_type(a, b) # Resulting operation type or None
if c_type: # there must be a common type for a and b
if TYPE.is_numeric(c_type): # there must be a common type for a and b
if (
check.is_numeric(a, b)
and (check.is_const(a) or check.is_number(a))
Expand Down
5 changes: 2 additions & 3 deletions src/symbols/strslice.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,9 @@ def make_node(cls, lineno: int, s, lower, upper):
if lo > up:
return STRING("", lineno)

if s.token == "STRING": # A constant string? Recalculate it now
if s.token in ("STRING", "CONST"): # A constant string? Recalculate it now
up += 1
st = s.value.ljust(up) # Procrustean filled (right)
return STRING(st[lo:up], lineno)
return STRING(s.value[lo:up], lineno)

# a$(0 TO INF.) = a$
if lo == gl.MIN_STRSLICE_IDX and up == gl.MAX_STRSLICE_IDX:
Expand Down
23 changes: 16 additions & 7 deletions src/zxbc/zxbparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ def make_constexpr(lineno, expr):
return sym.CONSTEXPR(expr, lineno=lineno)


def make_strslice(lineno, s, lower, upper):
def make_strslice(lineno: int, s, lower, upper):
"""Wrapper: returns String Slice node"""
return sym.STRSLICE.make_node(lineno, s, lower, upper)

Expand Down Expand Up @@ -395,17 +395,21 @@ def make_call(id_: str, lineno: int, args: sym.ARGLIST):
arr.append_child(offset)
return arr

if entry.class_ == CLASS.var: # An already declared/used string var
if entry.class_ in (CLASS.var, CLASS.const): # An already declared/used string var
if len(args) > 1:
errmsg.syntax_error_not_array_nor_func(lineno, id_)
return None

entry = SYMBOL_TABLE.access_var(id_, lineno)
if entry is None:
return None
if entry.class_ == CLASS.var:
entry = SYMBOL_TABLE.access_var(id_, lineno)
if entry is None:
return None

if len(args) == 1:
return sym.STRSLICE.make_node(lineno, entry, args[0].value, args[0].value)
if entry.class_ == CLASS.var:
return make_strslice(lineno, entry, args[0].value, args[0].value)
# it's a const
return make_strslice(lineno, sym.STRING(entry.value, lineno), args[0].value, args[0].value)

mark_entry_as_accessed(entry)
return entry
Expand Down Expand Up @@ -2478,6 +2482,11 @@ def p_string_lp_expr_rp(p):

def p_expr_id_substr(p):
"""string : ID substr"""
entry = SYMBOL_TABLE.get_entry(p[1])
if entry is not None and entry.type_ == TYPE.string and entry.token == "CONST":
p[0] = make_strslice(p.lineno(1), entry, p[2][0], p[2][1])
return

entry = SYMBOL_TABLE.access_var(p[1], p.lineno(1), default_type=TYPE.string)
p[0] = None
if entry is None:
Expand Down Expand Up @@ -2595,7 +2604,7 @@ def p_idcall_expr(p):
if p[0] is None:
return

if p[0].token in ("STRSLICE", "ID", "STRING"):
if p[0].token in ("STRSLICE", "ID", "STRING") or p[0].token == "CONST" and p[0].type_ == TYPE.string:
entry = SYMBOL_TABLE.access_call(p[1], p.lineno(1))
mark_entry_as_accessed(entry)
return
Expand Down
Loading