9 typedef enum Type Type;
18 typedef enum Builtin Builtin;
26 typedef union Value Value;
35 typedef struct Object Object;
41 #define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL }
43 void Object_deinitialize(Object* self) {
46 {% include "environment.c" %}
47 {% include "stack.c" %}
50 typedef struct Thread Thread;
52 Environment* environment;
54 size_t program_counter;
57 void Thread_initialize(Thread* self, size_t program_counter) {
58 self->environment = Environment_construct();
59 Stack_initialize(&(self->stack));
60 self->program_counter = program_counter;
63 void Thread_deinitialize(Thread* self) {
64 Environment_destruct(self->environment);
65 Stack_deinitialize(&(self->stack));
69 typedef const union Argument Argument;
77 void call(struct Thread* thread, Argument argument) {
78 assert(!Stack_isEmpty(&(thread->stack)));
79 Object f = Stack_pop(&(thread->stack));
80 size_t argumentCount = argument.label;
84 switch(f.value.builtin) {
87 assert(argumentCount == 2);
88 assert(!Stack_isEmpty(&(thread->stack)));
89 Object exponent = Stack_pop(&(thread->stack));
90 assert(exponent.type == INTEGER);
91 assert(exponent.value.integer >= 0);
93 assert(!Stack_isEmpty(&(thread->stack)));
94 Object base = Stack_pop(&(thread->stack));
95 assert(base.type == INTEGER);
98 result.type = INTEGER;
99 result.value.integer = 1;
101 while(exponent.value.integer > 0) {
102 result.value.integer *= base.value.integer;
103 exponent.value.integer--;
106 Stack_push(&(thread->stack), result);
111 // TODO Handle multiple arguments
112 assert(!Stack_isEmpty(&(thread->stack)));
113 Object arg = Stack_pop(&(thread->stack));
117 if(arg.value.boolean) printf("true");
118 else printf("false");
121 printf("%i", arg.value.integer);
125 printf("%s", arg.value.string);
132 Stack_push(&(thread->stack), BUILTIN_NIL);
146 {% with name='add', operation='+' %}
147 {% include "arithmetic_instruction.c" %}
151 void drop(struct Thread* thread, Argument argument) {
152 assert(!Stack_isEmpty(&(thread->stack)));
153 Object result = Stack_pop(&(thread->stack));
154 Object_deinitialize(&result);
157 void end(struct Thread* thread, Argument argument) {
160 {% with name='idiv', operation='/' %}
161 {% include "arithmetic_instruction.c" %}
164 {% with name='mod', operation='%' %}
165 {% include "arithmetic_instruction.c" %}
168 {% with name='mul', operation='*' %}
169 {% include "arithmetic_instruction.c" %}
172 void neg(struct Thread* thread, Argument argument) {
173 assert(!Stack_isEmpty(&(thread->stack)));
174 Object result = Stack_pop(&(thread->stack));
175 assert(result.type == INTEGER);
177 result.value.integer = -(result.value.integer);
179 Stack_push(&(thread->stack), result);
182 void pop(struct Thread* thread, Argument argument) {
183 char* argumentString = argument.string;
185 assert(!Stack_isEmpty(&(thread->stack)));
186 Object result = Stack_pop(&(thread->stack));
188 if(strcmp(argumentString, "print") == 0) {
190 } else if(strcmp(argumentString, "pow") == 0) {
195 Environment_set(thread->environment, argumentString, result);
198 void push(struct Thread* thread, Argument argument) {
199 char* argumentString = argument.string;
201 if(strcmp(argumentString, "false") == 0) {
202 Stack_push(&(thread->stack), (Object){ BOOLEAN, false });
203 }else if(strcmp(argumentString, "pow") == 0) {
205 result.type = BUILTIN;
206 result.value.builtin = POW;
207 Stack_push(&(thread->stack), result);
208 } else if(strcmp(argumentString, "print") == 0) {
210 result.type = BUILTIN;
211 result.value.builtin = PRINT;
212 Stack_push(&(thread->stack), result);
213 } else if(strcmp(argumentString, "true") == 0) {
214 Stack_push(&(thread->stack), (Object){ BOOLEAN, true });
216 Environment_get_Result result = Environment_get(thread->environment, argumentString);
218 fprintf(stderr, "Variable `%s` not found", argumentString);
221 Stack_push(&(thread->stack), result.result);
225 void push_integer(struct Thread* thread, Argument argument) {
227 result.type = INTEGER;
228 result.value.integer = argument.integer;
230 Stack_push(&(thread->stack), result);
233 void push_string(struct Thread* thread, Argument argument) {
235 result.type = STRING;
236 result.value.string = argument.string;
238 Stack_push(&(thread->stack), result);
241 {% with name='sub', operation='-' %}
242 {% include "arithmetic_instruction.c" %}
246 typedef const struct Instruction Instruction;
248 void (*instruction)(struct Thread*,Argument);
252 {% for label in labels_to_instruction_indices.keys() %}
253 #define LABEL_{{ label }} {{ labels_to_instruction_indices[label] }}
256 const Instruction program[] = {
257 {% for instruction in instruction_list %}
258 (Instruction){ {{ instruction.instruction }}, (Argument){{ generate_argument(instruction) }} },
264 Thread_initialize(&thread, 0);
266 for(; program[thread.program_counter].instruction != end; thread.program_counter++) {
267 program[thread.program_counter].instruction(
269 program[thread.program_counter].argument
273 Thread_deinitialize(&thread);