mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-11-24 15:32:27 +00:00
The evaluator doesn't add much and keeps falling behind; remove it.
This commit is contained in:
parent
20c824743e
commit
15072eff52
@ -8,6 +8,7 @@ History of SixtyPical
|
||||
* Initialized `byte table` values need not have all 256 bytes initialized.
|
||||
* Constraints for `vector` type come immediately after the type, not the variable.
|
||||
* `vector table` storage, and ability to copy vectors in and out of same.
|
||||
* Removed the evaluator. The reference implementation only analyzes and compiles.
|
||||
* Fixed bug where index register wasn't required to be initialized before table access.
|
||||
|
||||
0.10
|
||||
|
@ -21,8 +21,8 @@ based on common machine-language programming idioms, such as
|
||||
* explicit tail calls
|
||||
* indirect subroutine calls
|
||||
|
||||
The reference implementation can execute, analyze, and compile SixtyPical
|
||||
programs to 6502 machine code.
|
||||
The reference implementation can analyze and compile SixtyPical programs to
|
||||
6502 machine code.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
@ -45,8 +45,6 @@ Finish the little demo "game" where you can move a block around the screen with
|
||||
the joystick (i.e. bring it up to par with the original demo game that was written
|
||||
for SixtyPical)
|
||||
|
||||
### `vector table` type
|
||||
|
||||
### `low` and `high` address operators
|
||||
|
||||
To turn `word` type into `byte`.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
"""Usage: sixtypical [OPTIONS] FILES
|
||||
|
||||
Analyzes and/or executes and/or compiles a Sixtypical program.
|
||||
Analyzes and compiles a Sixtypical program.
|
||||
"""
|
||||
|
||||
from os.path import realpath, dirname, join
|
||||
@ -19,7 +19,6 @@ import sys
|
||||
import traceback
|
||||
|
||||
from sixtypical.parser import Parser
|
||||
from sixtypical.evaluator import Evaluator
|
||||
from sixtypical.analyzer import Analyzer
|
||||
from sixtypical.emitter import Emitter, Byte, Word
|
||||
from sixtypical.compiler import Compiler
|
||||
@ -43,9 +42,6 @@ if __name__ == '__main__':
|
||||
optparser.add_option("--traceback",
|
||||
action="store_true",
|
||||
help="")
|
||||
optparser.add_option("--execute",
|
||||
action="store_true",
|
||||
help="")
|
||||
|
||||
(options, args) = optparser.parse_args(sys.argv[1:])
|
||||
|
||||
@ -88,7 +84,3 @@ if __name__ == '__main__':
|
||||
pprint(emitter.accum)
|
||||
else:
|
||||
emitter.serialize(fh)
|
||||
|
||||
if options.execute:
|
||||
context = Evaluator().eval_program(program)
|
||||
print str(context)
|
||||
|
@ -2,8 +2,9 @@ SixtyPical
|
||||
==========
|
||||
|
||||
This document describes the SixtyPical programming language version 0.11,
|
||||
both its execution aspect and its static analysis aspect (even though
|
||||
these are, technically speaking, separate concepts.)
|
||||
both its static semantics (the capabilities and limits of the static
|
||||
analyses it defines) and its runtime semantics (with reference to the
|
||||
semantics of 6502 machine code.)
|
||||
|
||||
This document is nominally normative, but the tests in the `tests` directory
|
||||
are even more normative.
|
||||
|
@ -1,208 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
from sixtypical.ast import Program, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
ConstantRef, LocationRef, PartRef, IndirectRef,
|
||||
REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
|
||||
)
|
||||
|
||||
|
||||
class Context(object):
|
||||
def __init__(self):
|
||||
self._store = {}
|
||||
|
||||
def __str__(self):
|
||||
return '\n'.join("%s: %s" % (name, value)
|
||||
for (name, value) in sorted(self._store.iteritems())
|
||||
if not isinstance(value, Routine))
|
||||
|
||||
def get(self, ref):
|
||||
if isinstance(ref, ConstantRef):
|
||||
return ref.value
|
||||
elif isinstance(ref, LocationRef):
|
||||
return self._store[ref.name]
|
||||
elif isinstance(ref, PartRef):
|
||||
value = self.get(ref.ref)
|
||||
if ref.height == 0:
|
||||
return value & 255
|
||||
elif ref.height == 1:
|
||||
return (value >> 8) & 255
|
||||
else:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
raise ValueError(ref)
|
||||
|
||||
def set(self, ref, value):
|
||||
if isinstance(ref, PartRef):
|
||||
old = self.get(ref.ref)
|
||||
if ref.height == 0:
|
||||
value = (old & (255 << 8)) | value
|
||||
elif ref.height == 1:
|
||||
value = (value << 8) | (old & 255)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
ref = ref.ref
|
||||
assert isinstance(ref, LocationRef)
|
||||
self._store[ref.name] = value
|
||||
|
||||
|
||||
class Evaluator(object):
|
||||
|
||||
def eval_program(self, program):
|
||||
assert isinstance(program, Program)
|
||||
context = Context()
|
||||
for ref in (REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C):
|
||||
context.set(ref, 0)
|
||||
main = None
|
||||
|
||||
for defn in program.defns:
|
||||
if defn.initial is not None:
|
||||
context.set(defn.location, defn.initial)
|
||||
|
||||
for routine in program.routines:
|
||||
context.set(routine.location, routine)
|
||||
if routine.name == 'main':
|
||||
main = routine
|
||||
|
||||
self.eval_routine(main, context)
|
||||
return context
|
||||
|
||||
def eval_routine(self, routine, context):
|
||||
assert isinstance(routine, Routine)
|
||||
self.next_routine = routine
|
||||
while self.next_routine:
|
||||
routine = self.next_routine
|
||||
self.next_routine = None
|
||||
self.eval_block(routine.block, context)
|
||||
|
||||
def eval_block(self, block, context):
|
||||
assert isinstance(block, Block)
|
||||
for i in block.instrs:
|
||||
self.eval_instr(i, context)
|
||||
if self.next_routine:
|
||||
break
|
||||
|
||||
def eval_instr(self, instr, context):
|
||||
assert isinstance(instr, Instr)
|
||||
opcode = instr.opcode
|
||||
dest = instr.dest
|
||||
src = instr.src
|
||||
|
||||
if opcode == 'ld':
|
||||
result = context.get(src)
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'st':
|
||||
context.set(dest, context.get(src))
|
||||
elif opcode == 'add':
|
||||
carry = context.get(FLAG_C)
|
||||
val = context.get(src)
|
||||
now = context.get(dest)
|
||||
result = now + val + carry
|
||||
if result > 255:
|
||||
result &= 255
|
||||
context.set(FLAG_C, 1)
|
||||
else:
|
||||
context.set(FLAG_C, 0)
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'sub':
|
||||
carry = context.get(FLAG_C)
|
||||
val = context.get(src)
|
||||
now = context.get(dest)
|
||||
result = now - val - carry
|
||||
if result < 0:
|
||||
result &= 255
|
||||
context.set(FLAG_C, 1)
|
||||
else:
|
||||
context.set(FLAG_C, 0)
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'inc':
|
||||
val = context.get(dest)
|
||||
result = (val + 1) & 255
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'dec':
|
||||
val = context.get(dest)
|
||||
result = (val - 1) & 255
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'cmp':
|
||||
val = context.get(src)
|
||||
now = context.get(dest)
|
||||
result = now - val
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
if result < 0:
|
||||
result &= 255
|
||||
context.set(FLAG_C, 1)
|
||||
else:
|
||||
context.set(FLAG_C, 0)
|
||||
elif opcode == 'and':
|
||||
result = context.get(dest) & context.get(src)
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'or':
|
||||
result = context.get(dest) | context.get(src)
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'xor':
|
||||
result = context.get(dest) ^ context.get(src)
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'shl':
|
||||
val = context.get(dest)
|
||||
carry = context.get(FLAG_C)
|
||||
context.set(FLAG_C, 1 if val & 128 else 0)
|
||||
result = ((val << 1) + carry) & 255
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'shr':
|
||||
val = context.get(dest)
|
||||
carry = context.get(FLAG_C)
|
||||
context.set(FLAG_C, 1 if val & 1 else 0)
|
||||
result = (val >> 1) + (carry * 128)
|
||||
context.set(FLAG_Z, 1 if result == 0 else 0)
|
||||
context.set(FLAG_N, 1 if result & 128 else 0)
|
||||
context.set(dest, result)
|
||||
elif opcode == 'call':
|
||||
self.eval_routine(context.get(instr.location), context)
|
||||
elif opcode == 'goto':
|
||||
self.next_routine = context.get(instr.location)
|
||||
elif opcode == 'if':
|
||||
val = context.get(src)
|
||||
test = (val != 0) if not instr.inverted else (val == 0)
|
||||
if test:
|
||||
self.eval_block(instr.block1, context)
|
||||
elif instr.block2:
|
||||
self.eval_block(instr.block2, context)
|
||||
elif opcode == 'repeat':
|
||||
self.eval_block(instr.block, context)
|
||||
while context.get(src) == 0:
|
||||
self.eval_block(instr.block, context)
|
||||
elif opcode == 'copy':
|
||||
if isinstance(src, IndirectRef):
|
||||
raise NotImplementedError("this doesn't actually work")
|
||||
src = src.ref
|
||||
if isinstance(dest, IndirectRef):
|
||||
raise NotImplementedError("this doesn't actually work")
|
||||
dest = dest.ref
|
||||
context.set(dest, context.get(src))
|
||||
# these are trashed; so could be anything really
|
||||
context.set(REG_A, 0)
|
||||
context.set(FLAG_Z, 0)
|
||||
context.set(FLAG_N, 0)
|
||||
elif opcode == 'with-sei':
|
||||
self.eval_block(instr.block)
|
||||
else:
|
||||
raise NotImplementedError
|
1
test.sh
1
test.sh
@ -2,6 +2,5 @@
|
||||
|
||||
falderal --substring-error \
|
||||
tests/SixtyPical\ Syntax.md \
|
||||
tests/SixtyPical\ Execution.md \
|
||||
tests/SixtyPical\ Analysis.md \
|
||||
tests/SixtyPical\ Compilation.md
|
||||
|
@ -1,490 +0,0 @@
|
||||
SixtyPical Execution
|
||||
====================
|
||||
|
||||
This is a test suite, written in [Falderal][] format, for the dynamic
|
||||
execution behaviour of the Sixtypical language, disgregarding static analysis.
|
||||
|
||||
[Falderal]: http://catseye.tc/node/Falderal
|
||||
|
||||
-> Functionality "Execute SixtyPical program" is implemented by
|
||||
-> shell command "bin/sixtypical --execute %(test-body-file)"
|
||||
|
||||
-> Tests for functionality "Execute SixtyPical program"
|
||||
|
||||
Rudimentary program.
|
||||
|
||||
| routine main {
|
||||
| ld a, 0
|
||||
| add a, 1
|
||||
| }
|
||||
= a: 1
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Program accesses a memory location.
|
||||
|
||||
| byte lives
|
||||
|
|
||||
| routine main {
|
||||
| ld a, 0
|
||||
| st a, lives
|
||||
| ld x, lives
|
||||
| add x, 1
|
||||
| st x, lives
|
||||
| }
|
||||
= a: 0
|
||||
= c: 0
|
||||
= lives: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 1
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Program accesses a memory location with initial value.
|
||||
|
||||
| byte lives : 3
|
||||
|
|
||||
| routine main {
|
||||
| ld a, lives
|
||||
| }
|
||||
= a: 3
|
||||
= c: 0
|
||||
= lives: 3
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Add honours carry.
|
||||
|
||||
| routine main {
|
||||
| ld a, 255
|
||||
| st on, c
|
||||
| add a, 0
|
||||
| }
|
||||
= a: 0
|
||||
= c: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 1
|
||||
|
||||
| routine main {
|
||||
| ld a, $ff
|
||||
| st off, c
|
||||
| add a, 1
|
||||
| }
|
||||
= a: 0
|
||||
= c: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 1
|
||||
|
||||
Subtract honours carry.
|
||||
|
||||
| routine main {
|
||||
| ld a, 0
|
||||
| st on, c
|
||||
| sub a, 0
|
||||
| }
|
||||
= a: 255
|
||||
= c: 1
|
||||
= n: 1
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
| routine main {
|
||||
| ld a, 0
|
||||
| st off, c
|
||||
| sub a, 1
|
||||
| }
|
||||
= a: 255
|
||||
= c: 1
|
||||
= n: 1
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Inc and dec do not honour carry, but do set n and z.
|
||||
|
||||
| routine main {
|
||||
| ld x, 254
|
||||
| st on, c
|
||||
| inc x
|
||||
| }
|
||||
= a: 0
|
||||
= c: 1
|
||||
= n: 1
|
||||
= v: 0
|
||||
= x: 255
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
| routine main {
|
||||
| ld y, 1
|
||||
| st on, c
|
||||
| dec y
|
||||
| }
|
||||
= a: 0
|
||||
= c: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 1
|
||||
|
||||
Compare affects, but does not use, carry.
|
||||
|
||||
| routine main {
|
||||
| ld a, 1
|
||||
| st on, c
|
||||
| cmp a, 1
|
||||
| }
|
||||
= a: 1
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 1
|
||||
|
||||
| routine main {
|
||||
| ld a, 1
|
||||
| st off, c
|
||||
| cmp a, 5
|
||||
| }
|
||||
= a: 1
|
||||
= c: 1
|
||||
= n: 1
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
AND.
|
||||
|
||||
| routine main {
|
||||
| ld a, 15
|
||||
| and a, 18
|
||||
| }
|
||||
= a: 2
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
OR.
|
||||
|
||||
| routine main {
|
||||
| ld a, 34
|
||||
| or a, 18
|
||||
| }
|
||||
= a: 50
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
XOR.
|
||||
|
||||
| routine main {
|
||||
| ld a, 34
|
||||
| xor a, 18
|
||||
| }
|
||||
= a: 48
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Shift left.
|
||||
|
||||
| routine main {
|
||||
| ld a, 129
|
||||
| st off, c
|
||||
| shl a
|
||||
| }
|
||||
= a: 2
|
||||
= c: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
| routine main {
|
||||
| ld a, 0
|
||||
| st on, c
|
||||
| shl a
|
||||
| }
|
||||
= a: 1
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Shift right.
|
||||
|
||||
| routine main {
|
||||
| ld a, 129
|
||||
| st off, c
|
||||
| shr a
|
||||
| }
|
||||
= a: 64
|
||||
= c: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
| routine main {
|
||||
| ld a, 0
|
||||
| st on, c
|
||||
| shr a
|
||||
| }
|
||||
= a: 128
|
||||
= c: 0
|
||||
= n: 1
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Call routine.
|
||||
|
||||
| routine up {
|
||||
| inc x
|
||||
| inc y
|
||||
| }
|
||||
| routine main {
|
||||
| ld x, 0
|
||||
| ld y, 1
|
||||
| call up
|
||||
| call up
|
||||
| }
|
||||
= a: 0
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 2
|
||||
= y: 3
|
||||
= z: 0
|
||||
|
||||
If.
|
||||
|
||||
| routine main {
|
||||
| ld x, 40
|
||||
| cmp x, 40
|
||||
| if z {
|
||||
| ld a, 1
|
||||
| } else {
|
||||
| ld a, 8
|
||||
| }
|
||||
| ld x, 2
|
||||
| }
|
||||
= a: 1
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 2
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
| routine main {
|
||||
| ld x, 39
|
||||
| cmp x, 40
|
||||
| if z {
|
||||
| ld a, 1
|
||||
| } else {
|
||||
| ld a, 8
|
||||
| }
|
||||
| ld x, 2
|
||||
| }
|
||||
= a: 8
|
||||
= c: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 2
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
If without else.
|
||||
|
||||
| routine main {
|
||||
| ld x, 39
|
||||
| cmp x, 40
|
||||
| if z {
|
||||
| ld a, 1
|
||||
| }
|
||||
| ld x, 2
|
||||
| }
|
||||
= a: 0
|
||||
= c: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 2
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
`not` inverts the sense of the test.
|
||||
|
||||
| routine main {
|
||||
| ld x, 40
|
||||
| cmp x, 40
|
||||
| if not z {
|
||||
| ld a, 1
|
||||
| } else {
|
||||
| ld a, 8
|
||||
| }
|
||||
| ld x, 2
|
||||
| }
|
||||
= a: 8
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 2
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
| routine main {
|
||||
| ld x, 39
|
||||
| cmp x, 40
|
||||
| if not z {
|
||||
| ld a, 1
|
||||
| }
|
||||
| ld x, 2
|
||||
| }
|
||||
= a: 1
|
||||
= c: 1
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 2
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Repeat loop.
|
||||
|
||||
| routine main {
|
||||
| ld x, 0
|
||||
| ld y, 15
|
||||
| repeat {
|
||||
| inc x
|
||||
| inc y
|
||||
| cmp x, 10
|
||||
| } until z
|
||||
| }
|
||||
= a: 0
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 10
|
||||
= y: 25
|
||||
= z: 1
|
||||
|
||||
Copy instruction. Note that the state of a, z, and n are not defined
|
||||
after copy executes.
|
||||
|
||||
| routine main {
|
||||
| ld x, 5
|
||||
| copy x, y
|
||||
| }
|
||||
= a: 0
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 5
|
||||
= y: 5
|
||||
= z: 0
|
||||
|
||||
Copy word to word.
|
||||
|
||||
| word foo : 2000
|
||||
| word bar
|
||||
|
|
||||
| routine main {
|
||||
| copy foo, bar
|
||||
| }
|
||||
= a: 0
|
||||
= bar: 2000
|
||||
= c: 0
|
||||
= foo: 2000
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Copy literal word to word.
|
||||
|
||||
| word bar
|
||||
|
|
||||
| routine main {
|
||||
| copy word 2000, bar
|
||||
| }
|
||||
= a: 0
|
||||
= bar: 2000
|
||||
= c: 0
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Indirect call.
|
||||
|
||||
| vector foo outputs x trashes z, n
|
||||
|
|
||||
| routine bar outputs x trashes z, n {
|
||||
| ld x, 200
|
||||
| }
|
||||
|
|
||||
| routine main inputs bar outputs x, foo trashes a, z, n {
|
||||
| copy bar, foo
|
||||
| call foo
|
||||
| }
|
||||
= a: 0
|
||||
= c: 0
|
||||
= n: 1
|
||||
= v: 0
|
||||
= x: 200
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
goto.
|
||||
|
||||
| routine bar outputs x trashes z, n {
|
||||
| ld x, 200
|
||||
| }
|
||||
|
|
||||
| routine main outputs x trashes a, z, n {
|
||||
| ld y, 200
|
||||
| goto bar
|
||||
| }
|
||||
= a: 0
|
||||
= c: 0
|
||||
= n: 1
|
||||
= v: 0
|
||||
= x: 200
|
||||
= y: 200
|
||||
= z: 0
|
Loading…
Reference in New Issue
Block a user