diff --git a/HISTORY.md b/HISTORY.md index 7d7b22f..aea6685 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,6 +5,8 @@ History of SixtyPical ---- * `save X, Y, Z { }` now allowed as a shortcut for nested `save`s. +* Trying to call or goto a non-routine-typed symbol is now an + analysis error, not a syntax error. * Split TODO off into own file. * `sixtypical` no longer writes the compiled binary to standard output. The `--output` command-line argument should be given diff --git a/src/sixtypical/analyzer.py b/src/sixtypical/analyzer.py index 1e69965..98959e1 100644 --- a/src/sixtypical/analyzer.py +++ b/src/sixtypical/analyzer.py @@ -550,6 +550,8 @@ class Analyzer(object): context.invalidate_range(dest) elif opcode == 'call': type = instr.location.type + if not isinstance(type, (RoutineType, VectorType)): + raise TypeMismatchError(instr, instr.location) if isinstance(type, VectorType): type = type.of_type for ref in type.inputs: diff --git a/src/sixtypical/parser.py b/src/sixtypical/parser.py index 9da1c4f..84dc753 100644 --- a/src/sixtypical/parser.py +++ b/src/sixtypical/parser.py @@ -115,16 +115,11 @@ class Parser(object): for node in program.all_children(): if isinstance(node, SingleOp): instr = node + if isinstance(instr.src, ForwardReference): + instr.src = self.lookup(instr.src.name) if instr.opcode in ('call', 'goto'): - forward_reference = instr.location - name = forward_reference.name - model = self.lookup(name) - if not isinstance(model.type, (RoutineType, VectorType)): - self.syntax_error('Illegal call of non-executable "%s"' % name) - instr.location = model - if instr.opcode in ('copy',): - if isinstance(instr.src, ForwardReference): - instr.src = self.lookup(instr.src.name) + if isinstance(instr.location, ForwardReference): + instr.location = self.lookup(instr.location.name) return program diff --git a/tests/SixtyPical Analysis.md b/tests/SixtyPical Analysis.md index 0caecc8..2e06530 100644 --- a/tests/SixtyPical Analysis.md +++ b/tests/SixtyPical Analysis.md @@ -196,6 +196,35 @@ If a routine reads or writes a user-define memory location, it needs to declare | } = ok +### call ### + +You can't call a non-routine. + + | byte up + | + | routine main outputs x, y trashes z, n { + | ld x, 0 + | ld y, 1 + | call up + | } + ? TypeMismatchError: up + + | routine main outputs x, y trashes z, n { + | ld x, 0 + | ld y, 1 + | call x + | } + ? TypeMismatchError: x + +Nor can you goto a non-routine. + + | byte foo + | + | routine main { + | goto foo + | } + ? TypeMismatchError: foo + ### ld ### Can't `ld` from a memory location that isn't initialized. diff --git a/tests/SixtyPical Syntax.md b/tests/SixtyPical Syntax.md index e2ef953..1aa9a9c 100644 --- a/tests/SixtyPical Syntax.md +++ b/tests/SixtyPical Syntax.md @@ -404,24 +404,6 @@ Can't call routine that hasn't been defined. | } ? SyntaxError -And you can't call a non-routine. - - | byte up - | - | routine main { - | ld x, 0 - | ld y, 1 - | call up - | } - ? SyntaxError - - | routine main { - | ld x, 0 - | ld y, 1 - | call x - | } - ? SyntaxError - But you can call a routine that is yet to be defined, further on. | routine main { @@ -589,13 +571,6 @@ goto. | } ? SyntaxError - | byte foo - | - | routine main { - | goto foo - | } - ? SyntaxError - Buffers and pointers. | buffer[2048] buf