loa

Virtual machine for the Logic of Assumptions
git clone git://juanmeleiro.mat.br/loa
Log | Files | Refs

gardener.c (4479B)


      1 #include <stdio.h>
      2 
      3 #include "gardener.h"
      4 
      5 #include "stack.h"
      6 #include "tree.h"
      7 #include "schema.h"
      8 
      9 #define ensure(G, COND, ERR) if (!COND) { set_error(G, ERR); return; }
     10 
     11 typedef struct {
     12 	tree *tree;
     13 	schema *schema;
     14 	symbol key;
     15 } frame;
     16 
     17 struct gardener {
     18 	schema *top;
     19 	stack *stack;
     20 	gardener_status error;
     21 	tree *result;
     22 };
     23 
     24 frame*
     25 new_frame(void)
     26 {
     27 	frame *f = malloc(sizeof(frame));
     28 	f->tree = NULL;
     29 	f->schema = NULL;
     30 	f->key = 0;
     31 	return f;
     32 }
     33 
     34 /* GETTERS */
     35 
     36 schema*
     37 get_top(gardener *g)
     38 {
     39 	return g->top;
     40 }
     41 
     42 tree*
     43 get_cur_tree(gardener *g)
     44 {
     45 	if (peek(g->stack))
     46 		return ((frame*)peek(g->stack))->tree;
     47 	else
     48 		return g->result;
     49 }
     50 
     51 symbol
     52 get_cur_constructor(gardener *g)
     53 {
     54 	return get_head(get_cur_tree(g));
     55 }
     56 
     57 schema*
     58 get_cur_schema(gardener *g)
     59 {
     60 	if (peek(g->stack))
     61 		return ((frame*)peek(g->stack))->schema;
     62 	else
     63 		return g->top;
     64 }
     65 
     66 gardener_status
     67 get_error(gardener *g)
     68 {
     69 	return g->error;
     70 }
     71 
     72 tree*
     73 result(gardener *g)
     74 {
     75 	return g->result;
     76 }
     77 
     78 /* SETTERS */
     79 
     80 void
     81 set_error(gardener *g, gardener_status e)
     82 {
     83 	g->error = e;
     84 }
     85 
     86 /* PUBLIC */
     87 
     88 gardener*
     89 new_gardener(schema* s)
     90 {
     91 	gardener *g = malloc(sizeof(gardener));
     92 	g->top = s;
     93 	g->error = false;
     94 	g->stack = new_stack();
     95 	g->result = NULL;
     96 	return g;
     97 }
     98 
     99 
    100 void
    101 fill(gardener* g, symbol key, symbol value)
    102 {
    103 	ensure(g, (get_cur_tree(g) != NULL), NON_START_OP_ON_EMPTY_STACK);
    104 	tree *new = new_leaf(value);
    105 	set_subtree(get_cur_tree(g), key, new);
    106 }
    107 
    108 
    109 void
    110 sub(gardener* g, symbol key, symbol constructor)
    111 {
    112 	schema *cur_schema = get_cur_schema(g);
    113 	tree *cur = get_cur_tree(g);
    114 	ensure(g, (cur != NULL), NON_START_OP_ON_EMPTY_STACK);
    115 	symbol head = get_head(get_cur_tree(g));
    116 
    117 	ensure(g, has_key(cur_schema, head, key), SUB_INVALID_KEY);
    118 	schema *sub_schema = get_subschema(cur_schema, head, key);
    119 	ensure(g, is_constructor(sub_schema, constructor), SUB_WITH_INVALID_CONSTRUCTOR);
    120 	tree *new = new_node(constructor);
    121 
    122 	set_subtree(get_cur_tree(g), key, new);
    123 	frame *f = new_frame();
    124 	f->schema = sub_schema;
    125 	f->tree = new;
    126 	f->key = key;
    127 	push(g->stack, f);
    128 }
    129 
    130 void
    131 sup(gardener* g, symbol constructor, symbol key)
    132 {
    133 	// schema *cur_schema = get_cur_schema(g);
    134 
    135 	// ensure(g, is_constructor(cur_schema, constructor), SUP_WITH_INVALID_CONSTRUCTOR);
    136 	// ensure(g, has_key(cur_schema, constructor, key), SUP_INVALID_KEY);
    137 	ensure(g, (g->result == NULL), OP_AFTER_RESULT);
    138 
    139 	frame *old = pop(g->stack);
    140 
    141 	frame *new = new_frame();
    142 	new->tree = new_node(constructor);
    143 	new->schema = old->schema;
    144 	new->key = old->key;
    145 
    146 	set_subtree(new->tree, key, old->tree);
    147 	if (peek(g->stack)) set_subtree(((frame*)peek(g->stack))->tree, old->key, new->tree);
    148 	// free_frame(old);
    149 	push(g->stack, new);
    150 }
    151 
    152 
    153 void
    154 start(gardener* g, symbol c)
    155 {
    156 	ensure(g, is_empty(g->stack), START_ON_NONEMPTY_STACK);
    157 	ensure(g, (g->result == NULL), OP_AFTER_RESULT);
    158 	ensure(g, is_constructor(g->top, c), START_WITH_INVALID_CONSTRUCTOR);
    159 
    160 	frame *f = new_frame();
    161 	f->tree = new_node(c);
    162 	f->schema = g->top;
    163 
    164 	push(g->stack, f);
    165 }
    166 
    167 
    168 void
    169 done(gardener* g)
    170 {
    171 	frame *f;
    172 	ensure(g, (!is_empty(g->stack)), NON_START_OP_ON_EMPTY_STACK);
    173 	ensure(g, check(get_cur_schema(g), get_cur_tree(g)), DONE_ON_INVALID_TREE);
    174 	f = (frame*) pop(g->stack);
    175 
    176 	if (is_empty(g->stack))
    177 		g->result = f->tree;
    178 }
    179 
    180 void
    181 show(FILE *f, gardener *g)
    182 {
    183 	schema *s = get_cur_schema(g);
    184 	tree *cur = get_cur_tree(g);
    185 	if (cur == NULL) {
    186 		fprintf(f, "schema %s\n", repr(get_name(get_top(g))));
    187 		return;
    188 	}
    189 	symbol head = get_head(cur);
    190 
    191 	fprintf(f, "schema %s\n", repr(get_name(s)));
    192 	fprintf(f, "head %s\n", repr(head));
    193 	size_t num = get_amount_of_required_keys(s, head);
    194 	symbol *keys = get_required_keys(s, head);
    195 	for (size_t i = 0; i < num; i++) {
    196 		if (!get_subtree(cur, keys[i])) {
    197 			if (takes_leaf(s, head, keys[i])) {
    198 				fprintf(f, "symbol %s\n", repr(keys[i]));
    199 			} else {
    200 				fprintf(f, "goal %s %s\n", repr(get_name(get_subschema(s, head, keys[i]))), repr(keys[i]));
    201 			}
    202 		}
    203 	}
    204 	switch (get_error(g)) {
    205 		case SUB_INVALID_KEY:
    206 			fprintf(f, "error SUB_INVALID_KEY");
    207 			break;
    208 		case NON_START_OP_ON_EMPTY_STACK:
    209 			fprintf(f, "error NON_START_OP_ON_EMPTY_STACK");
    210 			break;
    211 		case START_ON_NONEMPTY_STACK:
    212 			fprintf(f, "error START_ON_NONEMPTY_STACK");
    213 			break;
    214 		case OP_AFTER_RESULT:
    215 			fprintf(f, "error OP_AFTER_RESULT");
    216 			break;
    217 		case SUB_WITH_INVALID_CONSTRUCTOR:
    218 			fprintf(f, "error SUB_WITH_INVALID_CONSTRUCTOR");
    219 			break;
    220 		case DONE_ON_INVALID_TREE:
    221 			fprintf(f, "error DONE_ON_INVALID_TREE");
    222 			break;
    223 		case OK:
    224 			break;
    225 	}
    226 }
    227