1 |
|
|
2 |
1. Overview |
* Overview |
3 |
|
|
4 |
A compiled sieve program consists of a sequence of cells. Each cell |
A compiled sieve program consists of a sequence of cells. Each cell |
5 |
is a pointer to sieve_op_t data, i.e. it points to an instruction handler |
is a pointer to sieve_op_t data, i.e. it points to an instruction handler |
13 |
increments the program counter and executes the handler. The evaluator |
increments the program counter and executes the handler. The evaluator |
14 |
stops executing the program when it encounters a NULL pointer. |
stops executing the program when it encounters a NULL pointer. |
15 |
|
|
16 |
When invoked, an instruction handler receives a single argument: a pointer |
When invoked, the instruction handler receives a single argument: a pointer |
17 |
to the sieve_machine_t structure, describing current runtime environment. |
to the sieve_machine_t structure, describing current runtime environment. |
18 |
If the handler needs any surplus arguments, it is its responsibility |
If the handler needs any surplus arguments, it is its responsibility |
19 |
to retrieve them from the program cells immediately following the |
to retrieve them from the program cells immediately following the |
20 |
handler address and increment the pc value accordingly. |
handler address and increment the pc value accordingly. |
21 |
|
|
22 |
2. Existing handlers |
* Existing handlers |
23 |
|
|
24 |
2.1. Push |
** Nop |
25 |
|
|
26 |
|
Name: instr_nop |
27 |
|
Arguments: None |
28 |
|
|
29 |
|
Does nothing |
30 |
|
|
31 |
|
** Push |
32 |
|
|
33 |
Name: instr_push |
Name: instr_push |
34 |
Arguments: None |
Arguments: None |
35 |
|
|
36 |
Pushes current numeric register on stack. |
Pushes current numeric register on stack. |
37 |
|
|
38 |
2.2. Pop |
** Pop |
39 |
|
|
40 |
Name: instr_pop |
Name: instr_pop |
41 |
Arguments: None |
Arguments: None |
42 |
|
|
43 |
Pops the top of stack value into the numeric register. |
Pops the top of stack value into the numeric register. |
44 |
|
|
45 |
2.3. Unconditional branch |
** Unconditional branch |
46 |
|
|
47 |
Name: instr_branch |
Name: instr_branch |
48 |
Arguments: [pc ] (number) Offset of the new cell. |
Arguments: [pc ] (number) Offset of the new cell. |
49 |
|
|
50 |
2.4. Branch if zero |
** Branch if zero |
51 |
|
|
52 |
Name: instr_brz |
Name: instr_brz |
53 |
Arguments: [pc ] (number) Offset of the new cell. |
Arguments: [pc ] (number) Offset of the new cell. |
54 |
|
|
55 |
2.5. Logical NOT |
** Branch if not zero |
56 |
|
|
57 |
|
Name: instr_brnz |
58 |
|
Arguments: [pc ] (number) Offset of the new cell. |
59 |
|
|
60 |
|
** Logical NOT |
61 |
|
|
62 |
Name: instr_not |
Name: instr_not |
63 |
Arguments: none |
Arguments: none |
64 |
|
|
65 |
2.6. Logical AND |
** Logical AND |
66 |
|
|
67 |
Name: instr_allof |
Name: instr_allof |
68 |
Arguments: [pc ] (number) Number of items to be popped from stack |
Arguments: [pc ] (number) Number of items to be popped from stack |
69 |
|
|
70 |
|
|
71 |
2.7. Logical OR |
** Logical OR |
72 |
|
|
73 |
Name: instr_anyof |
Name: instr_anyof |
74 |
Arguments: [pc ] (number) Number of items to be popped from stack |
Arguments: [pc ] (number) Number of items to be popped from stack |
75 |
|
|
76 |
2.8. Action handler |
** Action handler |
77 |
|
|
78 |
Name: instr_action |
Name: instr_action |
79 |
Arguments: [pc ] (sieve_handler_t*) Pointer to the action handling function. |
Arguments: [pc ] (sieve_handler_t*) Pointer to the action handling function. |
81 |
[pc+2] (list_t of sieve_runtime_tag_t) A list of tags. |
[pc+2] (list_t of sieve_runtime_tag_t) A list of tags. |
82 |
[pc+3] (string) Name of the action (for debugging purposes). |
[pc+3] (string) Name of the action (for debugging purposes). |
83 |
|
|
84 |
2.9. Test handler |
** Test handler |
85 |
|
|
86 |
Name: instr_test |
Name: instr_test |
87 |
Arguments: [pc ] (sieve_handler_t*) Pointer to the test handling function. |
Arguments: [pc ] (sieve_handler_t*) Pointer to the test handling function. |
89 |
[pc+2] (list_t of sieve_runtime_tag_t) A list of tags. |
[pc+2] (list_t of sieve_runtime_tag_t) A list of tags. |
90 |
[pc+3] (string) Name of the test (for debugging purposes). |
[pc+3] (string) Name of the test (for debugging purposes). |
91 |
|
|
92 |
3. Conditional statement branching |
* Conditional statement branching |
93 |
|
|
94 |
A simple statement |
A simple statement |
95 |
|
|
149 |
L_END: |
L_END: |
150 |
|
|
151 |
Generally speaking, each ELSIF branch generates a code, similar to usual |
Generally speaking, each ELSIF branch generates a code, similar to usual |
|
IF ... ELSE sequence. |
|
152 |
|
IF ... ELSE sequence. |
153 |
|
|
154 |
|
* Boolean shortcuts |
155 |
|
|
156 |
|
Boolean shortcuts are implemented for coding ALLOF and ANYOF conditions. |
157 |
|
The code these produce is shown in the next two subsections. Notice the |
158 |
|
insertion of the two Nop statement after the last condition. These replace |
159 |
|
the two slots used by the Brz or Brnz instruction, which would be useless, |
160 |
|
since the next statement after ALLOF or ANYOF is guaranteed to be a branch |
161 |
|
statement. This replacement speeds up the execution a little. |
162 |
|
|
163 |
|
** ALLOF |
164 |
|
|
165 |
|
ALLOF(cond1,cond2,cond3) |
166 |
|
|
167 |
|
# Evaluate cond1 |
168 |
|
. |
169 |
|
. |
170 |
|
. |
171 |
|
brz L_end |
172 |
|
# Evaluate cond2 |
173 |
|
. |
174 |
|
. |
175 |
|
. |
176 |
|
brz L_end |
177 |
|
# Evaluate cond3 |
178 |
|
. |
179 |
|
. |
180 |
|
. |
181 |
|
nop |
182 |
|
nop |
183 |
|
L_end: |
184 |
|
. |
185 |
|
|
186 |
|
** ANYOF |
187 |
|
|
188 |
|
ALLOF(cond1,cond2,cond3) |
189 |
|
|
190 |
|
# Evaluate cond1 |
191 |
|
. |
192 |
|
. |
193 |
|
. |
194 |
|
brnz L_end |
195 |
|
# Evaluate cond2 |
196 |
|
. |
197 |
|
. |
198 |
|
. |
199 |
|
brnz L_end |
200 |
|
# Evaluate cond3 |
201 |
|
. |
202 |
|
. |
203 |
|
. |
204 |
|
nop |
205 |
|
nop |
206 |
|
L_end: |
207 |
|
. |
208 |
|
|
209 |
|
|
210 |
|
Local variables: |
211 |
|
mode: outline |
212 |
|
paragraph-separate: "[ ]*$" |
213 |
|
end: |