v00.00.03

With this version we get two more types in our machine: signed
32bits integers and booleans.

The changes are really minimal, but this is just a small step in
preparing the machine to start handling some real computation soon.

After this, we have:
1) a representation for 32bit (fixnum) signed integers;
2) a representation for boolean values;
Reorganizing test suites.
Beginning v00.00.04 iteration.
Representation for instructions, with opcodes encoders and decoders for global-ref, global-set and return
Added code segment to modules.
Representation for user defined functions.
Evaluator now has a viable setup for preparing the execution of procedures.
Execution behaviour of the two instructions: global-ref and global-set
v00.00.04

This version creates support for our first interpreted pieces of
code: user-defined procedures. So far we have very few instructions
and the machine still won't be able to perform any useful
computation, but it creates the foundations for our real programs.

An interpreted procedure (from now on referred simply as a
procedure) is composed of a reference to the module in which it is
defined, an entry point index that points to what instruction in the
module is the first instruction of the procedure and the number of
local registers.

For now, our procedures receive no arguments (they'll only be called
from within the process of running a full module) and they return a
single result only.

The evaluator starts resembling a real machine: for the procedures
to work it needs an internal counter for the current instruction
(code pointer), a set of local registers (created upon execution of
the procedure) and a list of instructions that belong to the module.

Since we only have the possibility of calling a single procedure,
the evaluator stops executing as soon as it executes a return
instruction. The execution loop for the machine is as follows:
  1) fetch the instruction (from the current module) at the index
     pointed by the code pointer;
  2) execute the instruction fetched in step (1);
  3) calculate the change needed to be made on code pointer;
  4) update code pointer;
  5) go back to step (1);

This loop ends when the instruction executed in step (2) is a return
instruction: in that case, the evaluator copies the value received
by the return instruction as its result and stop executing.

The following instructions are implemented:
  1) global-ref: it takes the index of a local and of a global, then
                 copies the current value in the global to the
                 local.
  2) global-set: it takes the index of a global and of a local, then
                 copies the current value in the local to the
                 global.
  3) return: it takes the index of a local where it will find the
             value it is supposed to return to the evaluator. After
             the execution of return the evaluator must stop the
             fetch-run loop.

The encoding for instructions is (for now) fixed-size, using 32bits
to encode each instruction: 8 bits for the opcode and the remaining
24bits encode its arguments.

th this we're able to write simple, albeit useless, program: read
two global registers G1 and G2 and swap the values in those
registers among themselves, so that G1 has the previous G2 value and
G2 has the previous G1 value.

This adds the following elements to our previous machine:
  1) modules now have a code segment that holds instructions;
  2) a representation for instructions on the virtual machine;
  3) a representation and object type for procedures;
  4) the "fetch-run loop" of the evaluator;
  5) three instructions for the evaluator (global-ref, global-set
     and return);