X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=templates%2Fprogram2.c;fp=templates%2Fprogram2.c;h=6e21ce07d13d26937a3427bf7558ed999e108472;hp=0000000000000000000000000000000000000000;hb=c45c61444aae3df328e4dc84acf7e31e58a1f64e;hpb=268127b1e817f0dfe298d66e6cacdb0bb83139fb diff --git a/templates/program2.c b/templates/program2.c new file mode 100644 index 0000000..6e21ce0 --- /dev/null +++ b/templates/program2.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include + +enum Type; +typedef enum Type Type; +enum Type { + BUILTIN, + INTEGER, + STRING +}; + +enum Builtin; +typedef enum Builtin Builtin; +enum Builtin { + NIL, + PRINT +}; + +union Value; +typedef union Value Value; +union Value { + Builtin builtin; + char* string; + int32_t integer; +}; + +struct Object; +typedef struct Object Object; +struct Object { + Type type; + Value value; +}; + +#define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL } + +void Object_deinitialize(Object* self) { +} + +{% include "stack.c" %} + +struct Thread; +typedef struct Thread Thread; +struct Thread { + Stack stack; + size_t program_counter; +}; + +void Thread_initialize(Thread* self, size_t program_counter) { + Stack_initialize(&(self->stack)); + self->program_counter = program_counter; +} + +void Thread_deinitialize(Thread* self) { + Stack_deinitialize(&(self->stack)); +} + +union Argument; +typedef const union Argument Argument; +union Argument { + size_t label; + void* pointer; + char* string; + int32_t integer; +}; + +void call(struct Thread* thread, const union Argument argument) { + assert(!Stack_isEmpty(&(thread->stack))); + Object f = Stack_pop(&(thread->stack)); + + switch(f.type) { + case BUILTIN: + switch(f.value.builtin) { + case PRINT: + { + // TODO Handle multiple arguments + assert(!Stack_isEmpty(&(thread->stack))); + Object arg = Stack_pop(&(thread->stack)); + + switch(arg.type) { + case INTEGER: + printf("%i", arg.value.integer); + break; + + case STRING: + printf("%s", arg.value.string); + break; + + default: + assert(0); + } + + Stack_push(&(thread->stack), BUILTIN_NIL); + } + break; + + default: + assert(false); + } + break; + + default: + assert(false); + } +} + +void drop(struct Thread* thread, const union Argument argument) { + assert(!Stack_isEmpty(&(thread->stack))); + Object result = Stack_pop(&(thread->stack)); + Object_deinitialize(&result); +} + +void end(struct Thread* thread, const union Argument argument) { +} + +void push(struct Thread* thread, const union Argument argument) { + char* argumentString = argument.string; + + Object result; + + if(strcmp(argumentString, "print") == 0) { + result.type = BUILTIN; + result.value.builtin = PRINT; + } else { + assert(false); + } + + Stack_push(&(thread->stack), result); +} + +void push_integer(struct Thread* thread, const union Argument argument) { + Object result; + result.type = INTEGER; + result.value.integer = argument.integer; + + Stack_push(&(thread->stack), result); +} + +void push_string(struct Thread* thread, const union Argument argument) { + Object result; + result.type = STRING; + result.value.string = argument.string; + + Stack_push(&(thread->stack), result); +} + +struct Instruction; +typedef const struct Instruction Instruction; +struct Instruction { + void (*instruction)(struct Thread*,const union Argument); + Argument argument; +}; + +{% for label in labels_to_instruction_indices.keys() %} +#define LABEL_{{ label }} {{ labels_to_instruction_indices[label] }} +{% endfor %} + +const Instruction program[] = { +{% for instruction in instruction_list %} + (Instruction){ {{ instruction.instruction }}, (Argument){{ generate_argument(instruction) }} }, +{% endfor %} +}; + +int main() { + Thread thread; + Thread_initialize(&thread, 0); + + for(; program[thread.program_counter].instruction != end; thread.program_counter++) { + program[thread.program_counter].instruction( + &thread, + program[thread.program_counter].argument + ); + } + + Thread_deinitialize(&thread); + + return 0; +}