9 typedef enum Type Type;
17 typedef enum Builtin Builtin;
24 typedef union Value Value;
32 typedef struct Object Object;
38 #define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL }
40 void Object_deinitialize(Object* self) {
43 {% include "environment.c" %}
44 {% include "stack.c" %}
47 typedef struct Thread Thread;
49 Environment* environment;
51 size_t program_counter;
54 void Thread_initialize(Thread* self, size_t program_counter) {
55 self->environment = Environment_construct();
56 Stack_initialize(&(self->stack));
57 self->program_counter = program_counter;
60 void Thread_deinitialize(Thread* self) {
61 Environment_destruct(self->environment);
62 Stack_deinitialize(&(self->stack));
66 typedef const union Argument Argument;
74 void call(struct Thread* thread, const union Argument argument) {
75 assert(!Stack_isEmpty(&(thread->stack)));
76 Object f = Stack_pop(&(thread->stack));
80 switch(f.value.builtin) {
83 // TODO Handle multiple arguments
84 assert(!Stack_isEmpty(&(thread->stack)));
85 Object arg = Stack_pop(&(thread->stack));
89 printf("%i", arg.value.integer);
93 printf("%s", arg.value.string);
100 Stack_push(&(thread->stack), BUILTIN_NIL);
114 {% with name='add', operation='+' %}
115 {% include "arithmetic_instruction.c" %}
119 void drop(struct Thread* thread, const union Argument argument) {
120 assert(!Stack_isEmpty(&(thread->stack)));
121 Object result = Stack_pop(&(thread->stack));
122 Object_deinitialize(&result);
125 void end(struct Thread* thread, const union Argument argument) {
128 {% with name='idiv', operation='/' %}
129 {% include "arithmetic_instruction.c" %}
132 {% with name='mod', operation='%' %}
133 {% include "arithmetic_instruction.c" %}
136 {% with name='mul', operation='*' %}
137 {% include "arithmetic_instruction.c" %}
140 void pop(struct Thread* thread, const union Argument argument) {
141 char* argumentString = argument.string;
143 assert(!Stack_isEmpty(&(thread->stack)));
144 Object result = Stack_pop(&(thread->stack));
146 if(strcmp(argumentString, "print") == 0) {
150 Environment_set(thread->environment, argumentString, result);
153 void push(struct Thread* thread, const union Argument argument) {
154 char* argumentString = argument.string;
156 if(strcmp(argumentString, "print") == 0) {
158 result.type = BUILTIN;
159 result.value.builtin = PRINT;
160 Stack_push(&(thread->stack), result);
162 Environment_get_Result result = Environment_get(thread->environment, argumentString);
164 fprintf(stderr, "Variable `%s` not found", argumentString);
167 Stack_push(&(thread->stack), result.result);
171 void push_integer(struct Thread* thread, const union Argument argument) {
173 result.type = INTEGER;
174 result.value.integer = argument.integer;
176 Stack_push(&(thread->stack), result);
179 void push_string(struct Thread* thread, const union Argument argument) {
181 result.type = STRING;
182 result.value.string = argument.string;
184 Stack_push(&(thread->stack), result);
187 {% with name='sub', operation='-' %}
188 {% include "arithmetic_instruction.c" %}
192 typedef const struct Instruction Instruction;
194 void (*instruction)(struct Thread*,const union Argument);
198 {% for label in labels_to_instruction_indices.keys() %}
199 #define LABEL_{{ label }} {{ labels_to_instruction_indices[label] }}
202 const Instruction program[] = {
203 {% for instruction in instruction_list %}
204 (Instruction){ {{ instruction.instruction }}, (Argument){{ generate_argument(instruction) }} },
210 Thread_initialize(&thread, 0);
212 for(; program[thread.program_counter].instruction != end; thread.program_counter++) {
213 program[thread.program_counter].instruction(
215 program[thread.program_counter].argument
219 Thread_deinitialize(&thread);