loa

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

schema.c (2961B)


      1 #include <assert.h>
      2 #include <stdio.h>
      3 
      4 #include "schema.h"
      5 
      6 #include "assoc.h"
      7 
      8 struct schema {
      9 	assoc *constructors;
     10 	bool (*checker)(tree*);
     11 	symbol name;
     12 };
     13 
     14 struct schema _LEAF = { NULL };
     15 struct schema *LEAF = &_LEAF;
     16 
     17 struct constructor {
     18 	assoc *subschemas;
     19 };
     20 
     21 typedef struct constructor constructor;
     22 
     23 /* CONSTRUCTORS */
     24 
     25 schema*
     26 new_schema(symbol name)
     27 {
     28 	schema *s = malloc(sizeof(schema));
     29 	s->constructors = new_assoc();
     30 	s->checker = NULL;
     31 	s->name = name;
     32 	return s;
     33 }
     34 
     35 constructor*
     36 new_constructor()
     37 {
     38 	constructor *c = malloc(sizeof(constructor));
     39 	c->subschemas = new_assoc();
     40 	return c;
     41 }
     42 
     43 
     44 /* GETTERS AND SETTERS */
     45 
     46 symbol
     47 get_name(schema*s)
     48 {
     49 	return s->name;
     50 }
     51 
     52 bool
     53 is_constructor(schema* s, symbol c)
     54 {
     55 	return assoc_get(s->constructors, c) != NULL;
     56 }
     57 
     58 constructor*
     59 get_constructor(schema* s, symbol c)
     60 {
     61 	assert(is_constructor(s, c));
     62 	return (constructor*) assoc_get(s->constructors, c);
     63 }
     64 
     65 schema*
     66 get_subschema(schema* s, symbol c, symbol k)
     67 {
     68 	assert(is_constructor(s, c));
     69 	return (schema*) assoc_get(get_constructor(s, c)->subschemas, k);
     70 }
     71 
     72 bool
     73 has_key(schema *s, symbol c, symbol k)
     74 {
     75 	assert(is_constructor(s, c));
     76 	return (assoc_get(get_constructor(s, c)->subschemas, k) != NULL);
     77 }
     78 
     79 bool
     80 takes_leaf(schema *s, symbol c, symbol k)
     81 {
     82 	assert(is_constructor(s, c));
     83 	return (assoc_get(get_constructor(s, c)->subschemas, k) == LEAF);
     84 }
     85 
     86 void
     87 set_check_function(schema* s, bool (*f)(tree*))
     88 {
     89 	s->checker = f;
     90 }
     91 
     92 bool (*get_check_function(schema* s))(tree*)
     93 {
     94 	return s->checker;
     95 }
     96 
     97 size_t
     98 get_amount_of_required_keys(schema *s, symbol c)
     99 {
    100 	return get_amount_of_keys(get_constructor(s, c)->subschemas);
    101 }
    102 
    103 symbol*
    104 get_required_keys(schema *s, symbol c)
    105 {
    106 	return get_keys(get_constructor(s, c)->subschemas);
    107 }
    108 
    109 /* REST OF INTERFACE */
    110 
    111 void
    112 add_constructor(schema* s, symbol c)
    113 {
    114 	assert(s);
    115 	assert(!is_constructor(s, c));
    116 	constructor *sub = new_constructor();
    117 	assoc_set(s->constructors, c, sub);
    118 }
    119 
    120 void
    121 assign_subschema(schema* s, symbol c, symbol k, schema* sub)
    122 {
    123 	assert(is_constructor(s, c));
    124 	assoc_set(get_constructor(s, c)->subschemas, k, sub);
    125 }
    126 
    127 void
    128 mark_as_leaf(schema* s, symbol c, symbol k)
    129 {
    130 	assert(is_constructor(s, c));
    131 	assoc_set(get_constructor(s, c)->subschemas, k, LEAF);
    132 }
    133 
    134 bool
    135 check(schema* s, tree* t)
    136 {
    137 	if (!s) return true;
    138 	if (!t) return false;
    139 	if (s == LEAF && is_leaf(t)) return true;
    140 
    141 	symbol head = get_head(t);
    142 	if (!is_constructor(s, head)) return false;
    143 
    144 	bool good = true;
    145 
    146 	size_t lim = get_amount_of_keys(get_constructor(s, head)->subschemas);
    147 	symbol *keys = get_keys(get_constructor(s, head)->subschemas);
    148 
    149 	for (size_t i = 0; i < lim && good; i++) {
    150 		tree *subtree = get_subtree(t, keys[i]);
    151 		schema *subschema = get_subschema(s, head, keys[i]);
    152 		assert(subschema != NULL);
    153 
    154 		if (subtree)
    155 			good &= (check(subschema, get_subtree(t, keys[i])));
    156 		else
    157 			return false;
    158 	}
    159 
    160 	bool (*checker)(tree*) = get_check_function(s);
    161 	if (checker) good &= checker(t);
    162 
    163 	return good;
    164 }
    165 
    166