diff options
author | Bad Diode <bd@badd10de.dev> | 2021-11-03 14:51:42 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-11-03 14:51:42 +0100 |
commit | 889e34d0ca986f03de77dfa383c12f4980e746ee (patch) | |
tree | 2c070bdae851fedcefc1b748f48d4accce2ece50 | |
parent | 4e59245e506055e4e355c419de638cdc8a485c42 (diff) | |
download | bdl-889e34d0ca986f03de77dfa383c12f4980e746ee.tar.gz bdl-889e34d0ca986f03de77dfa383c12f4980e746ee.zip |
Fix behaviour of logic comparisons
-rw-r--r-- | src/compiler.h | 96 |
1 files changed, 55 insertions, 41 deletions
diff --git a/src/compiler.h b/src/compiler.h index 441b665..e511b7c 100644 --- a/src/compiler.h +++ b/src/compiler.h | |||
@@ -26,10 +26,11 @@ generate_label(void) { | |||
26 | // for freeing the memory. | 26 | // for freeing the memory. |
27 | static size_t label_counter = 0; | 27 | static size_t label_counter = 0; |
28 | char buf[32]; | 28 | char buf[32]; |
29 | memset(buf, 0, 32); | ||
30 | sprintf(buf, ".BDLL%ld", label_counter++); | 29 | sprintf(buf, ".BDLL%ld", label_counter++); |
31 | char * ret = malloc(strlen(buf)); | 30 | size_t len = strlen(buf); |
32 | memcpy(ret, buf, strlen(buf)); | 31 | char * ret = malloc(len + 1); |
32 | memcpy(ret, buf, len); | ||
33 | ret[len] = 0; | ||
33 | return ret; | 34 | return ret; |
34 | } | 35 | } |
35 | 36 | ||
@@ -85,9 +86,6 @@ typedef enum OpType { | |||
85 | OP_IS_BOOL, | 86 | OP_IS_BOOL, |
86 | OP_IS_FIXNUM, | 87 | OP_IS_FIXNUM, |
87 | // Logic operations. | 88 | // Logic operations. |
88 | OP_NOT, | ||
89 | OP_AND, | ||
90 | OP_OR, | ||
91 | OP_EQUAL, | 89 | OP_EQUAL, |
92 | OP_GREATER, | 90 | OP_GREATER, |
93 | OP_LESS, | 91 | OP_LESS, |
@@ -126,49 +124,65 @@ compile_type_predicate(OpType op, Object* args) { | |||
126 | } | 124 | } |
127 | 125 | ||
128 | void | 126 | void |
129 | compile_logic_list(OpType op, Object* args) { | 127 | compile_not(Object* args) { |
130 | printf(" ;; --> compile_logic_list\n"); | 128 | printf(" ;; --> compile_not\n"); |
131 | compile_object(args->head); | 129 | compile_object(args->head); |
132 | if (op == OP_NOT) { | 130 | printf(" pop rax\n"); |
131 | printf(" cmp rax, %d\n", FALSE_VAL); | ||
132 | printf(" mov rax, 0\n"); | ||
133 | printf(" sete al\n"); | ||
134 | printf(" shl rax, %d\n", BOOL_SHIFT); | ||
135 | printf(" or rax, %d\n", BOOL_TAG); | ||
136 | printf(" push rax\n"); | ||
137 | printf(" ;; <-- compile_not\n"); | ||
138 | } | ||
139 | |||
140 | void | ||
141 | compile_and(Object *args) { | ||
142 | printf(" ;; --> compile_and\n"); | ||
143 | char *lab_false = generate_label(); | ||
144 | char *lab_exit = generate_label(); | ||
145 | while (args != NULL) { | ||
146 | compile_object(args->head); | ||
147 | args = args->tail; | ||
133 | printf(" pop rax\n"); | 148 | printf(" pop rax\n"); |
134 | printf(" cmp rax, %d\n", FALSE_VAL); | 149 | printf(" cmp rax, %d\n", FALSE_VAL); |
135 | printf(" mov rax, 0\n"); | 150 | printf(" je %s\n", lab_false); |
136 | printf(" sete al\n"); | ||
137 | printf(" shl rax, %d\n", BOOL_SHIFT); | ||
138 | printf(" or rax, %d\n", BOOL_TAG); | ||
139 | printf(" push rax\n"); | ||
140 | printf(" ;; <-- compile_logic_list\n"); | ||
141 | return; | ||
142 | } | 151 | } |
152 | printf(" mov rax, %d\n", TRUE_VAL); | ||
153 | printf(" push rax\n"); | ||
154 | printf(" jmp %s\n", lab_exit); | ||
155 | printf("%s:\n", lab_false); | ||
156 | printf(" mov rax, %d\n", FALSE_VAL); | ||
157 | printf(" push rax\n"); | ||
158 | printf("%s:\n", lab_exit); | ||
159 | free(lab_false); | ||
160 | free(lab_exit); | ||
161 | printf(" ;; <-- compile_and\n"); | ||
162 | } | ||
143 | 163 | ||
144 | // TODO: Make sure to stop evaluating if the condition is not met. | 164 | void |
145 | args = args->tail; | 165 | compile_or(Object *args) { |
166 | printf(" ;; --> compile_or\n"); | ||
167 | char *lab_true = generate_label(); | ||
168 | char *lab_exit = generate_label(); | ||
146 | while (args != NULL) { | 169 | while (args != NULL) { |
147 | compile_object(args->head); | 170 | compile_object(args->head); |
148 | args = args->tail; | 171 | args = args->tail; |
149 | |||
150 | // Current value. | ||
151 | printf(" pop rcx\n"); | ||
152 | printf(" cmp rcx, %d\n", FALSE_VAL); | ||
153 | printf(" mov rcx, 0\n"); | ||
154 | printf(" setne cl\n"); | ||
155 | |||
156 | // Previous value. | ||
157 | printf(" pop rax\n"); | 172 | printf(" pop rax\n"); |
158 | printf(" cmp rax, %d\n", FALSE_VAL); | 173 | printf(" cmp rax, %d\n", FALSE_VAL); |
159 | printf(" mov rax, 0\n"); | 174 | printf(" jne %s\n", lab_true); |
160 | printf(" setne al\n"); | ||
161 | |||
162 | switch (op) { | ||
163 | case OP_AND: { printf(" and al, cl\n"); } break; | ||
164 | case OP_OR: { printf(" or al, cl\n"); } break; | ||
165 | default: break; | ||
166 | } | ||
167 | printf(" shl rax, %d\n", BOOL_SHIFT); | ||
168 | printf(" or rax, %d\n", BOOL_TAG); | ||
169 | printf(" push rax\n"); | ||
170 | } | 175 | } |
171 | printf(" ;; <-- compile_logic_list\n"); | 176 | printf(" mov rax, %d\n", FALSE_VAL); |
177 | printf(" push rax\n"); | ||
178 | printf(" jmp %s\n", lab_exit); | ||
179 | printf("%s:\n", lab_true); | ||
180 | printf(" mov rax, %d\n", TRUE_VAL); | ||
181 | printf(" push rax\n"); | ||
182 | printf("%s:\n", lab_exit); | ||
183 | free(lab_true); | ||
184 | free(lab_exit); | ||
185 | printf(" ;; <-- compile_or\n"); | ||
172 | } | 186 | } |
173 | 187 | ||
174 | void | 188 | void |
@@ -291,11 +305,11 @@ compile_proc_call(Object *obj) { | |||
291 | printf(" pop rdi\n"); | 305 | printf(" pop rdi\n"); |
292 | printf(" call display\n"); | 306 | printf(" call display\n"); |
293 | } else if (sv_equal(&obj->head->text, &STRING("not"))) { | 307 | } else if (sv_equal(&obj->head->text, &STRING("not"))) { |
294 | compile_logic_list(OP_NOT, obj->tail); | 308 | compile_not(obj->tail); |
295 | } else if (sv_equal(&obj->head->text, &STRING("and"))) { | 309 | } else if (sv_equal(&obj->head->text, &STRING("and"))) { |
296 | compile_logic_list(OP_AND, obj->tail); | 310 | compile_and(obj->tail); |
297 | } else if (sv_equal(&obj->head->text, &STRING("or"))) { | 311 | } else if (sv_equal(&obj->head->text, &STRING("or"))) { |
298 | compile_logic_list(OP_OR, obj->tail); | 312 | compile_or(obj->tail); |
299 | } else if (sv_equal(&obj->head->text, &STRING("="))) { | 313 | } else if (sv_equal(&obj->head->text, &STRING("="))) { |
300 | compile_cmp_list(OP_EQUAL, obj->tail); | 314 | compile_cmp_list(OP_EQUAL, obj->tail); |
301 | } else if (sv_equal(&obj->head->text, &STRING(">"))) { | 315 | } else if (sv_equal(&obj->head->text, &STRING(">"))) { |