04 - Stack Machines (Implementation)

The preliminary requirements for this assignment:
1. Git installed (see Dev > Git),
2. Python installed (see Dev > Python),
3. The template forked (see Dev > template),
4. The third assignment handed in (see Assignment 3 - Stack Machines (Theory)).

In this assignment you’ll have to implement a simple stack machine (non-real-world) that can perform basic arithmetic operations. The implementation has to be in Python using the template provided in ./robolab-template/src/stack_machine.py. Again, you will implement and run the program on your computer.

Read about the specification of our stack machine here: Specification.

Deadline for submission: Sunday, December 13th 2020, 23:59 // 11:59 pm
Please upload your solution into your own Gitlab repository using the prepared files.

Task 1

Implement the function top() in ./src/stack_machine.py:

  1. Implement or define a LIFO stack that holds unsigned 8-bit integers and characters.

  2. Add the missing logic to the function top() returning the top element if there is any, or None.
    Take into account that the items on the stack probably needs to be converted into a tuple beforehand.

Task 2

Implement the function do() in ./src/stack_machine.py:

  1. Define a representation for stack machine instructions and characters, e.g. using Enums classes.

  2. Add the missing logic for processing a 6-bit word (a Tuple).
    Handle the input parameter according to the specification.

    1. If the word is an operand or a character, push it to the stack.

    2. If the word is an instruction or a string operation (e.g. SPEAK), pop the operands needed from the stack and execute the instruction.
      Don’t forget to push the result back to the stack.

  3. Check for an overflow if required and set the overflow flag according to our specification.

    Stop the execution if there are not enough operands or there was an illegal instruction, e.g. division by 0.
    Implement all instructions from our specification.

You can move the logic for the instructions into another method, e.g. execute, in order to keep your code clean and readable.

Task 3

Now we are looking into unit-tests again and update the file ./src/test.py.

  1. First, import everything from stack_machine.py.

  2. Implement the instance test case for StackMachine as you did for HammingCode.

  3. Create a test case prototype for the function do() and add a check for the final result on the stack.
    Use asserts and pre-defined expectations (e.g. simple variable holding the value) for the check.

  4. Write a test case for the function top(). Make sure that the value returned matches our definition (8-bit tuple).

Task 4

In your file ./src/test.py, we will implement the prototyped test case for do().

  1. Implement and execute the following sequence (taken from assignment 3 and extended):

    • \[ \begin{matrix} 001010 \\ 010001 \\ 010001 \\ 010110 \\ 011111 \\ 000100 \\ 011011 \\ 000100 \\ 011001 \\ 000110 \\ 011000 \\ 100010 \\ 110110 \\ 101000 \\ 110101 \\ 000101 \\ 100001 \\ 010000 \end{matrix} \]

    • For the SPEAK instruction, we only print the output instead of using TTS in this assignment.

  2. What happens if there was a division by 0 or if there were not enough operands on the stack?
    Cover the correct error handling also with unit-tests.

Task 5 (bonus, not graded)

Provide a test case for every instruction listed in our specification.
To simplify your test cases you can outsource the object creation into a setUp function:

def setUp(self):
    self.sm = StackMachine()

Do not exchange source code with members of other groups! Keep it private!
We we do not tolerate plagiarism.
Plagiarism of any form will get you disqualified from the lab.