diff options
-rw-r--r-- | src/compiler.h | 153 |
1 files changed, 93 insertions, 60 deletions
diff --git a/src/compiler.h b/src/compiler.h index 18e8a3e..76aec85 100644 --- a/src/compiler.h +++ b/src/compiler.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #define BOOL_MASK 3 | 9 | #define BOOL_MASK 3 |
10 | #define BOOL_TAG 3 | 10 | #define BOOL_TAG 3 |
11 | #define BOOL_SHIFT 2 | 11 | #define BOOL_SHIFT 2 |
12 | #define TRUE_VAL ((1 << BOOL_SHIFT) | BOOL_TAG) | ||
13 | #define FALSE_VAL ((0 << BOOL_SHIFT) | BOOL_TAG) | ||
12 | #define FIXNUM_MASK 1 | 14 | #define FIXNUM_MASK 1 |
13 | #define FIXNUM_TAG 0 | 15 | #define FIXNUM_TAG 0 |
14 | #define FIXNUM_SHIFT 1 | 16 | #define FIXNUM_SHIFT 1 |
@@ -69,47 +71,18 @@ typedef enum OpType { | |||
69 | OP_IS_ZERO, | 71 | OP_IS_ZERO, |
70 | OP_IS_BOOL, | 72 | OP_IS_BOOL, |
71 | OP_IS_FIXNUM, | 73 | OP_IS_FIXNUM, |
72 | // TODO: etc. | 74 | // Logic operations. |
75 | OP_NOT, | ||
76 | OP_AND, | ||
77 | OP_OR, | ||
78 | OP_EQUAL, | ||
79 | OP_GREATER, | ||
80 | OP_LESS, | ||
81 | OP_GREATER_EQ, | ||
82 | OP_LESS_EQL, | ||
73 | } OpType; | 83 | } OpType; |
74 | 84 | ||
75 | void | 85 | void |
76 | arithmetic_op(OpType type) { | ||
77 | printf(" ;; --> arithmetic_op\n"); | ||
78 | printf(" pop rcx\n"); | ||
79 | printf(" pop rax\n"); | ||
80 | switch (type) { | ||
81 | case OP_ADD: { printf(" add rax, rcx\n"); } break; | ||
82 | case OP_SUB: { printf(" sub rax, rcx\n"); } break; | ||
83 | case OP_MUL: { | ||
84 | printf(" sar rax, %d\n", FIXNUM_SHIFT); | ||
85 | printf(" sar rcx, %d\n", FIXNUM_SHIFT); | ||
86 | printf(" mul rcx\n"); | ||
87 | printf(" sal rax, %d\n", FIXNUM_SHIFT); | ||
88 | } break; | ||
89 | case OP_DIV: { | ||
90 | printf(" sar rax, %d\n", FIXNUM_SHIFT); | ||
91 | printf(" sar rcx, %d\n", FIXNUM_SHIFT); | ||
92 | printf(" mov rdx, 0\n"); | ||
93 | printf(" div rcx\n"); | ||
94 | printf(" sal rax, %d\n", FIXNUM_SHIFT); | ||
95 | } break; | ||
96 | case OP_MOD: { | ||
97 | printf(" sar rax, %d\n", FIXNUM_SHIFT); | ||
98 | printf(" sar rcx, %d\n", FIXNUM_SHIFT); | ||
99 | printf(" mov rdx, 0\n"); | ||
100 | printf(" div rcx\n"); | ||
101 | printf(" mov rax, rdx\n"); | ||
102 | printf(" sal rax, %d\n", FIXNUM_SHIFT); | ||
103 | } break; | ||
104 | default: break; | ||
105 | } | ||
106 | printf(" push rax\n"); | ||
107 | printf(" ;; <-- arithmetic_op\n"); | ||
108 | } | ||
109 | |||
110 | typedef void (CompileProc)(OpType, Object*); | ||
111 | |||
112 | void | ||
113 | compile_type_predicate(OpType op, Object* args) { | 86 | compile_type_predicate(OpType op, Object* args) { |
114 | printf(" ;; --> compile_type_predicate\n"); | 87 | printf(" ;; --> compile_type_predicate\n"); |
115 | compile_object(args->head); | 88 | compile_object(args->head); |
@@ -143,19 +116,69 @@ compile_type_predicate(OpType op, Object* args) { | |||
143 | // TODO: Next -> numerical comparison operators =, <=, ... | 116 | // TODO: Next -> numerical comparison operators =, <=, ... |
144 | // "=", "<", ">", "<=", ">=", | 117 | // "=", "<", ">", "<=", ">=", |
145 | // "not", "and", "or", | 118 | // "not", "and", "or", |
146 | // NOTE: Make sure to stop evaluating if the condition is not met. | 119 | |
120 | void | ||
121 | compile_logic_list(OpType op, Object* args) { | ||
122 | printf(" ;; --> compile_logic_list\n"); | ||
123 | compile_object(args->head); | ||
124 | do { | ||
125 | // TODO: Make sure to stop evaluating if the condition is not met. | ||
126 | args = args->tail; | ||
127 | printf(" pop rax\n"); | ||
128 | switch (op) { | ||
129 | case OP_NOT: { | ||
130 | printf(" cmp rax, %d\n", FALSE_VAL); | ||
131 | printf(" mov rax, 0\n"); | ||
132 | } break; | ||
133 | default: break; | ||
134 | } | ||
135 | printf(" sete al\n"); | ||
136 | printf(" sal rax, %d\n", BOOL_SHIFT); | ||
137 | printf(" or rax, %d\n", BOOL_TAG); | ||
138 | printf(" push rax\n"); | ||
139 | } while (args != NULL); | ||
140 | printf(" ;; <-- compile_logic_list\n"); | ||
141 | } | ||
147 | 142 | ||
148 | void | 143 | void |
149 | compile_arithmetic_list(OpType op, Object* args) { | 144 | compile_arithmetic_list(OpType op, Object* args) { |
150 | printf(" ;; --> compile_arithmetic_list\n"); | 145 | printf(" ;; --> compile_arithmetic\n"); |
151 | compile_object(args->head); | 146 | compile_object(args->head); |
152 | args = args->tail; | 147 | args = args->tail; |
153 | while (args != NULL) { | 148 | while (args != NULL) { |
154 | compile_object(args->head); | 149 | compile_object(args->head); |
155 | args = args->tail; | 150 | args = args->tail; |
156 | arithmetic_op(op); | 151 | printf(" pop rcx\n"); |
152 | printf(" pop rax\n"); | ||
153 | switch (op) { | ||
154 | case OP_ADD: { printf(" add rax, rcx\n"); } break; | ||
155 | case OP_SUB: { printf(" sub rax, rcx\n"); } break; | ||
156 | case OP_MUL: { | ||
157 | printf(" sar rax, %d\n", FIXNUM_SHIFT); | ||
158 | printf(" sar rcx, %d\n", FIXNUM_SHIFT); | ||
159 | printf(" mul rcx\n"); | ||
160 | printf(" sal rax, %d\n", FIXNUM_SHIFT); | ||
161 | } break; | ||
162 | case OP_DIV: { | ||
163 | printf(" sar rax, %d\n", FIXNUM_SHIFT); | ||
164 | printf(" sar rcx, %d\n", FIXNUM_SHIFT); | ||
165 | printf(" mov rdx, 0\n"); | ||
166 | printf(" div rcx\n"); | ||
167 | printf(" sal rax, %d\n", FIXNUM_SHIFT); | ||
168 | } break; | ||
169 | case OP_MOD: { | ||
170 | printf(" sar rax, %d\n", FIXNUM_SHIFT); | ||
171 | printf(" sar rcx, %d\n", FIXNUM_SHIFT); | ||
172 | printf(" mov rdx, 0\n"); | ||
173 | printf(" div rcx\n"); | ||
174 | printf(" mov rax, rdx\n"); | ||
175 | printf(" sal rax, %d\n", FIXNUM_SHIFT); | ||
176 | } break; | ||
177 | default: break; | ||
178 | } | ||
179 | printf(" push rax\n"); | ||
157 | } | 180 | } |
158 | printf(" ;; <-- compile_arithmetic_list\n"); | 181 | printf(" ;; <-- compile_arithmetic\n"); |
159 | } | 182 | } |
160 | 183 | ||
161 | void | 184 | void |
@@ -164,35 +187,45 @@ compile_proc_call(Object *obj) { | |||
164 | // initialized at the start of the compilation procedure. | 187 | // initialized at the start of the compilation procedure. |
165 | if (sv_equal(&obj->head->text, &STRING("+"))) { | 188 | if (sv_equal(&obj->head->text, &STRING("+"))) { |
166 | compile_arithmetic_list(OP_ADD, obj->tail); | 189 | compile_arithmetic_list(OP_ADD, obj->tail); |
167 | } | 190 | } else if (sv_equal(&obj->head->text, &STRING("-"))) { |
168 | if (sv_equal(&obj->head->text, &STRING("-"))) { | ||
169 | compile_arithmetic_list(OP_SUB, obj->tail); | 191 | compile_arithmetic_list(OP_SUB, obj->tail); |
170 | } | 192 | } else if (sv_equal(&obj->head->text, &STRING("*"))) { |
171 | if (sv_equal(&obj->head->text, &STRING("*"))) { | ||
172 | compile_arithmetic_list(OP_MUL, obj->tail); | 193 | compile_arithmetic_list(OP_MUL, obj->tail); |
173 | } | 194 | } else if (sv_equal(&obj->head->text, &STRING("/"))) { |
174 | if (sv_equal(&obj->head->text, &STRING("/"))) { | ||
175 | compile_arithmetic_list(OP_DIV, obj->tail); | 195 | compile_arithmetic_list(OP_DIV, obj->tail); |
176 | } | 196 | } else if (sv_equal(&obj->head->text, &STRING("%"))) { |
177 | if (sv_equal(&obj->head->text, &STRING("%"))) { | ||
178 | compile_arithmetic_list(OP_MOD, obj->tail); | 197 | compile_arithmetic_list(OP_MOD, obj->tail); |
179 | } | 198 | } else if (sv_equal(&obj->head->text, &STRING("nil?"))) { |
180 | if (sv_equal(&obj->head->text, &STRING("nil?"))) { | ||
181 | compile_type_predicate(OP_IS_NIL, obj->tail); | 199 | compile_type_predicate(OP_IS_NIL, obj->tail); |
182 | } | 200 | } else if (sv_equal(&obj->head->text, &STRING("zero?"))) { |
183 | if (sv_equal(&obj->head->text, &STRING("zero?"))) { | ||
184 | compile_type_predicate(OP_IS_ZERO, obj->tail); | 201 | compile_type_predicate(OP_IS_ZERO, obj->tail); |
185 | } | 202 | } else if (sv_equal(&obj->head->text, &STRING("fixnum?"))) { |
186 | if (sv_equal(&obj->head->text, &STRING("fixnum?"))) { | ||
187 | compile_type_predicate(OP_IS_FIXNUM, obj->tail); | 203 | compile_type_predicate(OP_IS_FIXNUM, obj->tail); |
188 | } | 204 | } else if (sv_equal(&obj->head->text, &STRING("bool?"))) { |
189 | if (sv_equal(&obj->head->text, &STRING("bool?"))) { | ||
190 | compile_type_predicate(OP_IS_BOOL, obj->tail); | 205 | compile_type_predicate(OP_IS_BOOL, obj->tail); |
191 | } | 206 | } else if (sv_equal(&obj->head->text, &STRING("display"))) { |
192 | if (sv_equal(&obj->head->text, &STRING("display"))) { | ||
193 | compile_object(obj->tail->head); | 207 | compile_object(obj->tail->head); |
194 | printf(" pop rdi\n"); | 208 | printf(" pop rdi\n"); |
195 | printf(" call display\n"); | 209 | printf(" call display\n"); |
210 | } else if (sv_equal(&obj->head->text, &STRING("not"))) { | ||
211 | compile_logic_list(OP_NOT, obj->tail); | ||
212 | } else if (sv_equal(&obj->head->text, &STRING("and"))) { | ||
213 | compile_logic_list(OP_AND, obj->tail); | ||
214 | } else if (sv_equal(&obj->head->text, &STRING("or"))) { | ||
215 | compile_logic_list(OP_OR, obj->tail); | ||
216 | } else if (sv_equal(&obj->head->text, &STRING("="))) { | ||
217 | compile_logic_list(OP_EQUAL, obj->tail); | ||
218 | } else if (sv_equal(&obj->head->text, &STRING(">"))) { | ||
219 | compile_logic_list(OP_GREATER, obj->tail); | ||
220 | } else if (sv_equal(&obj->head->text, &STRING("<"))) { | ||
221 | compile_logic_list(OP_LESS, obj->tail); | ||
222 | } else if (sv_equal(&obj->head->text, &STRING(">="))) { | ||
223 | compile_logic_list(OP_GREATER_EQ, obj->tail); | ||
224 | } else if (sv_equal(&obj->head->text, &STRING("<="))) { | ||
225 | compile_logic_list(OP_LESS_EQL, obj->tail); | ||
226 | } else { | ||
227 | fprintf(stderr, "error: not implemented\n"); | ||
228 | exit(EXIT_FAILURE); | ||
196 | } | 229 | } |
197 | } | 230 | } |
198 | 231 | ||