2019-06-12 01:38:27 -07:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <memory.h>
|
|
|
|
|
|
|
|
struct node_parent {
|
|
|
|
char tag;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct stack {
|
|
|
|
int32_t size;
|
|
|
|
int32_t count;
|
|
|
|
struct node_parent** data;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct node_app {
|
|
|
|
char tag;
|
|
|
|
struct node_parent* left;
|
|
|
|
struct node_parent* right;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct node_num {
|
|
|
|
char tag;
|
|
|
|
int32_t value;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct node_global {
|
|
|
|
char tag;
|
|
|
|
int32_t arity;
|
|
|
|
void (*function)(struct stack*);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct node_ind {
|
|
|
|
char tag;
|
|
|
|
struct node_parent* next;
|
|
|
|
};
|
|
|
|
|
2019-06-12 07:21:51 -07:00
|
|
|
struct node_data {
|
|
|
|
char tag;
|
|
|
|
char ctag;
|
|
|
|
struct node_parent** array;
|
|
|
|
};
|
|
|
|
|
2019-06-12 01:38:27 -07:00
|
|
|
void stack_init(struct stack* stack) {
|
|
|
|
stack->size = 16;
|
|
|
|
stack->count = 0;
|
|
|
|
stack->data = malloc(sizeof(*stack->data) * stack->size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_free(struct stack* stack) {
|
|
|
|
free(stack->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_push(struct stack* stack, struct node_parent* node) {
|
|
|
|
assert(stack->count < stack->size);
|
|
|
|
stack->data[stack->count++] = node;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node_parent* stack_peek(struct stack* stack, int32_t offset) {
|
|
|
|
assert(offset + 1 <= stack->count);
|
|
|
|
return stack->data[stack->count - offset - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node_parent* stack_pop(struct stack* stack) {
|
|
|
|
assert(stack->count > 0);
|
|
|
|
return stack->data[--stack->count];
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_popn(struct stack* stack, int32_t count) {
|
|
|
|
assert(stack->count >= count);
|
|
|
|
stack->count -= count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_update(struct stack* stack, int32_t offset) {
|
|
|
|
assert(stack->count >= offset + 2);
|
2019-06-12 03:33:35 -07:00
|
|
|
struct node_ind* to_replace = (struct node_ind*) stack->data[stack->count - 1 - 1 - offset];
|
|
|
|
to_replace->tag = 3;
|
|
|
|
to_replace->next = stack->data[stack->count - 1];
|
2019-06-12 01:38:27 -07:00
|
|
|
stack->count--;
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_alloc(struct stack* stack, int32_t count) {
|
|
|
|
assert(stack->count + count <= stack->size);
|
|
|
|
for(int32_t i = 0; i < count; i++) {
|
|
|
|
stack->data[stack->count++] = malloc(sizeof(struct node_app));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_slide(struct stack* stack, int32_t count) {
|
|
|
|
assert(stack->count > count);
|
|
|
|
stack->data[stack->count - 1 - count] = stack->data[stack->count - 1];
|
|
|
|
stack->count -= count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_set(struct stack* stack, int32_t index, struct node_parent* parent) {
|
|
|
|
assert(stack->count > index);
|
|
|
|
stack->data[stack->count - 1 - index] = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t stack_size(struct stack* stack) {
|
|
|
|
return stack->count;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node_parent* malloc_node_num(int32_t value) {
|
|
|
|
struct node_num* node = malloc(sizeof(struct node_app));
|
|
|
|
node->tag = 0;
|
|
|
|
node->value = value;
|
|
|
|
return (struct node_parent*) node;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node_parent* malloc_node_app(struct node_parent* left, struct node_parent* right) {
|
|
|
|
struct node_app* node = malloc(sizeof(struct node_app));
|
|
|
|
node->tag = 1;
|
|
|
|
node->left = left;
|
|
|
|
node->right = right;
|
|
|
|
return (struct node_parent*) node;
|
|
|
|
}
|
|
|
|
struct node_parent* malloc_node_global(int32_t arity, void (*function)(struct stack*)) {
|
|
|
|
struct node_global* node = malloc(sizeof(struct node_app));
|
|
|
|
node->tag = 2;
|
|
|
|
node->arity = arity;
|
|
|
|
node->function = function;
|
|
|
|
return (struct node_parent*) node;
|
|
|
|
}
|
|
|
|
struct node_parent* malloc_node_indirect(struct node_parent* target) {
|
|
|
|
struct node_ind* node = malloc(sizeof(struct node_app));
|
|
|
|
node->tag = 3;
|
|
|
|
node->next = target;
|
|
|
|
return (struct node_parent*) node;
|
|
|
|
}
|
2019-06-12 07:21:51 -07:00
|
|
|
struct node_parent* malloc_node_data(char tag, struct node_parent** array) {
|
|
|
|
struct node_data* node = malloc(sizeof(struct node_data));
|
|
|
|
node->tag = 4;
|
|
|
|
node->ctag = tag;
|
|
|
|
node->array = array;
|
|
|
|
return (struct node_parent*) node;
|
|
|
|
}
|
2019-06-12 01:38:27 -07:00
|
|
|
|
|
|
|
void unwind(struct stack* stack) {
|
|
|
|
while(1) {
|
|
|
|
assert(stack_size(stack) != 0);
|
|
|
|
struct node_parent* node = stack_peek(stack, 0);
|
2019-06-12 07:21:51 -07:00
|
|
|
if(node->tag == 0 || node->tag == 4) {
|
2019-06-12 01:38:27 -07:00
|
|
|
return;
|
|
|
|
} else if(node->tag == 1) {
|
|
|
|
stack_push(stack, ((struct node_app*) node)->left);
|
|
|
|
} else if(node->tag == 2) {
|
|
|
|
struct node_global* global = (struct node_global*) node;
|
|
|
|
if(stack->size > global->arity) {
|
2019-06-12 03:33:35 -07:00
|
|
|
struct node_parent* root = stack_peek(stack, global->arity);
|
|
|
|
stack_popn(stack, global->arity + 1);
|
|
|
|
stack_push(stack, root);
|
|
|
|
while(root->tag == 1) {
|
|
|
|
struct node_app* app = (struct node_app*) root;
|
|
|
|
stack_push(stack, app->right);
|
|
|
|
root = app->left;
|
2019-06-12 01:38:27 -07:00
|
|
|
}
|
|
|
|
global->function(stack);
|
|
|
|
} else {
|
|
|
|
stack_popn(stack, stack_size(stack) - 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if(node->tag == 3) {
|
|
|
|
struct node_ind* ind = (struct node_ind*) node;
|
|
|
|
stack_pop(stack);
|
|
|
|
stack_push(stack, ind->next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 07:21:51 -07:00
|
|
|
struct node_parent* pack(struct stack* stack, char tag, int count) {
|
|
|
|
assert(stack->count >= count);
|
|
|
|
struct node_parent** new_array = malloc(sizeof(struct node_parent*) * count);
|
|
|
|
struct node_parent** current_slot = new_array;
|
|
|
|
|
|
|
|
while(count--) {
|
|
|
|
*current_slot = stack_pop(stack);
|
|
|
|
current_slot++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return malloc_node_data(tag, new_array);
|
|
|
|
}
|
|
|
|
|
|
|
|
void split(struct stack* stack, struct node_parent* node, int count) {
|
|
|
|
assert(stack->count > 0);
|
|
|
|
struct node_data* data = (struct node_data*) node;
|
|
|
|
while(count > 0) {
|
|
|
|
stack_push(stack, data->array[count - 1]);
|
|
|
|
count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 01:38:27 -07:00
|
|
|
struct node_parent* eval(struct node_parent* start) {
|
|
|
|
struct stack new_stack;
|
|
|
|
stack_init(&new_stack);
|
|
|
|
stack_push(&new_stack, start);
|
|
|
|
unwind(&new_stack);
|
|
|
|
struct node_parent* final_node = stack_pop(&new_stack);
|
|
|
|
stack_free(&new_stack);
|
|
|
|
return final_node;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void main_supercomb(struct stack* stack);
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
struct node_parent* result = eval(malloc_node_global(0, main_supercomb));
|
2019-06-12 07:21:51 -07:00
|
|
|
if(result->tag == 0) {
|
2019-06-12 08:52:55 -07:00
|
|
|
printf("result was a number: %d\n", ((struct node_num*) result)->value);
|
2019-06-12 07:21:51 -07:00
|
|
|
}
|
2019-06-12 01:38:27 -07:00
|
|
|
}
|