Skip to content

Commit 275a72c

Browse files
committed
feat: allow optional parameters!
1 parent 69b6ed8 commit 275a72c

15 files changed

Lines changed: 216 additions & 14 deletions

src/api/check.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ def check_call_arguments(lineno: int, id_: str, args):
112112

113113
entry = global_.SYMBOL_TABLE.get_entry(id_)
114114

115+
if len(args) < len(entry.params): # try filling default params
116+
for param in entry.params[len(args) :]:
117+
if param.default_value is None:
118+
break
119+
symbols.ARGLIST.make_node(args, symbols.ARGUMENT(param.default_value, lineno=lineno, byref=False))
120+
115121
if len(args) != len(entry.params):
116122
c = "s" if len(entry.params) != 1 else ""
117123
errmsg.error(

src/api/errmsg.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,13 @@ def syntax_error_cannot_initialize_array_of_type(lineno: int, type_name: str):
303303
error(lineno, f"Cannot initialize array of type {type_name}")
304304

305305

306+
# ----------------------------------------
307+
# Cannot define a default array argument
308+
# ----------------------------------------
309+
def syntax_error_cannot_define_default_array_argument(lineno: int):
310+
error(lineno, "Cannot define default array argument")
311+
312+
306313
# ----------------------------------------
307314
# Error, ID is a ... not a ...
308315
# ----------------------------------------
@@ -319,4 +326,11 @@ def syntax_error_already_declared(lineno: int, id_name: str, as_class: CLASS, at
319326
error(lineno, f"'{id_name}' already declared as {as_class} at {at_lineno}")
320327

321328

329+
# ----------------------------------------
330+
# Can't declare a mandatory parameter after an optional one
331+
# ----------------------------------------
332+
def syntax_error_mandatory_param_after_optional(lineno: int, param1: str, param2: str):
333+
error(lineno, f"Can't declare mandatory param '{param2}' after optional param '{param1}'")
334+
335+
322336
# endregion

src/api/symboltable.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from .errmsg import warning_not_used
3636
from .errmsg import syntax_error_func_type_mismatch
3737
from .errmsg import syntax_error_not_array_nor_func
38+
from .errmsg import syntax_error_cannot_define_default_array_argument
3839

3940
from .constants import DEPRECATED_SUFFIXES
4041
from .constants import SUFFIX_TYPE
@@ -695,26 +696,33 @@ def declare_label(self, id_: str, lineno: int) -> Optional[SymbolLABEL]:
695696
entry.type_ = self.basic_types[global_.PTR_TYPE]
696697
return entry
697698

698-
def declare_param(self, id_: str, lineno: int, type_=None, is_array=False) -> Optional[SymbolVAR]:
699+
def declare_param(
700+
self, id_: str, lineno: int, type_=None, is_array=False, default_value: Optional[Symbol] = None
701+
) -> Optional[SymbolVAR]:
699702
"""Declares a parameter
700703
Check if entry.declared is False. Otherwise raises an error.
701704
"""
702705
if not self.check_is_undeclared(id_, lineno, classname="parameter", scope=self.current_scope, show_error=True):
703706
return None
704707

705708
if is_array:
709+
if default_value is not None:
710+
syntax_error_cannot_define_default_array_argument(lineno)
711+
return None
712+
706713
entry = self.declare(id_, lineno, symbols.VARARRAY(id_, symbols.BOUNDLIST(), lineno, None, type_))
707714
entry.callable = True
708715
entry.scope = SCOPE.parameter
709716
else:
710-
entry = self.declare(id_, lineno, symbols.PARAMDECL(id_, lineno, type_))
717+
entry = self.declare(id_, lineno, symbols.PARAMDECL(id_, lineno, type_, default_value))
711718

712719
if entry is None:
713720
return None
714721

715722
entry.declared = True
716723
if entry.type_.implicit:
717724
warning_implicit_type(lineno, id_, type_)
725+
718726
return entry
719727

720728
def declare_array(self, id_: str, lineno: int, type_, bounds, default_value=None, addr=None):

src/arch/z80/translator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ def visit_FUNCTION(self, node):
14471447
if local_var.default_value is not None:
14481448
r.extend(self.array_default_value(local_var.type_, local_var.default_value))
14491449
self.ic_larrd(local_var.offset, q, local_var.size, r, bound_ptrs) # Initializes array bounds
1450-
elif local_var.class_ == CLASS.const:
1450+
elif local_var.class_ == CLASS.const or local_var.scope == SCOPE.parameter:
14511451
continue
14521452
else: # Local vars always defaults to 0, so if 0 we do nothing
14531453
if local_var.default_value is not None and local_var.default_value != 0:

src/parsetab/tabs.dbm.bak

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
'zxbpp', (0, 76970)
22
'asmparse', (77312, 268394)
33
'zxnext_asmparse', (346112, 298411)
4-
'zxbparser', (644608, 703160)
4+
'zxbparser', (644608, 704752)

src/parsetab/tabs.dbm.dat

1.55 KB
Binary file not shown.

src/parsetab/tabs.dbm.dir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
'zxbpp', (0, 76970)
22
'asmparse', (77312, 268394)
33
'zxnext_asmparse', (346112, 298411)
4-
'zxbparser', (644608, 703160)
4+
'zxbparser', (644608, 704752)

src/symbols/paramdecl.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,27 @@
88
# This program is Free Software and is released under the terms of
99
# the GNU General License
1010
# ----------------------------------------------------------------------
11+
from typing import Optional
12+
13+
import src.api.global_ as gl
1114

1215
from src.api.constants import CLASS
1316
from src.api.constants import SCOPE
1417
from src.api.config import OPTIONS
15-
import src.api.global_ as gl
16-
from .type_ import SymbolBASICTYPE as BasicType
17-
from .var import SymbolVAR
18+
from src.symbols.type_ import SymbolBASICTYPE as BasicType
19+
from src.symbols.var import SymbolVAR
20+
from src.symbols.symbol_ import Symbol
1821

1922

2023
class SymbolPARAMDECL(SymbolVAR):
2124
"""Defines a parameter declaration"""
2225

23-
def __init__(self, varname, lineno, type_=None):
24-
super(SymbolPARAMDECL, self).__init__(varname, lineno, type_=type_, class_=CLASS.var)
26+
def __init__(self, varname: str, lineno: int, type_=None, default_value: Optional[Symbol] = None):
27+
super().__init__(varname, lineno, type_=type_, class_=CLASS.var)
2528
self.byref = OPTIONS.default_byref # By default all params By value (false)
2629
self.offset = None # Set by PARAMLIST, contains positive offset from top of the stack
2730
self.scope = SCOPE.parameter
31+
self.default_value = default_value
2832

2933
@property
3034
def size(self):

src/zxbc/zxbparser.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,9 @@ def make_call(id_: str, lineno: int, args: symbols.ARGLIST):
411411
return make_func_call(id_, lineno, args)
412412

413413

414-
def make_param_decl(id_: str, lineno: int, typedef, is_array=False):
414+
def make_param_decl(id_: str, lineno: int, typedef, is_array: bool, default_value: Optional[symbols.SYMBOL] = None):
415415
"""Wrapper that creates a param declaration"""
416-
return SYMBOL_TABLE.declare_param(id_, lineno, typedef, is_array)
416+
return SYMBOL_TABLE.declare_param(id_, lineno, typedef, is_array, default_value)
417417

418418

419419
def make_type(typename, lineno, implicit=False):
@@ -2931,6 +2931,10 @@ def p_param_decl_list(p):
29312931

29322932
def p_param_decl_list2(p):
29332933
"""param_decl_list : param_decl_list COMMA param_definition"""
2934+
if p[1] is not None and p[3] is not None: # No errors in parsing
2935+
if p[3].default_value is None and p[1][-1].default_value is not None:
2936+
src.api.errmsg.syntax_error_mandatory_param_after_optional(p[3].lineno, p[1][-1].name, p[3].name)
2937+
29342938
p[0] = make_param_list(p[1], p[3])
29352939

29362940

@@ -2981,13 +2985,32 @@ def p_param_def_array(p):
29812985

29822986

29832987
def p_param_def_type(p):
2984-
"""param_def : singleid typedef"""
2988+
"""param_def : singleid typedef default_arg_value"""
29852989
id_: Id = p[1]
29862990
typedef = p[2]
29872991
if typedef is not None:
29882992
src.api.check.check_type_is_explicit(id_.lineno, id_.name, typedef)
29892993

2990-
p[0] = make_param_decl(id_.name, id_.lineno, typedef)
2994+
default_value = make_typecast(typedef, p[3], id_.lineno)
2995+
p[0] = make_param_decl(
2996+
id_.name,
2997+
id_.lineno,
2998+
typedef,
2999+
is_array=False,
3000+
default_value=default_value,
3001+
)
3002+
3003+
3004+
def p_param_def_default_arg_value(p):
3005+
"""default_arg_value :
3006+
| EQ expr
3007+
"""
3008+
if len(p) == 1:
3009+
p[0] = None
3010+
return
3011+
3012+
p[0] = p[2]
3013+
return
29913014

29923015

29933016
def p_function_body(p):
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
org 32768
2+
.core.__START_PROGRAM:
3+
di
4+
push ix
5+
push iy
6+
exx
7+
push hl
8+
exx
9+
ld hl, 0
10+
add hl, sp
11+
ld (.core.__CALL_BACK__), hl
12+
ei
13+
jp .core.__MAIN_PROGRAM__
14+
.core.__CALL_BACK__:
15+
DEFW 0
16+
.core.ZXBASIC_USER_DATA:
17+
; Defines USER DATA Length in bytes
18+
.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA
19+
.core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN
20+
.core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA
21+
.core.ZXBASIC_USER_DATA_END:
22+
.core.__MAIN_PROGRAM__:
23+
ld hl, 0
24+
push hl
25+
call _test
26+
ld hl, 0
27+
ld b, h
28+
ld c, l
29+
.core.__END_PROGRAM:
30+
di
31+
ld hl, (.core.__CALL_BACK__)
32+
ld sp, hl
33+
exx
34+
pop hl
35+
exx
36+
pop iy
37+
pop ix
38+
ei
39+
ret
40+
_test:
41+
push ix
42+
ld ix, 0
43+
add ix, sp
44+
_test__leave:
45+
ld sp, ix
46+
pop ix
47+
exx
48+
pop hl
49+
ex (sp), hl
50+
exx
51+
ret
52+
;; --- end of user code ---
53+
END

0 commit comments

Comments
 (0)