Finish initial draft of runtime posts.

This commit is contained in:
Danila Fedorin 2019-10-30 14:21:13 -07:00
parent 1ed59d9288
commit ec2e448ba2
3 changed files with 195 additions and 60 deletions

31
07/examples/runtime1.c Normal file
View File

@ -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));
}

View File

@ -1,48 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <memory.h>
struct stack; #include "runtime.h"
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;
};
struct node_base* alloc_node() { struct node_base* alloc_node() {
struct node_base* new_node = malloc(sizeof(struct node_app)); struct node_base* new_node = malloc(sizeof(struct node_app));
@ -50,14 +9,38 @@ struct node_base* alloc_node() {
return new_node; return new_node;
} }
struct stack { struct node_app* alloc_app(struct node_base* l, struct node_base* r) {
size_t size; struct node_app* node = (struct node_app*) alloc_node();
size_t count; node->base.tag = NODE_APP;
struct node_base** data; 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) { void stack_init(struct stack* s) {
s->size = 0; s->size = 4;
s->count = 0; s->count = 0;
s->data = malloc(sizeof(*s->data) * s->size); s->data = malloc(sizeof(*s->data) * s->size);
assert(s->data != NULL); 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) { struct node_base* stack_pop(struct stack* s) {
assert(s->count > 0); assert(s->count > 0);
s->count--; return s->data[--s->count];
} }
struct node_base* stack_peek(struct stack* s, size_t o) { 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) { void stack_alloc(struct stack* s, size_t o) {
while(o--) { while(o--) {
struct node_ind* new_node = (struct node_ind*) alloc_node(); stack_push(s, (struct node_base*) alloc_ind(NULL));
new_node->base.tag = NODE_IND;
new_node->next = NULL;
stack_push(s, (struct node_base*) new_node);
} }
} }
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); extern void f_main(struct stack* s);
int main(int argc, char** argv) { int main(int argc, char** argv) {
struct node_global* first_node = (struct node_global*) alloc_node(); struct node_global* first_node = alloc_global(f_main, 0);
first_node->base.tag = NODE_GLOBAL; struct node_base* result = eval((struct node_base*) first_node);
first_node->arity = 0; printf("%d\n", ((struct node_num*) result)->value);
first_node->function = f_main;
eval((struct node_base*) first_node);
} }

69
07/runtime.h Normal file
View File

@ -0,0 +1,69 @@
#pragma once
#include <stdlib.h>
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);