d22d595d8c1768ed8bb347106025f168173044a1
[fur] / templates / program2.c
1 #include<assert.h>
2 #include<stdbool.h>
3 #include<stdint.h>
4 #include<stdio.h>
5 #include<stdlib.h>
6 #include<string.h>
7
8 enum Type;
9 typedef enum Type Type;
10 enum Type {
11   BOOLEAN,
12   BUILTIN,
13   CLOSURE,
14   INTEGER,
15   LIST,
16   STRING,
17   STRUCTURE,
18   SYMBOL
19 };
20
21 enum Builtin;
22 typedef enum Builtin Builtin;
23 enum Builtin {
24   __FIELD__,
25   NIL,
26   POW,
27   PRINT
28 };
29
30 struct Object;
31 typedef struct Object Object;
32 struct Environment;
33 typedef struct Environment Environment;
34 struct Thread;
35 typedef struct Thread Thread;
36
37 struct Closure;
38 typedef struct Closure Closure;
39 struct Closure {
40   Environment* environment;
41   size_t entry;
42 };
43
44 struct List;
45 typedef struct List List;
46
47 struct Structure;
48 typedef struct Structure Structure;
49
50 union Value;
51 typedef union Value Value;
52 union Value {
53   Builtin builtin;
54   bool boolean;
55   Closure closure;
56   int32_t integer;
57   List* list;
58   char* string;
59   Structure* structure;
60   char* symbol;
61 };
62
63 struct Object {
64   Type type;
65   Value value;
66 };
67
68 struct List {
69   Object head;
70   List* tail;
71 };
72
73 struct Structure {
74   char* key;
75   Object value;
76   Structure* next;
77 };
78
79 #define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL }
80
81 void Object_deinitialize(Object* self) {
82 }
83
84 {% include "environment.c" %}
85 {% include "stack.c" %}
86 {% include "frame.c" %}
87
88 struct Thread {
89   Frame frame;
90   Stack stack;
91 };
92
93 void Thread_initialize(Thread* self, size_t programCounter) {
94   Frame_initialize(&(self->frame), Environment_construct(NULL), NULL, programCounter);
95   Stack_initialize(&(self->stack));
96 }
97
98 void Thread_deinitialize(Thread* self) {
99   Frame_deinitialize(&(self->frame));
100   Stack_deinitialize(&(self->stack));
101 }
102
103 Environment* Thread_getEnvironment(Thread* self) {
104   return self->frame.environment;
105 }
106
107 void Thread_setProgramCounter(Thread* self, size_t programCounter) {
108   self->frame.programCounter = programCounter;
109 }
110
111 void Thread_incrementProgramCounter(Thread* self) {
112   self->frame.programCounter++;
113 }
114
115 size_t Thread_getProgramCounter(Thread* self) {
116   return self->frame.programCounter;
117 }
118
119 union Argument;
120 typedef const union Argument Argument;
121 union Argument {
122   size_t label;
123   void* pointer;
124   char* string;
125   int32_t integer;
126   char* symbol;
127 };
128
129 void callBuiltinField(Thread* thread, size_t argumentCount) {
130   assert(argumentCount == 2);
131
132   assert(!Stack_isEmpty(&(thread->stack)));
133   Object key = Stack_pop(&(thread->stack));
134   assert(key.type == SYMBOL);
135
136   assert(!Stack_isEmpty(&(thread->stack)));
137   Object structure = Stack_pop(&(thread->stack));
138   assert(structure.type == STRUCTURE);
139
140   while(structure.value.structure != NULL) {
141     if(strcmp(structure.value.structure->key, key.value.string) == 0) {
142       Stack_push(&(thread->stack), structure.value.structure->value);
143       return;
144     }
145     structure.value.structure = structure.value.structure->next;
146   }
147
148   assert(false); // Symbol wasn't found in structure
149 }
150
151 void callBuiltinPow(Thread* thread, size_t argumentCount) {
152   assert(argumentCount == 2);
153   assert(!Stack_isEmpty(&(thread->stack)));
154   Object exponent = Stack_pop(&(thread->stack));
155   assert(exponent.type == INTEGER);
156   assert(exponent.value.integer >= 0);
157
158   assert(!Stack_isEmpty(&(thread->stack)));
159   Object base = Stack_pop(&(thread->stack));
160   assert(base.type == INTEGER);
161
162   Object result;
163   result.type = INTEGER;
164   result.value.integer = 1;
165
166   while(exponent.value.integer > 0) {
167     result.value.integer *= base.value.integer;
168     exponent.value.integer--;
169   }
170
171   Stack_push(&(thread->stack), result);
172 }
173
174 void callBuiltinPrint(Thread* thread, size_t argumentCount) {
175   assert(argumentCount > 0);
176
177   Object arguments[argumentCount];
178   size_t count;
179
180   for(count = 0; count < argumentCount; count++) {
181     assert(!Stack_isEmpty(&(thread->stack)));
182     arguments[argumentCount - count - 1] = Stack_pop(&(thread->stack));
183   }
184
185   for(count = 0; count < argumentCount; count ++) {
186     Object arg = arguments[count];
187
188     switch(arg.type) {
189       case BOOLEAN:
190         if(arg.value.boolean) printf("true");
191         else printf("false");
192         break;
193
194       case INTEGER:
195         printf("%i", arg.value.integer);
196         break;
197
198       case STRING:
199         printf("%s", arg.value.string);
200         break;
201
202       default:
203         assert(false);
204     }
205   }
206
207   Stack_push(&(thread->stack), BUILTIN_NIL);
208 }
209
210 void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) {
211   switch(b) {
212     case __FIELD__:
213       callBuiltinField(thread, argumentCount);
214       break;
215
216     case POW:
217       callBuiltinPow(thread, argumentCount);
218       break;
219
220     case PRINT:
221       callBuiltinPrint(thread, argumentCount);
222       break;
223
224     default:
225       assert(false);
226   }
227 }
228
229 void callClosure(Thread* thread, Closure closure, size_t argumentCount) {
230   // TODO Find a way to assert the argument count
231
232   Frame* returnFrame = malloc(sizeof(Frame));
233   *returnFrame = thread->frame;
234   Frame_initialize(
235     &(thread->frame),
236     Environment_construct(Environment_reference(closure.environment)),
237     returnFrame,
238     closure.entry - 1 // We will increment the frame immediately after this
239   );
240 }
241
242 void inst_call(Thread* thread, Argument argument) {
243   assert(!Stack_isEmpty(&(thread->stack)));
244   Object f = Stack_pop(&(thread->stack));
245   size_t argumentCount = argument.label;
246
247   switch(f.type) {
248     case BUILTIN:
249       callBuiltin(thread, f.value.builtin, argumentCount);
250       break;
251
252     case CLOSURE:
253       callClosure(thread, f.value.closure, argumentCount);
254       break;
255
256     default:
257       assert(false);
258   }
259 }
260
261 void inst_concat(Thread* thread, Argument argument) {
262   assert(!Stack_isEmpty(&(thread->stack)));
263   Object left = Stack_pop(&(thread->stack));
264   assert(!Stack_isEmpty(&(thread->stack)));
265   Object right = Stack_pop(&(thread->stack));
266
267   assert(left.type == STRING);
268   assert(right.type == STRING);
269
270   char* resultString = malloc(strlen(left.value.string) + strlen(right.value.string) + 1);
271   resultString[0] = '\0';
272
273   strcat(resultString, left.value.string);
274   strcat(resultString, right.value.string);
275
276   Object resultObject = (Object) {
277     STRING,
278     (Value)resultString
279   };
280
281   Stack_push(&(thread->stack), resultObject);
282 }
283
284 {% with name='add', operation='+' %}
285   {% include "arithmetic_instruction.c" %}
286 {% endwith %}
287
288 void inst_close(Thread* thread, Argument argument) {
289   Object result;
290   result.type = CLOSURE;
291   result.value.closure.environment = Thread_getEnvironment(thread);
292   result.value.closure.entry = argument.label;
293
294   Stack_push(&(thread->stack), result);
295 }
296
297 void inst_drop(Thread* thread, Argument argument) {
298   assert(!Stack_isEmpty(&(thread->stack)));
299   Object result = Stack_pop(&(thread->stack));
300   Object_deinitialize(&result);
301 }
302
303 void inst_end(Thread* thread, Argument argument) {
304 }
305
306 {% with name='eq', operation='==' %}
307   {% include "comparison_instruction.c" %}
308 {% endwith %}
309
310 void inst_get(Thread* thread, Argument argument) {
311   assert(!Stack_isEmpty(&(thread->stack)));
312   Object indexObject = Stack_pop(&(thread->stack));
313   assert(indexObject.type == INTEGER);
314   int32_t index = indexObject.value.integer;
315
316   assert(!Stack_isEmpty(&(thread->stack)));
317   Object listObject = Stack_pop(&(thread->stack));
318   assert(listObject.type == LIST);
319   List* list = listObject.value.list;
320
321   while(index > 0) {
322     assert(list != NULL);
323     list = list->tail;
324     index--;
325   }
326
327   assert(list != NULL);
328   Stack_push(&(thread->stack), list->head);
329 }
330
331 {% with name='gt', operation='>' %}
332   {% include "comparison_instruction.c" %}
333 {% endwith %}
334
335 {% with name='gte', operation='>=' %}
336   {% include "comparison_instruction.c" %}
337 {% endwith %}
338
339 {% with name='idiv', operation='/' %}
340   {% include "arithmetic_instruction.c" %}
341 {% endwith %}
342
343 void inst_jump(Thread* thread, Argument argument) {
344   Thread_setProgramCounter(thread, argument.label - 1); // We will increment before running
345 }
346
347 void inst_jump_if_false(Thread* thread, Argument argument) {
348   assert(!Stack_isEmpty(&(thread->stack)));
349   Object result = Stack_pop(&(thread->stack));
350   assert(result.type == BOOLEAN);
351
352   if(!(result.value.boolean)) {
353     inst_jump(thread, argument);
354   }
355 }
356
357 void inst_list(Thread* thread, Argument argument) {
358   Object result;
359   result.type = LIST;
360   result.value.list = NULL;
361
362   int32_t count = argument.integer;
363
364   while(count > 0) {
365     assert(!Stack_isEmpty(&(thread->stack)));
366     Object item = Stack_pop(&(thread->stack));
367
368     List* node = malloc(sizeof(List));
369     node->head = item;
370     node->tail = result.value.list;
371
372     result.value.list = node;
373     count--;
374   }
375
376   Stack_push(&(thread->stack), result);
377 }
378
379 {% with name='lt', operation='<' %}
380   {% include "comparison_instruction.c" %}
381 {% endwith %}
382
383 {% with name='lte', operation='<=' %}
384   {% include "comparison_instruction.c" %}
385 {% endwith %}
386
387 {% with name='mod', operation='%' %}
388   {% include "arithmetic_instruction.c" %}
389 {% endwith %}
390
391 {% with name='mul', operation='*' %}
392   {% include "arithmetic_instruction.c" %}
393 {% endwith %}
394
395 {% with name='neq', operation='!=' %}
396   {% include "comparison_instruction.c" %}
397 {% endwith %}
398
399 void inst_neg(Thread* thread, Argument argument) {
400   assert(!Stack_isEmpty(&(thread->stack)));
401   Object result = Stack_pop(&(thread->stack));
402   assert(result.type == INTEGER);
403
404   result.value.integer = -(result.value.integer);
405
406   Stack_push(&(thread->stack), result);
407 }
408
409 void inst_pop(Thread* thread, Argument argument) {
410   char* argumentString = argument.string;
411
412   assert(!Stack_isEmpty(&(thread->stack)));
413   Object result = Stack_pop(&(thread->stack));
414
415   if(strcmp(argumentString, "print") == 0) {
416     assert(false);
417   } else if(strcmp(argumentString, "pow") == 0) {
418     assert(false);
419   }
420
421
422   Environment_set(Thread_getEnvironment(thread), argumentString, result);
423 }
424
425 void inst_push(Thread* thread, Argument argument) {
426   char* argumentString = argument.string;
427
428   if(strcmp(argumentString, "__field__") == 0) {
429     // TODO Make this an instruction
430     Object result;
431     result.type = BUILTIN;
432     result.value.builtin = __FIELD__;
433     Stack_push(&(thread->stack), result);
434   } else if(strcmp(argumentString, "false") == 0) {
435     Stack_push(&(thread->stack), (Object){ BOOLEAN, false });
436   } else if(strcmp(argumentString, "pow") == 0) {
437     Object result;
438     result.type = BUILTIN;
439     result.value.builtin = POW;
440     Stack_push(&(thread->stack), result);
441   } else if(strcmp(argumentString, "print") == 0) {
442     Object result;
443     result.type = BUILTIN;
444     result.value.builtin = PRINT;
445     Stack_push(&(thread->stack), result);
446   } else if(strcmp(argumentString, "true") == 0) {
447     Stack_push(&(thread->stack), (Object){ BOOLEAN, true });
448   } else {
449     Environment_get_Result result = Environment_get(
450       Thread_getEnvironment(thread),
451       argumentString
452     );
453     if(!result.found) {
454       fprintf(stderr, "Variable `%s` not found", argumentString);
455       assert(false);
456     }
457     Stack_push(&(thread->stack), result.result);
458   }
459 }
460
461 void inst_push_integer(Thread* thread, Argument argument) {
462   Object result;
463   result.type = INTEGER;
464   result.value.integer = argument.integer;
465
466   Stack_push(&(thread->stack), result);
467 }
468
469 void inst_push_string(Thread* thread, Argument argument) {
470   Object result;
471   result.type = STRING;
472   result.value.string = argument.string;
473
474   Stack_push(&(thread->stack), result);
475 }
476
477 void inst_push_symbol(Thread* thread, Argument argument) {
478   // TODO Store symbols in a symbol table so they can be looked up by reference
479   // without string comparison
480   Object result;
481   result.type = SYMBOL;
482   result.value.symbol = argument.symbol;
483
484   Stack_push(&(thread->stack), result);
485 }
486
487 {% with name='sub', operation='-' %}
488   {% include "arithmetic_instruction.c" %}
489 {% endwith %}
490
491 void inst_return(Thread* thread, Argument argument) {
492   Frame* returnFrame = thread->frame.returnFrame;
493
494   Frame_deinitialize(&(thread->frame));
495
496   Frame_initialize(
497     &(thread->frame),
498     returnFrame->environment,
499     returnFrame->returnFrame,
500     returnFrame->programCounter
501   );
502
503   free(returnFrame);
504 }
505
506 void inst_structure(Thread* thread, Argument argument) {
507   Object result;
508   result.type = STRUCTURE;
509   result.value.structure = NULL;
510
511   int32_t count = argument.integer;
512
513   while(count > 0) {
514     assert(!Stack_isEmpty(&(thread->stack)));
515     Object key = Stack_pop(&(thread->stack));
516     assert(key.type == SYMBOL);
517
518     assert(!Stack_isEmpty(&(thread->stack)));
519     Object value = Stack_pop(&(thread->stack));
520
521     Structure* node = malloc(sizeof(Structure));
522     node->key = key.value.string;
523     node->value = value;
524     node->next = result.value.structure;
525
526     result.value.structure = node;
527     count--;
528   }
529
530   Stack_push(&(thread->stack), result);
531 }
532
533 struct Instruction;
534 typedef const struct Instruction Instruction;
535 struct Instruction {
536   void (*instruction)(Thread*,Argument);
537   Argument argument;
538 };
539
540 {% for label in labels_to_instruction_indices.keys() %}
541 #define LABEL_{{ label }} {{ labels_to_instruction_indices[label] }}
542 {% endfor %}
543
544 const Instruction program[] = {
545 {% for instruction in instruction_list %}
546   (Instruction){ inst_{{ instruction.instruction }}, (Argument){{ generate_argument(instruction) }} },
547 {% endfor %}
548 };
549
550 int main() {
551   Thread thread;
552   Thread_initialize(&thread, LABEL___main__);
553
554   for(; program[Thread_getProgramCounter(&thread)].instruction != inst_end; Thread_incrementProgramCounter(&thread)) {
555     program[Thread_getProgramCounter(&thread)].instruction(
556       &thread,
557       program[Thread_getProgramCounter(&thread)].argument
558     );
559   }
560
561   Thread_deinitialize(&thread);
562
563   return 0;
564 }