Skip to content

Commit 0a87262

Browse files
authored
Merge pull request #562 from boriel/feature/optimize_mul8_and_mul16_for_zxnext
Feature/optimize mul8 and mul16 for zxnext
2 parents 590c0a1 + f8cef32 commit 0a87262

206 files changed

Lines changed: 13004 additions & 13045 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/api/check.py

Lines changed: 84 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,22 @@
2222

2323

2424
__all__ = [
25-
'check_type',
26-
'check_is_declared_explicit',
27-
'check_and_make_label',
28-
'check_type_is_explicit',
29-
'check_call_arguments',
30-
'check_pending_calls',
31-
'check_pending_labels',
32-
'is_number',
33-
'is_const',
34-
'is_static',
35-
'is_string',
36-
'is_numeric',
37-
'is_dynamic',
38-
'is_null',
39-
'is_unsigned',
40-
'common_type'
25+
"check_type",
26+
"check_is_declared_explicit",
27+
"check_and_make_label",
28+
"check_type_is_explicit",
29+
"check_call_arguments",
30+
"check_pending_calls",
31+
"check_pending_labels",
32+
"is_number",
33+
"is_const",
34+
"is_static",
35+
"is_string",
36+
"is_numeric",
37+
"is_dynamic",
38+
"is_null",
39+
"is_unsigned",
40+
"common_type",
4141
]
4242

4343

@@ -46,8 +46,9 @@
4646
# These functions trigger syntax errors if checking goal fails.
4747
# ----------------------------------------------------------------------
4848

49+
4950
def check_type(lineno, type_list, arg):
50-
""" Check arg's type is one in type_list, otherwise,
51+
"""Check arg's type is one in type_list, otherwise,
5152
raises an error.
5253
"""
5354
if not isinstance(type_list, list):
@@ -57,17 +58,15 @@ def check_type(lineno, type_list, arg):
5758
return True
5859

5960
if len(type_list) == 1:
60-
errmsg.error(lineno, "Wrong expression type '%s'. Expected '%s'" %
61-
(arg.type_, type_list[0]))
61+
errmsg.error(lineno, "Wrong expression type '%s'. Expected '%s'" % (arg.type_, type_list[0]))
6262
else:
63-
errmsg.error(lineno, "Wrong expression type '%s'. Expected one of '%s'"
64-
% (arg.type_, tuple(type_list)))
63+
errmsg.error(lineno, "Wrong expression type '%s'. Expected one of '%s'" % (arg.type_, tuple(type_list)))
6564

6665
return False
6766

6867

69-
def check_is_declared_explicit(lineno: int, id_: str, classname: str = 'variable') -> bool:
70-
""" Check if the current ID is already declared.
68+
def check_is_declared_explicit(lineno: int, id_: str, classname: str = "variable") -> bool:
69+
"""Check if the current ID is already declared.
7170
If not, triggers a "undeclared identifier" error,
7271
if the --explicit command line flag is enabled (or #pragma
7372
option strict is in use).
@@ -100,12 +99,12 @@ def check_type_is_explicit(lineno: int, id_: str, type_):
10099

101100

102101
def check_call_arguments(lineno: int, id_: str, args):
103-
""" Check arguments against function signature.
102+
"""Check arguments against function signature.
104103
105-
Checks every argument in a function call against a function.
106-
Returns True on success.
104+
Checks every argument in a function call against a function.
105+
Returns True on success.
107106
"""
108-
if not global_.SYMBOL_TABLE.check_is_declared(id_, lineno, 'function'):
107+
if not global_.SYMBOL_TABLE.check_is_declared(id_, lineno, "function"):
109108
return False
110109

111110
if not check_is_callable(lineno, id_):
@@ -114,9 +113,10 @@ def check_call_arguments(lineno: int, id_: str, args):
114113
entry = global_.SYMBOL_TABLE.get_entry(id_)
115114

116115
if len(args) != len(entry.params):
117-
c = 's' if len(entry.params) != 1 else ''
118-
errmsg.error(lineno, f"Function '{id_}' takes {len(entry.params)} parameter{c}, not {len(args)}",
119-
fname=entry.filename)
116+
c = "s" if len(entry.params) != 1 else ""
117+
errmsg.error(
118+
lineno, f"Function '{id_}' takes {len(entry.params)} parameter{c}, not {len(args)}", fname=entry.filename
119+
)
120120
return False
121121

122122
for arg, param in zip(args, entry.params):
@@ -129,8 +129,9 @@ def check_call_arguments(lineno: int, id_: str, args):
129129

130130
if param.byref:
131131
if not isinstance(arg.value, symbols.VAR):
132-
errmsg.error(lineno, "Expected a variable name, not an expression (parameter By Reference)",
133-
fname=arg.filename)
132+
errmsg.error(
133+
lineno, "Expected a variable name, not an expression (parameter By Reference)", fname=arg.filename
134+
)
134135
return False
135136

136137
if arg.class_ not in (CLASS.var, CLASS.array):
@@ -143,15 +144,18 @@ def check_call_arguments(lineno: int, id_: str, args):
143144
arg.value.add_required_symbol(param)
144145

145146
if entry.forwarded: # The function / sub was DECLARED but not implemented
146-
errmsg.error(lineno, "%s '%s' declared but not implemented" % (CLASS.to_string(entry.class_), entry.name),
147-
fname=entry.filename)
147+
errmsg.error(
148+
lineno,
149+
"%s '%s' declared but not implemented" % (CLASS.to_string(entry.class_), entry.name),
150+
fname=entry.filename,
151+
)
148152
return False
149153

150154
return True
151155

152156

153157
def check_pending_calls():
154-
""" Calls the above function for each pending call of the current scope
158+
"""Calls the above function for each pending call of the current scope
155159
level
156160
"""
157161
result = True
@@ -164,7 +168,7 @@ def check_pending_calls():
164168

165169

166170
def check_pending_labels(ast):
167-
""" Iteratively traverses the node looking for ID with no class set,
171+
"""Iteratively traverses the node looking for ID with no class set,
168172
marks them as labels, and check they've been declared.
169173
170174
This way we avoid stack overflow for high line-numbered listings.
@@ -183,7 +187,7 @@ def check_pending_labels(ast):
183187
for x in node.children:
184188
pending.append(x)
185189

186-
if node.token != 'VAR' or (node.token == 'VAR' and node.class_ is not CLASS.unknown):
190+
if node.token != "VAR" or (node.token == "VAR" and node.class_ is not CLASS.unknown):
187191
continue
188192

189193
tmp = global_.SYMBOL_TABLE.get_entry(node.name)
@@ -199,7 +203,7 @@ def check_pending_labels(ast):
199203

200204

201205
def check_and_make_label(lbl: Union[str, int, float], lineno):
202-
""" Checks if the given label (or line number) is valid and, if so,
206+
"""Checks if the given label (or line number) is valid and, if so,
203207
returns a label object.
204208
:param lbl: Line number of label (string)
205209
:param lineno: Line number in the basic source code for error reporting
@@ -209,7 +213,7 @@ def check_and_make_label(lbl: Union[str, int, float], lineno):
209213
if lbl == int(lbl):
210214
id_ = str(int(lbl))
211215
else:
212-
errmsg.error(lineno, 'Line numbers must be integers.')
216+
errmsg.error(lineno, "Line numbers must be integers.")
213217
return None
214218
else:
215219
id_ = lbl
@@ -221,17 +225,17 @@ def check_and_make_label(lbl: Union[str, int, float], lineno):
221225
# Function for checking some arguments
222226
# ----------------------------------------------------------------------
223227
def is_null(*symbols_):
224-
""" True if no nodes or all the given nodes are either
228+
"""True if no nodes or all the given nodes are either
225229
None, NOP or empty blocks. For blocks this applies recursively
226230
"""
227231
for sym in symbols_:
228232
if sym is None:
229233
continue
230234
if not isinstance(sym, symbols.SYMBOL):
231235
return False
232-
if sym.token == 'NOP':
236+
if sym.token == "NOP":
233237
continue
234-
if sym.token == 'BLOCK':
238+
if sym.token == "BLOCK":
235239
if not is_null(*sym.children):
236240
return False
237241
continue
@@ -240,61 +244,57 @@ def is_null(*symbols_):
240244

241245

242246
def is_SYMBOL(token, *symbols_):
243-
""" Returns True if ALL of the given argument are AST nodes
247+
"""Returns True if ALL of the given argument are AST nodes
244248
of the given token (e.g. 'BINARY')
245249
"""
246250
assert all(isinstance(x, symbols.SYMBOL) for x in symbols_)
247251
return all(sym.token == token for sym in symbols_)
248252

249253

250254
def is_LABEL(*p):
251-
return is_SYMBOL('LABEL', *p)
255+
return is_SYMBOL("LABEL", *p)
252256

253257

254258
def is_string(*p):
255-
return is_SYMBOL('STRING', *p)
259+
return is_SYMBOL("STRING", *p)
256260

257261

258262
def is_const(*p):
259-
""" A constant in the program, like CONST a = 5
260-
"""
261-
return is_SYMBOL('VAR', *p) and all(x.class_ == CLASS.const for x in p)
263+
"""A constant in the program, like CONST a = 5"""
264+
return is_SYMBOL("VAR", *p) and all(x.class_ == CLASS.const for x in p)
262265

263266

264267
def is_CONST(*p):
265-
""" Not to be confused with the above.
268+
"""Not to be confused with the above.
266269
Check it's a CONSTant expression
267270
"""
268-
return is_SYMBOL('CONST', *p)
271+
return is_SYMBOL("CONST", *p)
269272

270273

271274
def is_static(*p):
272-
""" A static value (does not change at runtime)
275+
"""A static value (does not change at runtime)
273276
which is known at compile time
274277
"""
275-
return all(is_CONST(x) or
276-
is_number(x) or
277-
is_const(x)
278-
for x in p)
278+
return all(is_CONST(x) or is_number(x) or is_const(x) for x in p)
279279

280280

281281
def is_number(*p):
282-
""" Returns True if ALL of the arguments are AST nodes
282+
"""Returns True if ALL of the arguments are AST nodes
283283
containing NUMBER or numeric CONSTANTS
284284
"""
285285
try:
286-
return all(i.token == 'NUMBER' or (i.token == 'ID' and i.class_ == CLASS.const) for i in p)
286+
return all(i.token == "NUMBER" or (i.token == "ID" and i.class_ == CLASS.const) for i in p)
287287
except Exception:
288288
pass
289289

290290
return False
291291

292292

293293
def is_var(*p):
294-
""" Returns True if ALL of the arguments are AST nodes
294+
"""Returns True if ALL of the arguments are AST nodes
295295
containing ID
296296
"""
297-
return is_SYMBOL('VAR', *p)
297+
return is_SYMBOL("VAR", *p)
298298

299299

300300
def is_integer(*p):
@@ -307,8 +307,7 @@ def is_integer(*p):
307307

308308

309309
def is_unsigned(*p):
310-
""" Returns false unless all types in p are unsigned
311-
"""
310+
"""Returns false unless all types in p are unsigned"""
312311
try:
313312
return all(i.type_.is_basic and Type.is_unsigned(i.type_) for i in p)
314313
except Exception:
@@ -318,8 +317,7 @@ def is_unsigned(*p):
318317

319318

320319
def is_signed(*p):
321-
""" Returns false unless all types in p are signed
322-
"""
320+
"""Returns false unless all types in p are signed"""
323321
try:
324322
return all(i.type_.is_basic and Type.is_signed(i.type_) for i in p)
325323
except Exception:
@@ -329,8 +327,7 @@ def is_signed(*p):
329327

330328

331329
def is_numeric(*p):
332-
""" Returns false unless all elements in p are of numerical type
333-
"""
330+
"""Returns false unless all elements in p are of numerical type"""
334331
try:
335332
return all(i.type_.is_basic and Type.is_numeric(i.type_) for i in p)
336333
except Exception:
@@ -340,8 +337,7 @@ def is_numeric(*p):
340337

341338

342339
def is_type(type_, *p):
343-
""" True if all args have the same type
344-
"""
340+
"""True if all args have the same type"""
345341
try:
346342
return all(i.type_ == type_ for i in p)
347343
except Exception:
@@ -351,7 +347,7 @@ def is_type(type_, *p):
351347

352348

353349
def is_dynamic(*p): # TODO: Explain this better
354-
""" True if all args are dynamic (e.g. Strings, dynamic arrays, etc)
350+
"""True if all args are dynamic (e.g. Strings, dynamic arrays, etc)
355351
The use a ptr (ref) and it might change during runtime.
356352
"""
357353
try:
@@ -363,13 +359,12 @@ def is_dynamic(*p): # TODO: Explain this better
363359

364360

365361
def is_callable(*p):
366-
""" True if all the args are functions and / or subroutines
367-
"""
362+
"""True if all the args are functions and / or subroutines"""
368363
return all(isinstance(x, symbols.FUNCTION) for x in p)
369364

370365

371366
def is_block_accessed(block):
372-
""" Returns True if a block is "accessed". A block of code is accessed if
367+
"""Returns True if a block is "accessed". A block of code is accessed if
373368
it has a LABEL and it is used in a GOTO, GO SUB or @address access
374369
:param block: A block of code (AST node)
375370
:return: True / False depending if it has labels accessed or not
@@ -381,13 +376,12 @@ def is_block_accessed(block):
381376

382377

383378
def is_temporary_value(node) -> bool:
384-
""" Returns if the AST node value is a variable or a temporary copy in the heap.
385-
"""
386-
return node.token not in ('PARAMDECL', 'STRING', 'VAR') and node.t[0] not in ('_', '#')
379+
"""Returns if the AST node value is a variable or a temporary copy in the heap."""
380+
return node.token not in ("PARAMDECL", "STRING", "VAR") and node.t[0] not in ("_", "#")
387381

388382

389383
def common_type(a, b):
390-
""" Returns a type which is common for both a and b types.
384+
"""Returns a type which is common for both a and b types.
391385
Returns None if no common types allowed.
392386
"""
393387
if a is None or b is None:
@@ -435,17 +429,26 @@ def common_type(a, b):
435429

436430

437431
def is_ender(node) -> bool:
438-
""" Returns whether this node ends a block, that is, the following instruction won't be
432+
"""Returns whether this node ends a block, that is, the following instruction won't be
439433
executed after this one
440434
"""
441-
return node.token in {'END', 'ERROR',
442-
'CONTINUE_DO', 'CONTINUE_FOR', 'CONTINUE_WHILE',
443-
'EXIT_DO', 'EXIT_FOR', 'EXIT_WHILE',
444-
'GOTO', 'RETURN', 'STOP'}
435+
return node.token in {
436+
"END",
437+
"ERROR",
438+
"CONTINUE_DO",
439+
"CONTINUE_FOR",
440+
"CONTINUE_WHILE",
441+
"EXIT_DO",
442+
"EXIT_FOR",
443+
"EXIT_WHILE",
444+
"GOTO",
445+
"RETURN",
446+
"STOP",
447+
}
445448

446449

447450
def check_class(node, class_: CLASS, lineno: int) -> bool:
448-
""" Returns whether the given node has CLASS.unknown or the given class_.
451+
"""Returns whether the given node has CLASS.unknown or the given class_.
449452
It False, it will emit a syntax error
450453
"""
451454
if node.class_ == CLASS.unknown or node.class_ == class_:

0 commit comments

Comments
 (0)