9 typedef enum Type Type;
17 typedef enum Builtin Builtin;
25 typedef union Value Value;
33 typedef struct Object Object;
39 #define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL }
41 void Object_deinitialize(Object* self) {
44 {% include "environment.c" %}
45 {% include "stack.c" %}
48 typedef struct Thread Thread;
50 Environment* environment;
52 size_t program_counter;
55 void Thread_initialize(Thread* self, size_t program_counter) {
56 self->environment = Environment_construct();
57 Stack_initialize(&(self->stack));
58 self->program_counter = program_counter;
61 void Thread_deinitialize(Thread* self) {
62 Environment_destruct(self->environment);
63 Stack_deinitialize(&(self->stack));
67 typedef const union Argument Argument;
75 void call(struct Thread* thread, Argument argument) {
76 assert(!Stack_isEmpty(&(thread->stack)));
77 Object f = Stack_pop(&(thread->stack));
78 size_t argumentCount = argument.label;
82 switch(f.value.builtin) {
85 assert(argumentCount == 2);
86 assert(!Stack_isEmpty(&(thread->stack)));
87 Object exponent = Stack_pop(&(thread->stack));
88 assert(exponent.type == INTEGER);
89 assert(exponent.value.integer >= 0);
91 assert(!Stack_isEmpty(&(thread->stack)));
92 Object base = Stack_pop(&(thread->stack));
93 assert(base.type == INTEGER);
96 result.type = INTEGER;
97 result.value.integer = 1;
99 while(exponent.value.integer > 0) {
100 result.value.integer *= base.value.integer;
101 exponent.value.integer--;
104 Stack_push(&(thread->stack), result);
109 // TODO Handle multiple arguments
110 assert(!Stack_isEmpty(&(thread->stack)));
111 Object arg = Stack_pop(&(thread->stack));
115 printf("%i", arg.value.integer);
119 printf("%s", arg.value.string);
126 Stack_push(&(thread->stack), BUILTIN_NIL);
140 {% with name='add', operation='+' %}
141 {% include "arithmetic_instruction.c" %}
145 void drop(struct Thread* thread, Argument argument) {
146 assert(!Stack_isEmpty(&(thread->stack)));
147 Object result = Stack_pop(&(thread->stack));
148 Object_deinitialize(&result);
151 void end(struct Thread* thread, Argument argument) {
154 {% with name='idiv', operation='/' %}
155 {% include "arithmetic_instruction.c" %}
158 {% with name='mod', operation='%' %}
159 {% include "arithmetic_instruction.c" %}
162 {% with name='mul', operation='*' %}
163 {% include "arithmetic_instruction.c" %}
166 void neg(struct Thread* thread, Argument argument) {
167 assert(!Stack_isEmpty(&(thread->stack)));
168 Object result = Stack_pop(&(thread->stack));
169 assert(result.type == INTEGER);
171 result.value.integer = -(result.value.integer);
173 Stack_push(&(thread->stack), result);
176 void pop(struct Thread* thread, Argument argument) {
177 char* argumentString = argument.string;
179 assert(!Stack_isEmpty(&(thread->stack)));
180 Object result = Stack_pop(&(thread->stack));
182 if(strcmp(argumentString, "print") == 0) {
184 } else if(strcmp(argumentString, "pow") == 0) {
189 Environment_set(thread->environment, argumentString, result);
192 void push(struct Thread* thread, Argument argument) {
193 char* argumentString = argument.string;
195 if(strcmp(argumentString, "print") == 0) {
197 result.type = BUILTIN;
198 result.value.builtin = PRINT;
199 Stack_push(&(thread->stack), result);
200 } else if(strcmp(argumentString, "pow") == 0) {
202 result.type = BUILTIN;
203 result.value.builtin = POW;
204 Stack_push(&(thread->stack), result);
206 Environment_get_Result result = Environment_get(thread->environment, argumentString);
208 fprintf(stderr, "Variable `%s` not found", argumentString);
211 Stack_push(&(thread->stack), result.result);
215 void push_integer(struct Thread* thread, Argument argument) {
217 result.type = INTEGER;
218 result.value.integer = argument.integer;
220 Stack_push(&(thread->stack), result);
223 void push_string(struct Thread* thread, Argument argument) {
225 result.type = STRING;
226 result.value.string = argument.string;
228 Stack_push(&(thread->stack), result);
231 {% with name='sub', operation='-' %}
232 {% include "arithmetic_instruction.c" %}
236 typedef const struct Instruction Instruction;
238 void (*instruction)(struct Thread*,Argument);
242 {% for label in labels_to_instruction_indices.keys() %}
243 #define LABEL_{{ label }} {{ labels_to_instruction_indices[label] }}
246 const Instruction program[] = {
247 {% for instruction in instruction_list %}
248 (Instruction){ {{ instruction.instruction }}, (Argument){{ generate_argument(instruction) }} },
254 Thread_initialize(&thread, 0);
256 for(; program[thread.program_counter].instruction != end; thread.program_counter++) {
257 program[thread.program_counter].instruction(
259 program[thread.program_counter].argument
263 Thread_deinitialize(&thread);