Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions src/api/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def check_type_is_explicit(lineno: int, id_: str, type_):
errmsg.syntax_error_undeclared_type(lineno, id_)


def check_call_arguments(lineno: int, id_: str, args):
def check_call_arguments(lineno: int, id_: str, args, filename: str):
"""Check arguments against function signature.

Checks every argument in a function call against a function.
Expand All @@ -109,14 +109,14 @@ def check_call_arguments(lineno: int, id_: str, args):
param_names = {x.name for x in entry.ref.params}
for arg in args:
if arg.name is not None and arg.name not in param_names:
errmsg.error(lineno, f"Unexpected argument '{arg.name}'", fname=entry.filename)
errmsg.error(lineno, f"Unexpected argument '{arg.name}'", fname=filename)
return False

last_arg_name = None
for arg, param in zip(args, entry.ref.params):
if last_arg_name is not None and arg.name is None:
errmsg.error(
lineno, f"Positional argument cannot go after keyword argument '{last_arg_name}'", fname=entry.filename
lineno, f"Positional argument cannot go after keyword argument '{last_arg_name}'", fname=filename
)
return False

Expand All @@ -139,15 +139,13 @@ def check_call_arguments(lineno: int, id_: str, args):

for arg in args:
if arg.name is None:
errmsg.error(lineno, f"Too many arguments for Function '{id_}'", fname=entry.filename)
errmsg.error(lineno, f"Too many arguments for Function '{id_}'", fname=filename)
return False

if len(named_args) != len(entry.ref.params):
c = "s" if len(entry.ref.params) != 1 else ""
errmsg.error(
lineno,
f"Function '{id_}' takes {len(entry.ref.params)} parameter{c}, not {len(args)}",
fname=entry.filename,
lineno, f"Function '{id_}' takes {len(entry.ref.params)} parameter{c}, not {len(args)}", fname=filename
)
return False

Expand Down Expand Up @@ -195,8 +193,8 @@ def check_pending_calls():
result = True

# Check for functions defined after calls (parameters, etc)
for id_, params, lineno in global_.FUNCTION_CALLS:
result = result and check_call_arguments(lineno, id_, params)
for call in global_.FUNCTION_CALLS:
result = result and check_call_arguments(call.lineno, call.entry.original_name, call.args, call.filename)

return result

Expand Down
3 changes: 2 additions & 1 deletion src/api/global_.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from src.api.opcodestemps import OpcodesTemps

if TYPE_CHECKING:
from src.symbols.call import SymbolCALL
from src.symbols.id_ import SymbolID


Expand Down Expand Up @@ -90,7 +91,7 @@ class LoopInfo(NamedTuple):
# Function calls pending to check
# Each scope pushes (prepends) an empty list
# ----------------------------------------------------------------------
FUNCTION_CALLS: list[SymbolID] = []
FUNCTION_CALLS: list[SymbolCALL] = []

# ----------------------------------------------------------------------
# Function level entry ID in which scope we are in. If the list
Expand Down
16 changes: 6 additions & 10 deletions src/symbols/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ def __init__(self, entry: SymbolID, arglist: Iterable[SymbolARGUMENT], lineno: i
super().__init__()
self.entry = entry
self.args = arglist # Func. call / array access
self.lineno = lineno
self.filename = filename
self.lineno: int = lineno
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bartsanchez Apparently this is needed to avoid a [has-type] mypy error??

self.filename: str = filename

ref = entry.ref
if isinstance(ref, FuncRef):
Expand Down Expand Up @@ -95,17 +95,13 @@ def make_node(cls, id_: str, params, lineno: int, filename: str) -> Optional["Sy
return None

if entry.declared and not entry.forwarded:
check.check_call_arguments(lineno, id_, params)
check.check_call_arguments(lineno, id_, params, filename)
else: # All functions goes to global scope by default
if entry.token != "FUNCTION":
entry = entry.to_function(lineno)
gl.SYMBOL_TABLE.move_to_global_scope(id_)
gl.FUNCTION_CALLS.append(
(
id_,
params,
lineno,
)
)
result = cls(entry, params, lineno, filename)
gl.FUNCTION_CALLS.append(result)
return result

return cls(entry, params, lineno, filename)
4 changes: 3 additions & 1 deletion src/symbols/id_/_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class SymbolID(SymbolIdABC):

__slots__ = (
"name",
"original_name",
"filename",
"lineno",
"mangled",
Expand All @@ -58,7 +59,8 @@ def __init__(
super().__init__(name=name, lineno=lineno, filename=filename, type_=type_, class_=class_)
assert class_ in (CLASS.const, CLASS.label, CLASS.var, CLASS.unknown)

self.name = name
self.name = name # This value will be modified later removing the trailing sigil ($) if used.
self.original_name = name # This value will always contain the original name, preserving the sigil if used
self.filename = global_.FILENAME if filename is None else filename # In which file was first used
self.lineno = lineno # In which line was first used
self.mangled = f"{global_.MANGLE_CHR}{name}" # This value will be overridden later
Expand Down
10 changes: 10 additions & 0 deletions tests/functional/arch/zx48k/bad_fname_err5.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#line 1 "file2.bas"
#line 1 "file1.bas"
sub foo(a as ubyte, b as ubyte)
print a, ", ", b
end sub

#line 2 "file2.bas"


foo(42)
10 changes: 10 additions & 0 deletions tests/functional/arch/zx48k/bad_fname_err6.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#line 1 "file2.bas"
#line 1 "file1.bas"
sub foo(a as ubyte, b as ubyte)
print a, ", ", b
end sub

#line 2 "file2.bas"


foo(42, 43, 44)
4 changes: 4 additions & 0 deletions tests/functional/cmdline/test_errmsg.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ ND.Controls.bas:4: error: Invalid argument 'dirData'
ND.Controls.bas:2: warning: [W150] Variable 'dirData' is never used
>>> process_file('arch/zx48k/bad_fname_err4.bas', ['-S', '-q'])
ND.Controls.bas:2: error: sub 'Controls_LABEL' declared but not implemented
>>> process_file('arch/zx48k/bad_fname_err5.bas', ['-S', '-q'])
file2.bas:4: error: Function 'foo' takes 2 parameters, not 1
>>> process_file('arch/zx48k/bad_fname_err6.bas', ['-S', '-q'])
file2.bas:4: error: Too many arguments for Function 'foo'

# DO LOOP type errors
>>> process_file('arch/zx48k/do_crash.bas', ['-S', '-q'])
Expand Down
Loading