Skip to content

Commit 267b57d

Browse files
authored
Merge pull request #692 from boriel/bugfix/const_substr
fix: allow substr of CONST strings
2 parents 427a64a + 133de73 commit 267b57d

File tree

15 files changed

+4806
-18
lines changed

15 files changed

+4806
-18
lines changed

src/api/check.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ def is_null(*symbols_):
278278
return True
279279

280280

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

292292

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

296299

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

322325

323326
def is_static_str(*p):

src/api/string_labels.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,23 @@
1212
a mapping of constant Strings to Labels.
1313
"""
1414
from collections import defaultdict
15+
from typing import Final
1516

1617
from src.api import tmp_labels
1718

18-
STRING_LABELS: dict[str, str] = defaultdict(tmp_labels.tmp_label)
19+
STRING_LABELS: Final[dict[str, str]] = defaultdict(tmp_labels.tmp_label)
1920

2021

2122
def reset():
2223
"""Initializes this module"""
23-
global STRING_LABELS
2424
STRING_LABELS.clear()
2525

2626

2727
def add_string_label(string: str) -> str:
28-
"""Maps ("folds") the given string, returning an unique label ID.
28+
"""Maps ("folds") the given string, returning a unique label ID.
2929
This allows several constant labels to be initialized to the same address
3030
thus saving memory space.
3131
:param string: the string to map
3232
:return: the unique label ID
3333
"""
34-
global STRING_LABELS
3534
return STRING_LABELS[string]

src/symbols/binary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None):
7979
a, b = left, right # short form names
8080
# Check for constant non-numeric operations
8181
c_type = check.common_type(a, b) # Resulting operation type or None
82-
if c_type: # there must be a common type for a and b
82+
if TYPE.is_numeric(c_type): # there must be a common type for a and b
8383
if (
8484
check.is_numeric(a, b)
8585
and (check.is_const(a) or check.is_number(a))

src/symbols/strslice.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,9 @@ def make_node(cls, lineno: int, s, lower, upper):
105105
if lo > up:
106106
return STRING("", lineno)
107107

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

113112
# a$(0 TO INF.) = a$
114113
if lo == gl.MIN_STRSLICE_IDX and up == gl.MAX_STRSLICE_IDX:

src/zxbc/zxbparser.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ def make_constexpr(lineno, expr):
243243
return sym.CONSTEXPR(expr, lineno=lineno)
244244

245245

246-
def make_strslice(lineno, s, lower, upper):
246+
def make_strslice(lineno: int, s, lower, upper):
247247
"""Wrapper: returns String Slice node"""
248248
return sym.STRSLICE.make_node(lineno, s, lower, upper)
249249

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

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

403-
entry = SYMBOL_TABLE.access_var(id_, lineno)
404-
if entry is None:
405-
return None
403+
if entry.class_ == CLASS.var:
404+
entry = SYMBOL_TABLE.access_var(id_, lineno)
405+
if entry is None:
406+
return None
406407

407408
if len(args) == 1:
408-
return sym.STRSLICE.make_node(lineno, entry, args[0].value, args[0].value)
409+
if entry.class_ == CLASS.var:
410+
return make_strslice(lineno, entry, args[0].value, args[0].value)
411+
# it's a const
412+
return make_strslice(lineno, sym.STRING(entry.value, lineno), args[0].value, args[0].value)
409413

410414
mark_entry_as_accessed(entry)
411415
return entry
@@ -2478,6 +2482,11 @@ def p_string_lp_expr_rp(p):
24782482

24792483
def p_expr_id_substr(p):
24802484
"""string : ID substr"""
2485+
entry = SYMBOL_TABLE.get_entry(p[1])
2486+
if entry is not None and entry.type_ == TYPE.string and entry.token == "CONST":
2487+
p[0] = make_strslice(p.lineno(1), entry, p[2][0], p[2][1])
2488+
return
2489+
24812490
entry = SYMBOL_TABLE.access_var(p[1], p.lineno(1), default_type=TYPE.string)
24822491
p[0] = None
24832492
if entry is None:
@@ -2595,7 +2604,7 @@ def p_idcall_expr(p):
25952604
if p[0] is None:
25962605
return
25972606

2598-
if p[0].token in ("STRSLICE", "ID", "STRING"):
2607+
if p[0].token in ("STRSLICE", "ID", "STRING") or p[0].token == "CONST" and p[0].type_ == TYPE.string:
25992608
entry = SYMBOL_TABLE.access_call(p[1], p.lineno(1))
26002609
mark_entry_as_accessed(entry)
26012610
return

0 commit comments

Comments
 (0)