diff --git a/07/examples/runtime1.c b/07/examples/runtime1.c new file mode 100644 index 0000000..0157051 --- /dev/null +++ b/07/examples/runtime1.c @@ -0,0 +1,31 @@ +#include "../runtime.h" + +void f_add(struct stack* s) { + struct node_num* left = (struct node_num*) eval(stack_peek(s, 0)); + struct node_num* right = (struct node_num*) eval(stack_peek(s, 1)); + stack_push(s, (struct node_base*) alloc_num(left->value + right->value)); +} + +void f_main(struct stack* s) { + // PushInt 320 + stack_push(s, (struct node_base*) alloc_num(320)); + + // PushInt 6 + stack_push(s, (struct node_base*) alloc_num(6)); + + // PushGlobal f_add (the function for +) + stack_push(s, (struct node_base*) alloc_global(f_add, 2)); + + struct node_base* left; + struct node_base* right; + + // MkApp + left = stack_pop(s); + right = stack_pop(s); + stack_push(s, (struct node_base*) alloc_app(left, right)); + + // MkApp + left = stack_pop(s); + right = stack_pop(s); + stack_push(s, (struct node_base*) alloc_app(left, right)); +} diff --git a/07/runtime.c b/07/runtime.c index 27f3848..6ee3cd6 100644 --- a/07/runtime.c +++ b/07/runtime.c @@ -1,48 +1,7 @@ #include -#include #include - -struct stack; - -enum node_tag { - NODE_APP, - NODE_NUM, - NODE_GLOBAL, - NODE_IND, - NODE_PACK -}; - -struct node_base { - enum node_tag tag; -}; - -struct node_app { - struct node_base base; - struct node_base* left; - struct node_base* right; -}; - -struct node_num { - struct node_base base; - int32_t value; -}; - -struct node_global { - struct node_base base; - int32_t arity; - void (*function)(struct stack*); -}; - -struct node_ind { - struct node_base base; - struct node_base* next; -}; - -struct node_data { - struct node_base base; - int8_t tag; - struct node_base** array; -}; +#include +#include "runtime.h" struct node_base* alloc_node() { struct node_base* new_node = malloc(sizeof(struct node_app)); @@ -50,14 +9,38 @@ struct node_base* alloc_node() { return new_node; } -struct stack { - size_t size; - size_t count; - struct node_base** data; -}; +struct node_app* alloc_app(struct node_base* l, struct node_base* r) { + struct node_app* node = (struct node_app*) alloc_node(); + node->base.tag = NODE_APP; + node->left = l; + node->right = r; + return node; +} + +struct node_num* alloc_num(int32_t n) { + struct node_num* node = (struct node_num*) alloc_node(); + node->base.tag = NODE_NUM; + node->value = n; + return node; +} + +struct node_global* alloc_global(void (*f)(struct stack*), int32_t a) { + struct node_global* node = (struct node_global*) alloc_node(); + node->base.tag = NODE_GLOBAL; + node->arity = a; + node->function = f; + return node; +} + +struct node_ind* alloc_ind(struct node_base* n) { + struct node_ind* node = (struct node_ind*) alloc_node(); + node->base.tag = NODE_IND; + node->next = n; + return node; +} void stack_init(struct stack* s) { - s->size = 0; + s->size = 4; s->count = 0; s->data = malloc(sizeof(*s->data) * s->size); assert(s->data != NULL); @@ -77,7 +60,7 @@ void stack_push(struct stack* s, struct node_base* n) { struct node_base* stack_pop(struct stack* s) { assert(s->count > 0); - s->count--; + return s->data[--s->count]; } struct node_base* stack_peek(struct stack* s, size_t o) { @@ -105,21 +88,73 @@ void stack_update(struct stack* s, size_t o) { void stack_alloc(struct stack* s, size_t o) { while(o--) { - struct node_ind* new_node = (struct node_ind*) alloc_node(); - new_node->base.tag = NODE_IND; - new_node->next = NULL; - stack_push(s, (struct node_base*) new_node); + stack_push(s, (struct node_base*) alloc_ind(NULL)); } } -void eval(struct node_base* n); +void stack_pack(struct stack* s, size_t n, int8_t t) { + assert(s->count >= n); + + struct node_base** data = malloc(sizeof(*data) * n); + assert(data != NULL); + memcpy(data, &s->data[s->count - 1 - n], n * sizeof(*data)); + + struct node_data* new_node = (struct node_data*) alloc_node(); + new_node->array = data; + new_node->base.tag = NODE_DATA; + new_node->tag = t; + + stack_popn(s, n); + stack_push(s, (struct node_base*) new_node); +} + +void stack_split(struct stack* s, size_t n) { + struct node_data* node = (struct node_data*) stack_pop(s); + for(size_t i = 0; i < n; i++) { + stack_push(s, node->array[i]); + } +} + +void unwind(struct stack* s) { + while(1) { + struct node_base* peek = stack_peek(s, 0); + if(peek->tag == NODE_APP) { + struct node_app* n = (struct node_app*) peek; + stack_push(s, n->left); + } else if(peek->tag == NODE_GLOBAL) { + struct node_global* n = (struct node_global*) peek; + assert(s->count > n->arity); + + for(size_t i = 1; i <= n->arity; i++) { + s->data[s->count - i] + = ((struct node_app*) s->data[s->count - i - 1])->right; + } + + n->function(s); + } else if(peek->tag == NODE_IND) { + struct node_ind* n = (struct node_ind*) peek; + stack_pop(s); + stack_push(s, n->next); + } else { + break; + } + } +} + +struct node_base* eval(struct node_base* n) { + struct stack program_stack; + stack_init(&program_stack); + stack_push(&program_stack, n); + unwind(&program_stack); + struct node_base* result = stack_pop(&program_stack); + stack_free(&program_stack); + return result; +} extern void f_main(struct stack* s); int main(int argc, char** argv) { - struct node_global* first_node = (struct node_global*) alloc_node(); - first_node->base.tag = NODE_GLOBAL; - first_node->arity = 0; - first_node->function = f_main; - eval((struct node_base*) first_node); + struct node_global* first_node = alloc_global(f_main, 0); + struct node_base* result = eval((struct node_base*) first_node); + printf("%d\n", ((struct node_num*) result)->value); } diff --git a/07/runtime.h b/07/runtime.h new file mode 100644 index 0000000..2a585b1 --- /dev/null +++ b/07/runtime.h @@ -0,0 +1,69 @@ +#pragma once +#include + +struct stack; + +enum node_tag { + NODE_APP, + NODE_NUM, + NODE_GLOBAL, + NODE_IND, + NODE_DATA +}; + +struct node_base { + enum node_tag tag; +}; + +struct node_app { + struct node_base base; + struct node_base* left; + struct node_base* right; +}; + +struct node_num { + struct node_base base; + int32_t value; +}; + +struct node_global { + struct node_base base; + int32_t arity; + void (*function)(struct stack*); +}; + +struct node_ind { + struct node_base base; + struct node_base* next; +}; + +struct node_data { + struct node_base base; + int8_t tag; + struct node_base** array; +}; + +struct node_base* alloc_node(); +struct node_app* alloc_app(struct node_base* l, struct node_base* r); +struct node_num* alloc_num(int32_t n); +struct node_global* alloc_global(void (*f)(struct stack*), int32_t a); +struct node_ind* alloc_ind(struct node_base* n); + +struct stack { + size_t size; + size_t count; + struct node_base** data; +}; + +void stack_free(struct stack* s); +void stack_push(struct stack* s, struct node_base* n); +struct node_base* stack_pop(struct stack* s); +struct node_base* stack_peek(struct stack* s, size_t o); +void stack_popn(struct stack* s, size_t n); +void stack_slide(struct stack* s, size_t n); +void stack_update(struct stack* s, size_t o); +void stack_alloc(struct stack* s, size_t o); +void stack_pack(struct stack* s, size_t n, int8_t t); +void stack_split(struct stack* s, size_t n); + +struct node_base* eval(struct node_base* n);