Skip to content

Commit ee76467

Browse files
authored
Merge pull request #1001 from boriel-basic/bug/cannot_use_array_element_by_ref
fix: implement ByRef with an Array Element
2 parents bc2073e + 0270897 commit ee76467

File tree

6 files changed

+48
-21
lines changed

6 files changed

+48
-21
lines changed

src/api/check.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,13 @@ def check_call_arguments(lineno: int, id_: str, args, filename: str):
160160
return False
161161

162162
if param.byref:
163-
if not isinstance(arg.value, symbols.ID):
163+
if not isinstance(arg.value, (symbols.ID, symbols.ARRAYLOAD)):
164164
errmsg.error(
165165
lineno, "Expected a variable name, not an expression (parameter By Reference)", fname=arg.filename
166166
)
167167
return False
168168

169-
if arg.class_ not in (CLASS.var, CLASS.array):
169+
if arg.class_ not in (CLASS.var, CLASS.array, CLASS.unknown):
170170
errmsg.error(lineno, "Expected a variable or array name (parameter By Reference)")
171171
return False
172172

src/arch/z80/visitor/translator.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
from collections import namedtuple
21
from collections.abc import Callable
3-
from typing import Any
2+
from typing import Any, NamedTuple
43

54
import src.api.errmsg
65
import src.api.global_ as gl
@@ -22,6 +21,8 @@
2221
from src.arch.z80.visitor.translator_visitor import JumpTable, TranslatorVisitor
2322
from src.arch.z80.visitor.unary_op_translator import UnaryOpTranslator
2423
from src.symbols import sym as symbols
24+
from src.symbols.arrayaccess import SymbolARRAYACCESS
25+
from src.symbols.binary import SymbolBINARY
2526
from src.symbols.id_ import ref
2627
from src.symbols.type_ import Type
2728

@@ -30,7 +31,10 @@
3031
"Translator",
3132
)
3233

33-
LabelledData = namedtuple("LabelledData", ("label", "data"))
34+
35+
class LabelledData(NamedTuple):
36+
label: str
37+
data: list[str]
3438

3539

3640
class Translator(TranslatorVisitor):
@@ -210,7 +214,10 @@ def visit_ARGUMENT(self, node):
210214
else:
211215
yield node.value
212216
self.ic_param(node.type_, node.t)
213-
else:
217+
return
218+
219+
# ByRef argument
220+
if node.value.token not in ("ARRAYLOAD", "ARRAYACCESS"):
214221
scope = node.value.scope
215222
if node.t[0] == "_":
216223
t = optemps.new_t()
@@ -229,6 +236,22 @@ def visit_ARGUMENT(self, node):
229236
self.ic_paddr(-node.value.offset, t)
230237

231238
self.ic_param(TYPE.uinteger, t)
239+
return
240+
241+
# Must compute Address of @array(...)
242+
if node.value.scope == SCOPE.global_ and self.O_LEVEL > 1: # Calculate offset if global variable
243+
node.value = SymbolBINARY.make_node(
244+
"PLUS",
245+
symbols.UNARY("ADDRESS", node.value.entry, node.value.lineno, type_=self.TYPE(gl.PTR_TYPE)),
246+
symbols.NUMBER(node.value.offset, lineno=node.value.lineno, type_=self.TYPE(gl.PTR_TYPE)),
247+
lineno=node.lineno,
248+
func=lambda x, y: x + y,
249+
)
250+
else:
251+
node.value = SymbolARRAYACCESS.copy_from(node.value)
252+
node.value = symbols.UNARY("ADDRESS", node.value, node.lineno, type_=self.TYPE(gl.PTR_TYPE))
253+
254+
yield node.value
232255

233256
def visit_ARRAYLOAD(self, node):
234257
scope = node.entry.scope

src/arch/z80/visitor/translator_inst_visitor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ def ic_paaddr(self, t1, t2) -> None:
195195
def ic_paddr(self, t1, t2) -> None:
196196
self.emit("paddr", t1, t2)
197197

198-
def ic_paload(self, type_: TYPE | sym.BASICTYPE, t, offset: int) -> None:
198+
def ic_paload(self, type_: TYPE | sym.BASICTYPE, t, offset: str) -> None:
199199
self.emit(f"paload{self.TSUFFIX(type_)}", t, offset)
200200

201201
def ic_param(self, type_: TYPE | sym.BASICTYPE, t) -> None:

src/symbols/argument.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def byref(self):
6363
@byref.setter
6464
def byref(self, value):
6565
if value:
66-
assert self.value.token in ("VAR", "VARARRAY")
66+
assert self.value.token in ("VAR", "VARARRAY", "ARRAYLOAD")
6767
self._byref = value
6868

6969
@property

src/symbols/arrayaccess.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
# vim: ts=4:et:sw=4:
1+
# ----------------------------------------------------------------------
2+
# Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel)
3+
#
4+
# This program is Free Software and is released under the terms of
5+
# the GNU General License
6+
# ----------------------------------------------------------------------
7+
28
from functools import cached_property
3-
from typing import Optional
9+
from typing import Self
410

511
import src.api.global_ as gl
612
from src.api import check, errmsg
@@ -10,13 +16,6 @@
1016
from src.symbols.id_ import SymbolID
1117
from src.symbols.typecast import SymbolTYPECAST as TYPECAST
1218

13-
# ----------------------------------------------------------------------
14-
# Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel)
15-
#
16-
# This program is Free Software and is released under the terms of
17-
# the GNU General License
18-
# ----------------------------------------------------------------------
19-
2019

2120
class SymbolARRAYACCESS(SymbolCALL):
2221
"""Defines an array access. It's pretty much like a function call
@@ -38,7 +37,7 @@ def __init__(self, entry, arglist: SymbolARGLIST, lineno: int, filename: str):
3837
self.entry.ref.is_dynamically_accessed = True
3938

4039
@property
41-
def entry(self):
40+
def entry(self) -> SymbolID:
4241
return self.children[0]
4342

4443
@entry.setter
@@ -54,7 +53,7 @@ def type_(self):
5453
return self.entry.type_
5554

5655
@property
57-
def arglist(self):
56+
def arglist(self) -> SymbolARGLIST:
5857
return self.children[1]
5958

6059
@arglist.setter
@@ -98,7 +97,7 @@ def is_constant(self) -> bool:
9897
return self.offset is None
9998

10099
@classmethod
101-
def make_node(cls, id_: str, arglist: SymbolARGLIST, lineno: int, filename: str) -> Optional["SymbolARRAYACCESS"]:
100+
def make_node(cls, id_: str, arglist: SymbolARGLIST, lineno: int, filename: str) -> Self | None:
102101
"""Creates an array access. A(x1, x2, ..., xn)"""
103102
assert isinstance(arglist, SymbolARGLIST)
104103
variable = gl.SYMBOL_TABLE.access_array(id_, lineno)
@@ -129,3 +128,7 @@ def make_node(cls, id_: str, arglist: SymbolARGLIST, lineno: int, filename: str)
129128

130129
# Returns the variable entry and the node
131130
return cls(variable, arglist, lineno, filename)
131+
132+
@classmethod
133+
def copy_from(cls, other: Self) -> Self | None:
134+
return cls(entry=other.entry, arglist=other.arglist, lineno=other.lineno, filename=other.filename)

src/symbols/arrayload.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
class SymbolARRAYLOAD(SymbolARRAYACCESS):
1414
"""This class is the same as SymbolARRAYACCESS, we just declare it to make
15-
a distinction. (e.g. the Token is gotten from the class name)
15+
a distinction. (e.g. the Token is gotten from the class name).
16+
1617
"""
1718

1819
pass

0 commit comments

Comments
 (0)