Skip to content

Commit 1ba939b

Browse files
committed
Allow passing arrays as parameters
* Arrays will be passed always by Ref * Uses the same syntax as in FreeBasic * Allows different array-bounds to use the same function Still some extra checks pending
1 parent 038fa96 commit 1ba939b

2 files changed

Lines changed: 110 additions & 47 deletions

File tree

arch/zx48k/translator.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from api.errors import InvalidLoopError
2121
from api.errors import InvalidOperatorError
2222
from api.errors import InvalidBuiltinFunctionError
23+
from api.errors import InternalError
2324

2425
from . import backend
2526
from .backend.__float import _float
@@ -300,17 +301,18 @@ def visit_LETARRAY(self, node):
300301
if scope == SCOPE.global_:
301302
self.ic_astore(arr.type_, arr.entry.mangled, node.children[1].t)
302303
elif scope == SCOPE.parameter:
303-
self.ic_pastore(arr.type_, arr.entry.offset, node.children[1].t)
304+
# HINT: Arrays are always passed ByREF
305+
self.ic_pastore(arr.type_, '*{}'.format(arr.entry.offset), node.children[1].t)
304306
elif scope == SCOPE.local:
305307
self.ic_pastore(arr.type_, -arr.entry.offset, node.children[1].t)
306308
else:
307309
name = arr.entry.data_label
308310
if scope == SCOPE.global_:
309311
self.ic_store(arr.type_, '%s + %i' % (name, arr.offset), node.children[1].t)
310-
elif scope == SCOPE.parameter:
311-
self.ic_pstore(arr.type_, arr.entry.offset - arr.offset, node.children[1].t)
312312
elif scope == SCOPE.local:
313313
self.ic_pstore(arr.type_, -(arr.entry.offset - arr.offset), node.children[1].t)
314+
else:
315+
raise InternalError("Invalid scope {} for variable '{}'".format(scope, arr.entry.name))
314316

315317
def visit_LETSUBSTR(self, node):
316318
yield node.children[3]
@@ -1345,12 +1347,12 @@ def visit_FUNCTION(self, node):
13451347
# if self.O_LEVEL > 1:
13461348
# return
13471349

1348-
if local_var.class_ == CLASS.array and local_var.scope != SCOPE.global_:
1350+
if local_var.class_ == CLASS.array and local_var.scope == SCOPE.local:
13491351
l = [len(local_var.bounds) - 1] + [x.count for x in local_var.bounds[1:]] # TODO Check this
13501352
q = []
13511353
for x in l:
13521354
q.append('%02X' % (x & 0xFF))
1353-
q.append('%02X' % (x >> 8))
1355+
q.append('%02X' % ((x & 0xFF) >> 8))
13541356

13551357
q.append('%02X' % local_var.type_.size)
13561358
r = []

zxbparser.py

Lines changed: 103 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ def make_array_access(id_, lineno, arglist):
294294
""" Creates an array access. A(x1, x2, ..., xn).
295295
This is an RVALUE (Read the element)
296296
"""
297+
for i, arg in enumerate(arglist):
298+
arg.value = make_typecast(TYPE.by_name(api.constants.TYPE.to_string(gl.BOUND_TYPE)), arg.value, arg.lineno)
299+
297300
return symbols.ARRAYACCESS.make_node(id_, arglist, lineno)
298301

299302

@@ -379,10 +382,10 @@ def make_call(id_, lineno, args):
379382
return make_func_call(id_, lineno, args)
380383

381384

382-
def make_param_decl(id_, lineno, typedef):
385+
def make_param_decl(id_, lineno, typedef, is_array=False):
383386
""" Wrapper that creates a param declaration
384387
"""
385-
return SYMBOL_TABLE.declare_param(id_, lineno, typedef)
388+
return SYMBOL_TABLE.declare_param(id_, lineno, typedef, is_array)
386389

387390

388391
def make_type(typename, lineno, implicit=False):
@@ -1047,43 +1050,13 @@ def p_assignment(p):
10471050
syntax_error(p.lineno(i), 'Cannot assign an array to an scalar variable')
10481051
return
10491052

1050-
if variable.class_ == CLASS.array:
1051-
if q1class_ != variable.class_:
1052-
syntax_error(p.lineno(i), 'Cannot assign an scalar to an array variable')
1053-
return
1054-
1055-
if q[1].type_ != variable.type_:
1056-
syntax_error(p.lineno(i), 'Arrays must have the same element type')
1057-
return
1058-
1059-
if variable.memsize != q[1].memsize:
1060-
syntax_error(p.lineno(i), "Arrays '%s' and '%s' must have the same size" %
1061-
(variable.name, q[1].name))
1062-
return
1063-
1064-
if variable.count != q[1].count:
1065-
warning(p.lineno(i), "Arrays '%s' and '%s' don't have the same number of dimensions" %
1066-
(variable.name, q[1].name))
1067-
else:
1068-
for b1, b2 in zip(variable.bounds, q[1].bounds):
1069-
if b1.count != b2.count:
1070-
warning(p.lineno(i), "Arrays '%s' and '%s' don't have the same dimensions" %
1071-
(variable.name, q[1].name))
1072-
break
1073-
# Array copy
1074-
variable.accessed = True
1075-
p[0] = make_sentence('ARRAYCOPY', variable, q[1])
1076-
return
1077-
10781053
expr = make_typecast(variable.type_, q[1], p.lineno(i))
10791054
p[0] = make_sentence('LET', variable, expr)
10801055

10811056

10821057
def p_lexpr(p):
10831058
""" lexpr : ID EQ
10841059
| LET ID EQ
1085-
| ARRAY_ID EQ
1086-
| LET ARRAY_ID EQ
10871060
"""
10881061
global LET_ASSIGNMENT
10891062

@@ -1099,6 +1072,49 @@ def p_lexpr(p):
10991072
SYMBOL_TABLE.access_id(p[i], p.lineno(i))
11001073

11011074

1075+
def p_array_copy(p):
1076+
""" statement : ARRAY_ID EQ ARRAY_ID
1077+
| LET ARRAY_ID EQ ARRAY_ID
1078+
"""
1079+
if p[1] == 'LET':
1080+
array_id1, array_id2 = p[2], p[4]
1081+
l1, l2 = p.lineno(2), p.lineno(4)
1082+
else:
1083+
array_id1, array_id2 = p[1], p[3]
1084+
l1, l2 = p.lineno(1), p.lineno(3)
1085+
1086+
larray = SYMBOL_TABLE.access_id(array_id1, l1)
1087+
rarray = SYMBOL_TABLE.access_id(array_id2, l2)
1088+
1089+
if larray is None or rarray is None:
1090+
p[0] = None
1091+
return
1092+
1093+
if larray.type_ != rarray.type_:
1094+
syntax_error(l1, 'Arrays must have the same element type')
1095+
return
1096+
1097+
if larray.memsize != rarray.memsize:
1098+
syntax_error(l1, "Arrays '%s' and '%s' must have the same size" %
1099+
(array_id1, array_id2))
1100+
return
1101+
1102+
if larray.count != rarray.count:
1103+
warning(l1, "Arrays '%s' and '%s' don't have the same number of dimensions" %
1104+
(larray.name, rarray.name))
1105+
else:
1106+
for b1, b2 in zip(larray.bounds, rarray.bounds):
1107+
if b1.count != b2.count:
1108+
warning(l1, "Arrays '%s' and '%s' don't have the same dimensions" %
1109+
(array_id1, array_id2))
1110+
break
1111+
# Array copy
1112+
larray.accessed = True
1113+
rarray.accessed = True
1114+
p[0] = make_sentence('ARRAYCOPY', larray, rarray)
1115+
return
1116+
1117+
11021118
def p_arr_assignment(p):
11031119
""" statement : ARRAY_ID arg_list EQ expr
11041120
| LET ARRAY_ID arg_list EQ expr
@@ -2543,7 +2559,6 @@ def p_exprstr_file(p):
25432559

25442560
def p_id_expr(p):
25452561
""" bexpr : ID
2546-
| ARRAY_ID
25472562
"""
25482563
entry = SYMBOL_TABLE.access_id(p[1], p.lineno(1), default_class=CLASS.var)
25492564
if entry is None:
@@ -2557,7 +2572,7 @@ def p_id_expr(p):
25572572

25582573
p[0] = entry
25592574

2560-
if entry.class_ == CLASS.array:
2575+
if entry.class_ == CLASS.array: # HINT: This should never happen now
25612576
if not LET_ASSIGNMENT:
25622577
syntax_error(p.lineno(1), "Variable '%s' is an array and cannot be used in this context" % p[1])
25632578
p[0] = None
@@ -2769,18 +2784,40 @@ def p_arg_list_arg(p):
27692784

27702785

27712786
def p_arguments(p):
2772-
""" arguments : arguments COMMA expr
2787+
""" arguments : argument
2788+
"""
2789+
if p[1] is None:
2790+
p[0] = None
2791+
return
2792+
2793+
p[0] = make_arg_list(p[1])
2794+
2795+
2796+
def p_arguments_argument(p):
2797+
""" arguments : arguments COMMA argument
27732798
"""
27742799
if p[1] is None or p[3] is None:
27752800
p[0] = None
27762801
else:
2777-
p[0] = make_arg_list(p[1], make_argument(p[3], p.lineno(2)))
2802+
p[0] = make_arg_list(p[1], p[3])
27782803

27792804

27802805
def p_argument(p):
2781-
""" arguments : expr %prec ID
2806+
""" argument : expr
27822807
"""
2783-
p[0] = make_arg_list(make_argument(p[1], p.lineno(1)))
2808+
p[0] = make_argument(p[1], p.lineno(1))
2809+
2810+
2811+
def p_argument_array(p):
2812+
""" argument : ARRAY_ID
2813+
"""
2814+
entry = SYMBOL_TABLE.access_array(p[1], p.lineno(1))
2815+
if entry is None:
2816+
p[0] = None
2817+
return
2818+
2819+
entry.accessed = True
2820+
p[0] = make_argument(entry, p.lineno(1))
27842821

27852822

27862823
def p_funcdecl(p):
@@ -2960,18 +2997,42 @@ def p_param_byref_definition(p):
29602997
def p_param_byval_definition(p):
29612998
""" param_definition : BYVAL param_def
29622999
"""
2963-
p[0] = p[2]
3000+
param_def = p[2]
3001+
p[0] = param_def
29643002

29653003
if p[0] is not None:
2966-
p[0].byref = False
3004+
if param_def.class_ == CLASS.array:
3005+
api.errmsg.syntax_error_cannot_pass_array_by_value(p.lineno(1), param_def.name)
3006+
p[0] = None
3007+
return
3008+
param_def.byref = False
29673009

29683010

29693011
def p_param_definition(p):
29703012
""" param_definition : param_def
29713013
"""
2972-
p[0] = p[1]
3014+
param_def = p[1]
3015+
p[0] = param_def
29733016
if p[0] is not None:
2974-
p[0].byref = OPTIONS.byref.value
3017+
if param_def.class_ == CLASS.array:
3018+
param_def.byref = True
3019+
else:
3020+
param_def.byref = OPTIONS.byref.value
3021+
3022+
3023+
def p_param_def_array(p):
3024+
""" param_def : ID LP RP typedef
3025+
"""
3026+
typeref = p[4]
3027+
if typeref is None:
3028+
p[0] = None
3029+
return
3030+
3031+
lineno = p.lineno(1)
3032+
id_ = p[1]
3033+
3034+
api.check.check_type_is_explicit(lineno, id_, typeref)
3035+
p[0] = make_param_decl(id_, lineno, typeref, is_array=True)
29753036

29763037

29773038
def p_param_def_type(p):

0 commit comments

Comments
 (0)