2019-10-26 20:30:29 -07:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
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;
|
2019-10-30 00:19:56 -07:00
|
|
|
int32_t arity;
|
2019-10-26 20:30:29 -07:00
|
|
|
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() {
|
2019-10-30 00:19:56 -07:00
|
|
|
struct node_base* new_node = malloc(sizeof(struct node_app));
|
2019-10-26 20:30:29 -07:00
|
|
|
assert(new_node != NULL);
|
|
|
|
return new_node;
|
|
|
|
}
|
2019-10-30 00:19:56 -07:00
|
|
|
|
|
|
|
struct stack {
|
|
|
|
size_t size;
|
|
|
|
size_t count;
|
|
|
|
struct node_base** data;
|
|
|
|
};
|
|
|
|
|
|
|
|
void stack_init(struct stack* s) {
|
|
|
|
s->size = 0;
|
|
|
|
s->count = 0;
|
|
|
|
s->data = malloc(sizeof(*s->data) * s->size);
|
|
|
|
assert(s->data != NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_free(struct stack* s) {
|
|
|
|
free(s->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_push(struct stack* s, struct node_base* n) {
|
|
|
|
while(s->count >= s->size) {
|
|
|
|
s->data = realloc(s->data, sizeof(*s->data) * (s->size *= 2));
|
|
|
|
assert(s->data != NULL);
|
|
|
|
}
|
|
|
|
s->data[s->count++] = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node_base* stack_pop(struct stack* s) {
|
|
|
|
assert(s->count > 0);
|
|
|
|
s->count--;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node_base* stack_peek(struct stack* s, size_t o) {
|
|
|
|
assert(s->count > o);
|
|
|
|
return s->data[s->count - o - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_popn(struct stack* s, size_t n) {
|
|
|
|
assert(s->count >= n);
|
|
|
|
s->count -= n;
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_slide(struct stack* s, size_t n) {
|
|
|
|
assert(s->count > n);
|
|
|
|
s->data[s->count - n - 1] = s->data[s->count - 1];
|
|
|
|
s->count -= n;
|
|
|
|
}
|
|
|
|
|
|
|
|
void stack_update(struct stack* s, size_t o) {
|
|
|
|
assert(s->count > o + 1);
|
|
|
|
struct node_ind* ind = (struct node_ind*) s->data[s->count - o - 2];
|
|
|
|
ind->base.tag = NODE_IND;
|
|
|
|
ind->next = s->data[s->count -= 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void eval(struct node_base* n);
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|