1. Overview A compiled sieve program consists of a sequence of cells. Each cell is a pointer to sieve_op_t data, i.e. it points to an instruction handler (sieve_instr_t type) or to a memory location containing sieve_value_t structure. The exact interpretation of this pointer depends on the value of program counter. The very first entry in a sieve program (pc = 0) is always a NULL pointer. The next entry (pc = 1) is always expected to contain a valid instruction handler. When executing a program, the sieve runtime evaluator starts from pc = 1. It reads the cell contents, interprets it as address of an instruction handler, increments the program counter and executes the handler. The evaluator stops executing the program when it encounters a NULL pointer. When invoked, an instruction handler receives a single argument: a pointer to the sieve_machine_t structure, describing current runtime environment. If the handler needs any surplus arguments, it is its responsibility to retrieve them from the program cells immediately following the handler address and increment the pc value accordingly. 2. Existing handlers 2.1. Push Name: instr_push Arguments: None Pushes current numeric register on stack. 2.2. Pop Name: instr_pop Arguments: None Pops the top of stack value into the numeric register. 2.3. Unconditional branch Name: instr_branch Arguments: [pc ] (number) Offset of the new cell. 2.4. Branch if zero Name: instr_brz Arguments: [pc ] (number) Offset of the new cell. 2.5. Logical NOT Name: instr_not Arguments: none 2.6. Logical AND Name: instr_allof Arguments: [pc ] (number) Number of items to be popped from stack 2.7. Logical OR Name: instr_anyof Arguments: [pc ] (number) Number of items to be popped from stack 2.8. Action handler Name: instr_action Arguments: [pc ] (sieve_handler_t*) Pointer to the action handling function. [pc+1] (list_t of sieve_value_t) A list of required arguments. [pc+2] (list_t of sieve_runtime_tag_t) A list of tags. [pc+3] (string) Name of the action (for debugging purposes). 2.9. Test handler Name: instr_test Arguments: [pc ] (sieve_handler_t*) Pointer to the test handling function. [pc+1] (list_t of sieve_value_t) A list of required arguments. [pc+2] (list_t of sieve_runtime_tag_t) A list of tags. [pc+3] (string) Name of the test (for debugging purposes). 3. Conditional statement branching A simple statement IF cond list1 ELSE list2 is translated into the following program # Compute the condition . . . brz L_ELSE # Evaluate list1 . . . br L_END L_ELSE: # Evaluate list2 . . . L_END: A more complex statement in the form: IF cond1 list1 ELSIF cond2 list2 ELSE list3 is translated into the following program # Compute the condition 1 . . . brz L_ELSIF # Evaluate list1 . . . br L_END L_ELSIF: # Compute the condition 2 . . . brz L_ELSE # Evaluate list 2 . . . br L_END L_ELSE: # Evaluate list 3 . . . L_END: Generally speaking, each ELSIF branch generates a code, similar to usual IF ... ELSE sequence.