loa

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

commit 44aaa0b9491720601ab0e600badec6a04b66941e
parent 610c76f97cbccfd503c0b74882b5eabf1279517f
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date:   Thu, 11 Apr 2024 16:52:12 -0300

Add gardener module

Diffstat:
Mcoding/assoc.c | 19+++++++++++++++++++
Mcoding/assoc.h | 2++
Mcoding/assoc.test.c | 54+++++++++++++++++++++++++++++++++++++++++++++++++++++-
Acoding/gardener.c | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dcoding/gardener.c.wip | 64----------------------------------------------------------------
Mcoding/gardener.h | 2++
Acoding/gardener.test.c | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acoding/schema.c | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcoding/schema.h | 19++++++++++++++++++-
Acoding/schema.test.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acoding/stack.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Acoding/stack.h | 10++++++++++
Acoding/stack.test.c | 25+++++++++++++++++++++++++
Mcoding/test.sh | 13++++++++-----
Mcoding/tree.c | 9+++++++++
Mcoding/tree.h | 11++++++-----
16 files changed, 681 insertions(+), 76 deletions(-)

diff --git a/coding/assoc.c b/coding/assoc.c @@ -64,6 +64,25 @@ assoc_get(assoc* a, symbol s) return get(a->cells, s); } +size_t +get_amount_of_keys(assoc* a) +{ + size_t amount; + struct cell *c; + for (amount = 0, c = a->cells; c; c = c->next, amount++); + return amount; +} + +symbol* +get_keys(assoc* a) +{ + struct cell *c; + size_t i; + symbol *res = malloc(sizeof(symbol)*get_amount_of_keys(a)); + for (i = 0, c = a->cells; c; res[i++] = c->key, c = c->next); + return res; +} + void free_cells(struct cell *c) { diff --git a/coding/assoc.h b/coding/assoc.h @@ -10,3 +10,5 @@ assoc* new_assoc(void); void* assoc_get(assoc*, symbol); void assoc_set(assoc*, symbol, void*); void free_assoc(assoc*); +size_t get_amount_of_keys(assoc*); +symbol* get_keys(assoc*); diff --git a/coding/assoc.test.c b/coding/assoc.test.c @@ -12,14 +12,66 @@ test_get_after_set_is_id() assoc *a = new_assoc(); assoc_set(a, k, (void*)123); - bool res = assoc_get(a, k) == (void*)123; + bool res = (assoc_get(a, k) == (void*)123); free_assoc(a); return res; } +bool +test_amount_of_keys() +{ + symbol k = intern("k"); + symbol l = intern("l"); + symbol m = intern("m"); + assoc *a = new_assoc(); + + assoc_set(a, k, (void*)1); + assoc_set(a, l, (void*)2); + assoc_set(a, m, (void*)3); + + bool res = (get_amount_of_keys(a) == 3); + + free_assoc(a); + + return res; +} + +bool +test_keys() +{ + symbol k = intern("k"); + symbol l = intern("l"); + symbol m = intern("m"); + assoc *a = new_assoc(); + + assoc_set(a, k, (void*)1); + assoc_set(a, l, (void*)2); + assoc_set(a, m, (void*)3); + + symbol *keys = get_keys(a); + size_t num_keys = get_amount_of_keys(a); + + bool res = true; + for (size_t i = 0; i < num_keys; i++) { + res &= ( + keys[i] == k || + keys[i] == l || + keys[i] == m + ); + + res &= (assoc_get(a, keys[i]) != NULL); + } + + free_assoc(a); + + return res; +} + int main() { assert(test_get_after_set_is_id()); + assert(test_amount_of_keys()); + assert(test_keys()); return 0; } diff --git a/coding/gardener.c b/coding/gardener.c @@ -0,0 +1,124 @@ +#include <assert.h> + +#include "gardener.h" + +#include "stack.h" +#include "tree.h" +#include "schema.h" + +struct gardener { + schema *top; + stack *treestack; + stack *schemastack; + bool error; +}; + +/* GETTERS */ + +schema* +get_top(gardener *g) +{ + return g->top; +} + +tree* +get_cur_tree(gardener *g) +{ + return peek(g->treestack); +} + +schema* +get_cur_schema(gardener *g) +{ + return peek(g->schemastack); +} + +bool +get_error(gardener *g) +{ + return g->error; +} + +/* SETTERS */ + +void +set_error(gardener *g) +{ + g->error = true; +} + +/* PUBLIC */ + +gardener* +new_gardener(schema* s) +{ + gardener *g = malloc(sizeof(gardener)); + g->top = s; + g->error = false; + g->treestack = new_stack(); + g->schemastack = new_stack(); + push(g->schemastack, g->top); + return g; +} + + +void +fill(gardener* g, symbol key, symbol value) +{ + tree *new = new_leaf(value); + set_subtree(get_cur_tree(g), key, new); +} + + +void +sub(gardener* g, symbol key, symbol constructor) +{ + + schema *cur_schema = get_cur_schema(g); + symbol head = get_head(get_cur_tree(g)); + assert(has_key(cur_schema, head, key)); + schema *sub_schema = get_subschema(cur_schema, head, key); + tree *new = new_node(constructor); + + set_subtree(get_cur_tree(g), key, new); + push(g->schemastack, sub_schema); + push(g->treestack, new); +} + + +void +start(gardener* g, symbol c) +{ + assert(is_empty(g->treestack)); + tree *t = new_node(c); + push(g->treestack, t); +} + + +bool +done(gardener* g) +{ + bool res = check(get_cur_schema(g), get_cur_tree(g)); + + if (res) { + if (!is_empty(g->treestack)) + pop(g->treestack); + } else { + set_error(g); + } + return res; +} + +/* +void +sup(gardener* g, symbol key, symbol constructor) +{ + if (at_ground(g)) { + tree *sup = new_node(constructor); + set(sup, key, get_cur_tree(g)); + set_cur_tree(g, sup); + } else { + set_error(g); + } +} +*/ diff --git a/coding/gardener.c.wip b/coding/gardener.c.wip @@ -1,64 +0,0 @@ -#include "gardener.h" - -#include "tree.h" -#include "schema.h" - -struct gardener { -}; - -schema* get_schema (gardener *g); -void set_schema (gardener *g, schema *s); -schema* push_schema (gardener *g); -schema* pop_schema (gardener *g); -tree* get_tree (gardener *g); -void set_tree (gardener *g, tree *t); -tree* pop_tree (gardener *g); -void push_tree (gardener *g); -void set_error (gardener *g); -bool at_ground (gardener *g); - -/* PUBLIC */ - -gardener* new_gardener(schema*); - -void -fill(gardener* g, symbol key, symbol value) -{ - tree *new = new_leaf(value); - set(get_cur_tree(g), key, new); -} - -void -sub(gardener* g, symbol key, symbol constructor) -{ - tree *new = new_node(constructor); - set(get_cur_tree(g), key, new); - push_cur_tree(g); - push_schema(g, get_subschema(peek_schema(g), key)); - set_cur_tree(g, new); -} - -bool -done(gardener* g) -{ - schema *s = pop_schema(g); - if (check(s, get_cur_tree(g))) { - set_error(g); - return false; - } else { - set_cur_tree(g, pop_tree(g)); - } -} - -void -sup(gardener* g, symbol key, symbol constructor) -{ - if (at_ground(g)) { - tree *sup = new_node(constructor); - set(sup, key, get_cur_tree(g)); - set_cur_tree(g, sup); - } else { - set_error(g); - } -} - diff --git a/coding/gardener.h b/coding/gardener.h @@ -4,8 +4,10 @@ typedef struct gardener gardener; gardener* new_gardener(schema*); +bool get_error(gardener*); void fill(gardener*, symbol key, symbol value); void sub(gardener*, symbol key, symbol constructor); bool done(gardener*); void sup(gardener*, symbol key, symbol constructor); +void start(gardener*, symbol constructor); diff --git a/coding/gardener.test.c b/coding/gardener.test.c @@ -0,0 +1,158 @@ +#include <stdio.h> +#include <stdbool.h> +#include <assert.h> + +#include "symbol.h" +#include "schema.h" +#include "gardener.h" + +bool +test_empty_constructor_success(void) +{ + bool res = true; + + symbol c = intern("c"); + schema *s = new_schema(); + add_constructor(s, c); + + gardener *g = new_gardener(s); + start(g, c); + + res &= done(g); + res &= !get_error(g); + + return res; +} + +bool +test_empty_constructor_empty_tree_fail(void) +{ + bool res = true; + + symbol c = intern("c"); + schema *s = new_schema(); + add_constructor(s, c); + gardener *g = new_gardener(s); + + res &= !done(g); + res &= get_error(g); + return res; +} + +bool +test_double_deep_schema_fail(void) +{ + bool res = true; + + schema *s = new_schema(); + symbol c = intern("c"); + add_constructor(s, c); + + schema *t = new_schema(); + symbol d = intern("d"); + add_constructor(t, d); + + symbol k = intern("k"); + assign_subschema(s, c, k, t); + + gardener *g = new_gardener(s); + start(g, c); + + res &= !done(g); + res &= get_error(g); + + return res; +} + +bool +test_double_deep_schema_success(void) +{ + bool res = true; + + symbol c = intern("c"); + symbol d = intern("d"); + symbol k = intern("k"); + + schema *s = new_schema(); + add_constructor(s, c); + + schema *t = new_schema(); + add_constructor(t, d); + + assign_subschema(s, c, k, t); + + gardener *g = new_gardener(s); + start(g, c); + sub(g, k, d); + + res &= done(g); + res &= !get_error(g); + + return res; +} + +bool +test_triple_deep_schema_fail(void) +{ + bool res = true; + + symbol c = intern("c"); + symbol d = intern("d"); + symbol k = intern("k"); + + schema *s = new_schema(); + add_constructor(s, c); + + schema *t = new_schema(); + add_constructor(t, d); + + assign_subschema(s, c, k, t); + assign_subschema(t, d, k, LEAF); + + gardener *g = new_gardener(s); + start(g, c); + sub(g, k, d); + + res &= !done(g); + res &= get_error(g); + + return res; +} + +bool +test_triple_deep_schema_success(void) +{ + bool res = true; + + schema *s = new_schema(); + symbol c = intern("c"); + add_constructor(s, c); + + schema *t = new_schema(); + symbol d = intern("d"); + add_constructor(t, d); + + symbol k = intern("k"); + assign_subschema(s, c, k, t); + assign_subschema(t, d, k, LEAF); + + gardener *g = new_gardener(s); + start(g, c); + sub(g, k, d); + fill(g, k, k); + res &= done(g); + res &= !get_error(g); + + return res; +} + +int main() +{ + assert(test_empty_constructor_success()); + assert(test_empty_constructor_empty_tree_fail()); + assert(test_double_deep_schema_fail()); + assert(test_double_deep_schema_success()); + assert(test_triple_deep_schema_fail()); + assert(test_triple_deep_schema_success()); + return 0; +} diff --git a/coding/schema.c b/coding/schema.c @@ -0,0 +1,143 @@ +#include <assert.h> +#include <stdio.h> + +#include "schema.h" + +#include "assoc.h" + +struct schema { + assoc *constructors; + bool (*checker)(tree*); +}; + +struct constructor { + assoc *subschemas; +}; + +typedef struct constructor constructor; + +/* CONSTRUCTORS */ + +schema* +new_schema(void) +{ + schema *s = malloc(sizeof(schema)); + s->constructors = new_assoc(); + s->checker = NULL; + return s; +} + +struct schema _LEAF = { NULL }; +struct schema *LEAF = &_LEAF; + +constructor* +new_constructor() +{ + constructor *c = malloc(sizeof(constructor)); + c->subschemas = new_assoc(); + return c; +} + + +/* GETTERS AND SETTERS */ + +bool +is_constructor(schema* s, symbol c) +{ + return assoc_get(s->constructors, c) != NULL; +} + +constructor* +get_constructor(schema* s, symbol c) +{ + assert(is_constructor(s, c)); + return (constructor*) assoc_get(s->constructors, c); +} + +schema* +get_subschema(schema* s, symbol c, symbol k) +{ + assert(is_constructor(s, c)); + return (schema*) assoc_get(get_constructor(s, c)->subschemas, k); +} + +bool +has_key(schema *s, symbol c, symbol k) +{ + assert(is_constructor(s, c)); + return (assoc_get(get_constructor(s, c)->subschemas, k) != NULL); +} + +bool +takes_leaf(schema *s, symbol c, symbol k) +{ + assert(is_constructor(s, c)); + return (assoc_get(get_constructor(s, c)->subschemas, k) == LEAF); +} + +void +set_check_function(schema* s, bool (*f)(tree*)) +{ + s->checker = f; +} + +bool (*get_check_function(schema* s))(tree*) +{ + return s->checker; +} + +/* REST OF INTERFACE */ + +void +add_constructor(schema* s, symbol c) +{ + assert(!is_constructor(s, c)); + constructor *sub = new_constructor(); + assoc_set(s->constructors, c, sub); +} + +void +assign_subschema(schema* s, symbol c, symbol k, schema* sub) +{ + assert(is_constructor(s, c)); + assoc_set(get_constructor(s, c)->subschemas, k, sub); +} + +void +mark_as_leaf(schema* s, symbol c, symbol k) +{ + assert(is_constructor(s, c)); + assoc_set(get_constructor(s, c)->subschemas, k, LEAF); +} + +bool +check(schema* s, tree* t) +{ + if (!s) return true; + if (!t) return false; + if (s == LEAF && is_leaf(t)) return true; + + bool good = true; + symbol head = get_head(t); + + size_t lim = get_amount_of_keys(get_constructor(s, head)->subschemas); + symbol *keys = get_keys(get_constructor(s, head)->subschemas); + + for (size_t i = 0; i < lim && good; i++) { + tree *subtree = get_subtree(t, keys[i]); + schema *subschema = get_subschema(s, head, keys[i]); + assert(subschema != NULL); + + if (subtree) + good &= (check(subschema, get_subtree(t, keys[i]))); + else + return false; + } + + bool (*checker)(tree*) = get_check_function(s); + if (checker) good &= checker(t); + + return good; +} + + diff --git a/coding/schema.h b/coding/schema.h @@ -5,6 +5,23 @@ typedef struct schema schema; +/* BUILDING */ schema* new_schema(void); -schema* get_subschema(schema*, symbol); +void add_constructor(schema*, symbol); +void assign_subschema(schema*, symbol, symbol, schema*); +void mark_as_leaf(schema*, symbol, symbol); +void set_check_function(schema*, bool (*)(tree*)); + +/* USING */ +schema* get_subschema(schema*, symbol, symbol); +bool has_key(schema*, symbol, symbol); +bool takes_leaf(schema*, symbol, symbol); bool check(schema*, tree*); + +extern struct schema *LEAF; + +/* Guarantees: + - assign_subschema, get_subschema => id + Test: + - check tree + */ diff --git a/coding/schema.test.c b/coding/schema.test.c @@ -0,0 +1,54 @@ +#include <stdbool.h> +#include <assert.h> + +#include "schema.h" + +#include "symbol.h" +#include "assoc.h" + +bool +test_set_and_get_subschema(void) +{ + schema *s = new_schema(); + schema *sub = new_schema(); + symbol c = intern("c"); + symbol a = intern("a"); + + add_constructor(s, c); + assign_subschema(s, c, a, sub); + + return (get_subschema(s, c, a) == sub); +} + +bool +test_set_and_query_leaf(void) +{ + schema *s = new_schema(); + symbol c = intern("c"); + symbol a = intern("a"); + + add_constructor(s, c); + mark_as_leaf(s, c, a); + + return takes_leaf(s, c, a); +} + +bool +test_leaf_exists(void) +{ + assert(LEAF != NULL); +} + +bool +test_check(void) +{ +} + +int +main() +{ + assert(test_set_and_get_subschema()); + assert(test_set_and_query_leaf()); + assert(test_leaf_exists()); + return 0; +} diff --git a/coding/stack.c b/coding/stack.c @@ -0,0 +1,50 @@ +#include <stdlib.h> +#include <assert.h> + +#include "stack.h" + +struct stack { + size_t len; + size_t cap; + void **items; +}; + +stack* +new_stack(void) +{ + stack *s = malloc(sizeof(stack)); + s->len = 0; + s->cap = 1; + s->items = malloc(s->cap*sizeof(void*)); + return s; +} + +void +push(stack* s, void* p) +{ + if (s->len == s->cap) + s->items = realloc(s->items, sizeof(void*) * (s->cap *= 2)); + assert(s->items); + + s->items[s->len++] = p; +} + +void* pop(stack* s) +{ + return s->items[s->len--]; +} + +void* +peek(stack* s) +{ + if (s->len > 0) + return s->items[s->len - 1]; + else + return NULL; +} + +bool +is_empty(stack* s) +{ + return (s->len == 0); +} diff --git a/coding/stack.h b/coding/stack.h @@ -0,0 +1,10 @@ +#include <stdbool.h> + +typedef struct stack stack; + +stack* new_stack(void); + +void* pop (stack* ); +void* peek (stack* ); +void push (stack*, void* ); +bool is_empty (stack* ); diff --git a/coding/stack.test.c b/coding/stack.test.c @@ -0,0 +1,25 @@ +#include <stdbool.h> + +#include "stack.h" + +bool +test_push_then_pop() +{ + stack *s = new_stack(); + push(s, (void*)0x1); + return (pop(s) == (void*)0x1 && is_empty(s)); +} + +bool +test_push_then_peek() +{ + stack *s = new_stack(); + push(s, (void*)0x1); + return (peek(s) == (void*)0x1 && !is_empty(s)); +} + +int +main() +{ + return 0; +} diff --git a/coding/test.sh b/coding/test.sh @@ -2,11 +2,14 @@ src=$(ls *.c | grep -v '\.test\.c') -for f in *.test.c +for m in symbol assoc stack tree schema gardener do + f=$m.test.c out=$(basename $f .c) - cc -fmax-errors=1 $f $src -o $out || exit 1 - ./$out + echo "Compiling $f..." + cc -g -fmax-errors=1 $f $src -o $out || exit 1 + echo "Running $f..." + ./$out || break + rm $out done - -rm *.test +echo Done. diff --git a/coding/tree.c b/coding/tree.c @@ -1,4 +1,6 @@ #include <stdbool.h> +#include <assert.h> + #include "assoc.h" #include "tree.h" @@ -46,3 +48,10 @@ get_subtree(tree* t, symbol k) else return NULL; } + +symbol +get_head(tree* t) +{ + assert(t != NULL); + return t->head; +} diff --git a/coding/tree.h b/coding/tree.h @@ -2,11 +2,12 @@ typedef struct tree tree; -tree* new_leaf (symbol); -tree* new_node (symbol); -void set_subtree (tree*, symbol, tree*); -tree* get_subtree (tree*, symbol); -bool is_leaf (tree*); +tree* new_leaf (symbol); +tree* new_node (symbol); +void set_subtree (tree*, symbol, tree*); +tree* get_subtree (tree*, symbol); +bool is_leaf (tree*); +symbol get_head (tree*); /* Guarantees: * - set(t, k, v), is_leaf(t) || get(t, k) == v;