1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-11-29 03:51:35 +00:00

Forward-reference resolution becomes increasingly general.

This commit is contained in:
Chris Pressey 2018-09-07 13:40:41 +01:00
parent 26a2fb448c
commit af0e1b41c7
5 changed files with 37 additions and 34 deletions

View File

@ -5,6 +5,8 @@ History of SixtyPical
---- ----
* `save X, Y, Z { }` now allowed as a shortcut for nested `save`s. * `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. * Split TODO off into own file.
* `sixtypical` no longer writes the compiled binary to standard * `sixtypical` no longer writes the compiled binary to standard
output. The `--output` command-line argument should be given output. The `--output` command-line argument should be given

View File

@ -550,6 +550,8 @@ class Analyzer(object):
context.invalidate_range(dest) context.invalidate_range(dest)
elif opcode == 'call': elif opcode == 'call':
type = instr.location.type type = instr.location.type
if not isinstance(type, (RoutineType, VectorType)):
raise TypeMismatchError(instr, instr.location)
if isinstance(type, VectorType): if isinstance(type, VectorType):
type = type.of_type type = type.of_type
for ref in type.inputs: for ref in type.inputs:

View File

@ -115,16 +115,11 @@ class Parser(object):
for node in program.all_children(): for node in program.all_children():
if isinstance(node, SingleOp): if isinstance(node, SingleOp):
instr = node instr = node
if isinstance(instr.src, ForwardReference):
instr.src = self.lookup(instr.src.name)
if instr.opcode in ('call', 'goto'): if instr.opcode in ('call', 'goto'):
forward_reference = instr.location if isinstance(instr.location, ForwardReference):
name = forward_reference.name instr.location = self.lookup(instr.location.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)
return program return program

View File

@ -196,6 +196,35 @@ If a routine reads or writes a user-define memory location, it needs to declare
| } | }
= ok = 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 ### ### ld ###
Can't `ld` from a memory location that isn't initialized. Can't `ld` from a memory location that isn't initialized.

View File

@ -404,24 +404,6 @@ Can't call routine that hasn't been defined.
| } | }
? SyntaxError ? 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. But you can call a routine that is yet to be defined, further on.
| routine main { | routine main {
@ -589,13 +571,6 @@ goto.
| } | }
? SyntaxError ? SyntaxError
| byte foo
|
| routine main {
| goto foo
| }
? SyntaxError
Buffers and pointers. Buffers and pointers.
| buffer[2048] buf | buffer[2048] buf