loa

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

zen.c (4015B)


      1 #include "zen.h"
      2 #include "schema.h"
      3 #include "gardener.h"
      4 
      5 typedef enum {
      6 	OP_START,
      7 	OP_FILL,
      8 	OP_DONE,
      9 	OP_SUB,
     10 	OP_SUP,
     11 	OP_NOOP
     12 } op_type;
     13 
     14 struct garden {
     15 	gardener *gardener;
     16 	garden_status status;
     17 	op_type next;
     18 	symbol a;
     19 	symbol b;
     20 };
     21 
     22 char*
     23 next_symbol_meaning(garden_status s, op_type next)
     24 {
     25 	if (s == ERROR) return "enlightenment";
     26 	if (s == WAITING_FOR_OP) return "operation";
     27 
     28 	switch (next) {
     29 		case OP_NOOP:
     30 			return "nothing";
     31 		case OP_FILL:
     32 			if (s == WAITING_FOR_B)
     33 				return "key";
     34 			else
     35 				return "value";
     36 		case OP_START:
     37 			return "constructor";
     38 		case OP_DONE:
     39 			return "enlightenment";
     40 		case OP_SUB:
     41 			if (s == WAITING_FOR_B)
     42 				return "key";
     43 			else
     44 				return "constructor";
     45 		case OP_SUP:
     46 			if (s == WAITING_FOR_B)
     47 				return "constructor";
     48 			else
     49 				return "key";
     50 	}
     51 	return "enlightenment";
     52 }
     53 
     54 void
     55 display_garden(FILE *f, garden *g)
     56 {
     57 	show(f, g->gardener);
     58 	fprintf(f, "\nWaiting for %s.\n",
     59 	        next_symbol_meaning(g->status, g->next));
     60 }
     61 
     62 garden*
     63 new_garden(schema* s)
     64 {
     65 	garden *g = malloc(sizeof(garden));
     66 	g->gardener = new_gardener(s);
     67 	g->status = WAITING_FOR_OP;
     68 	return g;
     69 }
     70 
     71 garden_status
     72 get_status(garden *g)
     73 {
     74 	return g->status;
     75 }
     76 
     77 op_type
     78 symbol_to_op(symbol s)
     79 {
     80 	if (s == intern("start") || s == intern("@"))
     81 		return OP_START;
     82 	else if (s == intern("fill") || s == intern("!"))
     83 		return OP_FILL;
     84 	else if (s == intern("done") || s == intern("}"))
     85 		return OP_DONE;
     86 	else if (s == intern("sub") || s == intern("{"))
     87 		return OP_SUB;
     88 	else if (s == intern("sup") || s == intern("^"))
     89 		return OP_SUP;
     90 	else
     91 		return OP_NOOP;
     92 }
     93 
     94 garden_status
     95 next_status_for_op(op_type op)
     96 {
     97 	switch (op) {
     98 		case OP_NOOP:
     99 			return ERROR;
    100 		case OP_START:
    101 			return WAITING_FOR_A;
    102 		case OP_FILL:
    103 			return WAITING_FOR_B;
    104 		case OP_DONE:
    105 			return WAITING_FOR_OP;
    106 		case OP_SUB:
    107 			return WAITING_FOR_B;
    108 		case OP_SUP:
    109 			return WAITING_FOR_B;
    110 	}
    111 	return ERROR;
    112 }
    113 
    114 void
    115 end_op(garden *g)
    116 {
    117 	if (get_error(g->gardener) != OK)
    118 		g->status = ERROR;
    119 	else
    120 		g->status = WAITING_FOR_OP;
    121 }
    122 
    123 void
    124 exec_op(garden *g)
    125 {
    126 	switch (g->next) {
    127 
    128 		case OP_START:
    129 			start(g->gardener, g->a);
    130 			end_op(g);
    131 			break;
    132 
    133 		case OP_FILL:
    134 			fill(g->gardener, g->b, g->a);
    135 			end_op(g);
    136 			break;
    137 
    138 		case OP_NOOP:
    139 			g->status = ERROR;
    140 			break;
    141 
    142 		case OP_DONE:
    143 			done(g->gardener);
    144 			end_op(g);
    145 			break;
    146 
    147 		case OP_SUB:
    148 			sub(g->gardener, g->b, g->a);
    149 			end_op(g);
    150 			break;
    151 
    152 		case OP_SUP:
    153 			sup(g->gardener, g->b, g->a);
    154 			end_op(g);
    155 			break;
    156 	}
    157 }
    158 
    159 void
    160 check_b(garden *g)
    161 {
    162 	switch (g->next) {
    163 
    164 		case OP_START:
    165 			g->status = ERROR;
    166 			break;
    167 
    168 		case OP_NOOP:
    169 			g->status = ERROR;
    170 			break;
    171 
    172 		case OP_FILL:
    173 			if (has_key(get_cur_schema(g->gardener),
    174 			            get_cur_constructor(g->gardener),
    175 			            g->b) &&
    176 			    takes_leaf(get_cur_schema(g->gardener),
    177 			               get_cur_constructor(g->gardener),
    178 			               g->b)) {
    179 				g->status = WAITING_FOR_A;
    180 			} else {
    181 				g->status = ERROR;
    182 			}
    183 			break;
    184 
    185 		case OP_DONE:
    186 			g->status = ERROR;
    187 			break;
    188 
    189 		case OP_SUB:
    190 			if (has_key(get_cur_schema(g->gardener),
    191 			            get_cur_constructor(g->gardener),
    192 			            g->b)) {
    193 				g->status = WAITING_FOR_A;
    194 			} else {
    195 				g->status = ERROR;
    196 			}
    197 			break;
    198 
    199 		case OP_SUP:
    200 			if (is_constructor(get_cur_schema(g->gardener),
    201 			                   g->b)) {
    202 			    g->status = WAITING_FOR_A;
    203 			} else {
    204 				g->status = ERROR;
    205 			}
    206 	}
    207 }
    208 
    209 bool
    210 takes_args(op_type op)
    211 {
    212 	switch (op) {
    213 		case OP_FILL:
    214 		case OP_SUB:
    215 		case OP_SUP:
    216 		case OP_START:
    217 			return true;
    218 		case OP_NOOP:
    219 		case OP_DONE:
    220 			/* FALLTHROUGH */
    221 	}
    222 	return false;
    223 }
    224 
    225 void
    226 instruct(garden *g, symbol s)
    227 {
    228 	(void)s;
    229 	switch (g->status) {
    230 
    231 		case WAITING_FOR_OP:
    232 			g->next = symbol_to_op(s);
    233 			if (takes_args(g->next)) {
    234 				g->status = next_status_for_op(g->next);
    235 			} else {
    236 				exec_op(g);
    237 			}
    238 			break;
    239 
    240 		case WAITING_FOR_A:
    241 			g->a = s;
    242 			exec_op(g);
    243 			break;
    244 			
    245 		case WAITING_FOR_B:
    246 			g->b = s;
    247 			check_b(g);
    248 			break;
    249 
    250 		case ERROR:
    251 			break;
    252 
    253 	}
    254 }