diff --git a/doc/SixtyPical.md b/doc/SixtyPical.md index 5e6fd8b..7eaddc5 100644 --- a/doc/SixtyPical.md +++ b/doc/SixtyPical.md @@ -334,8 +334,8 @@ To simulate a "while" loop, use an `if` internal to the block, like copy , Reads from src and writes to dest. Differs from `st` in that is able to -copy more general types of data (for example, vectors,) and it sets the -`z` and `n` flags and trashes the `a` register. +copy more general types of data (for example, vectors,) and it trashes the +`z` and `n` flags and the `a` register. * It is illegal if dest is read-only. * It is illegal if dest does not occur in the WRITES lists of the current @@ -343,8 +343,8 @@ copy more general types of data (for example, vectors,) and it sets the * It is illegal if src is not of same type as dest. * It is illegal if src is uninitialized. -After execution, dest is considered initialized, as are `z` and `n`, while -`a` is considered uninitialized. +After execution, dest is considered initialized, and `z` and `n`, and +`a` are considered uninitialized. Grammar ------- diff --git a/src/sixtypical/analyzer.py b/src/sixtypical/analyzer.py index 9ab4053..d615ca5 100644 --- a/src/sixtypical/analyzer.py +++ b/src/sixtypical/analyzer.py @@ -2,8 +2,9 @@ from sixtypical.ast import Program, Routine, Block, Instr from sixtypical.model import ( - TYPE_BYTE, TYPE_BYTE_TABLE, - ConstantRef, LocationRef, FLAG_Z, FLAG_N, FLAG_V, FLAG_C + TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_ROUTINE, TYPE_VECTOR, + ConstantRef, LocationRef, + REG_A, FLAG_Z, FLAG_N, FLAG_V, FLAG_C ) @@ -214,5 +215,16 @@ def analyze_instr(instr, context, routines): analyze_block(instr.block, context, routines) # NB I *think* that's enough... but it might not be? + elif opcode == 'copy': + if src.type == dest.type: + pass + elif src.type == TYPE_ROUTINE and dest.type == TYPE_VECTOR: + pass + else: + raise TypeMismatchError((src, dest)) + context.assert_initialized(src) + context.assert_writeable(dest) + context.set_initialized(dest) + context.set_uninitialized(REG_A, FLAG_Z, FLAG_N) else: raise NotImplementedError(opcode) diff --git a/src/sixtypical/evaluator.py b/src/sixtypical/evaluator.py index 2c9fbb4..e69bbaf 100644 --- a/src/sixtypical/evaluator.py +++ b/src/sixtypical/evaluator.py @@ -154,5 +154,11 @@ def eval_instr(instr, context, routines): eval_block(instr.block, context, routines) while context.get(src) == 0: eval_block(instr.block, context, routines) + elif opcode == 'copy': + 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) else: raise NotImplementedError diff --git a/tests/SixtyPical Analysis.md b/tests/SixtyPical Analysis.md index fcc84fb..e0b9db0 100644 --- a/tests/SixtyPical Analysis.md +++ b/tests/SixtyPical Analysis.md @@ -965,3 +965,74 @@ initialized at the start. | } until z | } ? UninitializedAccessError: y + +### copy ### + +Can't `copy` from a memory location that isn't initialized. + + | byte lives + | routine main + | inputs x + | outputs lives + | trashes a, z, n + | { + | copy x, lives + | } + = ok + + | byte lives + | routine main + | outputs lives + | trashes x, a, z, n + | { + | copy x, lives + | } + ? UninitializedAccessError: x + +Can't `st` to a memory location that doesn't appear in (outputs ∪ trashes). + + | byte lives + | routine main + | trashes lives, a, z, n + | { + | copy 0, lives + | } + = ok + + | byte lives + | routine main + | outputs lives + | trashes a, z, n + | { + | copy 0, lives + | } + = ok + + | byte lives + | routine main + | inputs lives + | trashes a, z, n + | { + | copy 0, lives + | } + ? IllegalWriteError: lives + +a, z, and n are trashed, and must be declared as such + + | byte lives + | routine main + | outputs lives + | { + | copy 0, lives + | } + ? IllegalWriteError: a + +a, z, and n are trashed, and must not be declared as outputs. + + | byte lives + | routine main + | outputs lives, a, z, n + | { + | copy 0, lives + | } + ? UninitializedOutputError: a diff --git a/tests/SixtyPical Execution.md b/tests/SixtyPical Execution.md index 421776e..9570d63 100644 --- a/tests/SixtyPical Execution.md +++ b/tests/SixtyPical Execution.md @@ -385,3 +385,18 @@ Repeat loop. = 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