loa

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

commit 8419dd813c09022f358a68f1a751f402ebbe5fa9
parent a9edbec57fdb9fc69af23507043fbf9fa76c15d0
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date:   Wed,  8 May 2024 19:11:45 +0200

Add sup

Diffstat:
Mcoding/default.test.do | 1-
Mcoding/gardener.c | 89++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mcoding/gardener.h | 4++--
Mcoding/gardener.test.c | 30+++++++++++++++++++++++++++++-
Mcoding/model.c | 7+++----
Mcoding/model.test.c | 30+++++++++++++++++++++++++-----
Mcoding/test.do | 12+++++-------
Mcoding/tree.c | 23+++++++++++++++++++++++
Mcoding/tree.h | 15+++++++++------
9 files changed, 164 insertions(+), 47 deletions(-)

diff --git a/coding/default.test.do b/coding/default.test.do @@ -4,4 +4,3 @@ headers=*.h src=$(ls *.c | grep -v .test.c) redo-ifchange $src $headers cc -g -Wall -Wextra -fmax-errors=1 $src $1.c -o $3 >&2 -./$3 >&2 || exit 1 diff --git a/coding/gardener.c b/coding/gardener.c @@ -8,14 +8,29 @@ #define ensure(G, COND, ERR) if (!COND) { set_error(G, ERR); return; } +typedef struct { + tree *tree; + schema *schema; + symbol key; +} frame; + struct gardener { schema *top; - stack *treestack; - stack *schemastack; + stack *stack; gardener_status error; tree *result; }; +frame* +new_frame(void) +{ + frame *f = malloc(sizeof(frame)); + f->tree = NULL; + f->schema = NULL; + f->key = 0; + return f; +} + /* GETTERS */ schema* @@ -27,13 +42,19 @@ get_top(gardener *g) tree* get_cur_tree(gardener *g) { - return peek(g->treestack); + if (peek(g->stack)) + return ((frame*)peek(g->stack))->tree; + else + return g->result; } schema* get_cur_schema(gardener *g) { - return peek(g->schemastack); + if (peek(g->stack)) + return ((frame*)peek(g->stack))->schema; + else + return g->top; } gardener_status @@ -64,10 +85,8 @@ new_gardener(schema* s) gardener *g = malloc(sizeof(gardener)); g->top = s; g->error = false; - g->treestack = new_stack(); - g->schemastack = new_stack(); + g->stack = new_stack(); g->result = NULL; - push(g->schemastack, g->top); return g; } @@ -95,32 +114,60 @@ sub(gardener* g, symbol key, symbol constructor) tree *new = new_node(constructor); set_subtree(get_cur_tree(g), key, new); - push(g->schemastack, sub_schema); - push(g->treestack, new); + frame *f = new_frame(); + f->schema = sub_schema; + f->tree = new; + f->key = key; + push(g->stack, f); +} + +void +sup(gardener* g, symbol constructor, symbol key) +{ + // schema *cur_schema = get_cur_schema(g); + + // ensure(g, is_constructor(cur_schema, constructor), SUP_WITH_INVALID_CONSTRUCTOR); + // ensure(g, has_key(cur_schema, constructor, key), SUP_INVALID_KEY); + ensure(g, (g->result == NULL), OP_AFTER_RESULT); + + frame *old = pop(g->stack); + + frame *new = new_frame(); + new->tree = new_node(constructor); + new->schema = old->schema; + new->key = old->key; + + set_subtree(new->tree, key, old->tree); + if (peek(g->stack)) set_subtree(((frame*)peek(g->stack))->tree, old->key, new->tree); + // free_frame(old); + push(g->stack, new); } void start(gardener* g, symbol c) { - ensure(g, is_empty(g->treestack), START_ON_NONEMPTY_STACK); - ensure(g, (g->result == NULL), START_AFTER_RESULT); - tree *t = new_node(c); - push(g->treestack, t); + ensure(g, is_empty(g->stack), START_ON_NONEMPTY_STACK); + ensure(g, (g->result == NULL), OP_AFTER_RESULT); + + frame *f = new_frame(); + f->tree = new_node(c); + f->schema = g->top; + + push(g->stack, f); } void done(gardener* g) { - tree *res; - ensure(g, (!is_empty(g->treestack)), NON_START_OP_ON_EMPTY_STACK); + frame *f; + ensure(g, (!is_empty(g->stack)), NON_START_OP_ON_EMPTY_STACK); ensure(g, check(get_cur_schema(g), get_cur_tree(g)), DONE_ON_INVALID_TREE); - res = pop(g->treestack); - pop(g->schemastack); + f = (frame*) pop(g->stack); - if (is_empty(g->treestack)) - g->result = res; + if (is_empty(g->stack)) + g->result = f->tree; } void @@ -154,8 +201,8 @@ show(FILE *f, gardener *g) case START_ON_NONEMPTY_STACK: fprintf(f, "error START_ON_NONEMPTY_STACK"); break; - case START_AFTER_RESULT: - fprintf(f, "error START_AFTER_RESULT"); + case OP_AFTER_RESULT: + fprintf(f, "error OP_AFTER_RESULT"); break; case SUB_WITH_INVALID_CONSTRUCTOR: fprintf(f, "error SUB_WITH_INVALID_CONSTRUCTOR"); diff --git a/coding/gardener.h b/coding/gardener.h @@ -8,7 +8,7 @@ typedef enum { START_ON_NONEMPTY_STACK, SUB_WITH_INVALID_CONSTRUCTOR, DONE_ON_INVALID_TREE, - START_AFTER_RESULT, + OP_AFTER_RESULT, NON_START_OP_ON_EMPTY_STACK } gardener_status; @@ -21,7 +21,7 @@ tree* result(gardener*); void fill(gardener*, symbol key, symbol value); void sub(gardener*, symbol key, symbol constructor); void done(gardener*); -// void sup(gardener*, symbol key, symbol constructor); +void sup(gardener*, symbol key, symbol constructor); void start(gardener*, symbol constructor); void show(FILE *f, gardener*); diff --git a/coding/gardener.test.c b/coding/gardener.test.c @@ -38,7 +38,7 @@ test_start_after_result_fail(void) done(g); assert(get_error(g) == OK); start(g, intern("nil")); - assert(get_error(g) == START_AFTER_RESULT); + assert(get_error(g) == OP_AFTER_RESULT); } bool @@ -162,6 +162,33 @@ test_triple_deep_schema_success(void) return get_error(g) == OK; } +bool +test_sup_invalid_constructor(void) +{ + return false; +} + +bool +test_sup_invalid_key(void) +{ + return false; +} + +bool +test_sup(void) +{ + schema *s = new_schema(intern("test")); + add_constructor(s, intern("continue")); + add_constructor(s, intern("end")); + assign_subschema(s, intern("continue"), intern("next"), s); + gardener *g = new_gardener(s); + start(g, intern("end")); + sup(g, intern("continue"), intern("next")); + done(g); + + return get_error(g) == OK && result(g) && get_head(result(g)) == intern("continue"); +} + int main() { @@ -172,5 +199,6 @@ main() assert(test_double_deep_schema_success()); assert(test_triple_deep_schema_fail()); assert(test_triple_deep_schema_success()); + assert(test_sup()); return 0; } diff --git a/coding/model.c b/coding/model.c @@ -31,9 +31,9 @@ start_schema(context) end_schema(context); start_schema(term) - add_constructor (it, I("term") ); - mark_as_leaf (it, I("term"), I("head") ); - assign_subschema (it, I("term"), I("tail"), schema(term_list) ); + add_constructor (it, I("term") ); + mark_as_leaf (it, I("term"), I("head") ); + assign_subschema (it, I("term"), I("subterms"), schema(term_list) ); end_schema(term) start_schema(term_list) @@ -57,4 +57,3 @@ start_schema(proof) assign_subschema (it, I("step"), I("args"), schema(term_list) ); assign_subschema (it, I("step"), I("rest"), schema(proof) ); end_schema(proof) - diff --git a/coding/model.test.c b/coding/model.test.c @@ -45,11 +45,11 @@ void test_term(void) { schema *term = schema(term); - assert (is_constructor (term, I("term") ) ); - assert (has_key (term, I("term"), I("head") ) ); - assert (has_key (term, I("term"), I("tail") ) ); - assert (takes_leaf (term, I("term"), I("head") ) ); - assert (get_subschema (term, I("term"), I("tail") ) == schema(term_list) ); + assert (is_constructor (term, I("term") ) ); + assert (has_key (term, I("term"), I("head") ) ); + assert (has_key (term, I("term"), I("subterms") ) ); + assert (takes_leaf (term, I("term"), I("head") ) ); + assert (get_subschema (term, I("term"), I("subterms") ) == schema(term_list) ); } void @@ -104,9 +104,29 @@ test_use(void) done (g ); assert(get_error(g) == OK); sub (g, I("pressupositions"), I("nil") ); assert(get_error(g) == OK); done (g ); assert(get_error(g) == OK); + sup (g, I("attitude"), I("prev") ); assert(get_error(g) == OK); + fill (g, I("name"), I("is") ); assert(get_error(g) == OK); + sub (g, I("vars"), I("var") ); assert(get_error(g) == OK); + fill (g, I("name"), I("a") ); assert(get_error(g) == OK); + sub (g, I("rest"), I("var") ); assert(get_error(g) == OK); + fill (g, I("name"), I("b") ); assert(get_error(g) == OK); + sub (g, I("rest"), I("nil") ); assert(get_error(g) == OK); + done (g ); assert(get_error(g) == OK); + done (g ); assert(get_error(g) == OK); + done (g ); assert(get_error(g) == OK); + sub (g, I("pressupositions"), I("cons") ); assert(get_error(g) == OK); + sub (g, I("car"), I("term") ); assert(get_error(g) == OK); + fill (g, I("head"), I("wft") ); assert(get_error(g) == OK); + sub (g, I("subterms"), I("nil") ); assert(get_error(g) == OK); + done (g ); assert(get_error(g) == OK); + done (g ); assert(get_error(g) == OK); + sub (g, I("cdr"), I("nil") ); assert(get_error(g) == OK); + done (g ); assert(get_error(g) == OK); + done (g ); assert(get_error(g) == OK); done (g ); assert(get_error(g) == OK); show(stdout, g); + display_tree(stdout, result(g)); } int diff --git a/coding/test.do b/coding/test.do @@ -1,11 +1,9 @@ #!/bin/sh -redo symbol.test -redo assoc.test -redo stack.test -redo tree.test -redo schema.test -redo gardener.test -redo model.test +for t in symbol assoc stack tree schema gardener model +do + redo $t.test || exit 1 + ./$t.test >&2 || exit 1 +done echo Done. >&2 diff --git a/coding/tree.c b/coding/tree.c @@ -55,3 +55,26 @@ get_head(tree* t) assert(t != NULL); return t->head; } + +void +display_tree(FILE* f, tree *t) +{ + if (is_leaf(t)) { + fprintf(f, "\"%s\"", repr(get_head(t))); + } else { + size_t num = get_amount_of_keys(t->children); + symbol *keys = get_keys(t->children); + + fprintf(f, "{\"CONSTR\":\"%s\",", repr(get_head(t))); + fprintf(f, "\"KEYS\":{"); + for (size_t i = 0; i < num; i++) { + fprintf(f, "\"%s\":", repr(keys[i])); + display_tree(f, get_subtree(t, keys[i])); + if (i < num - 1) fputc(',', f); + } + fprintf(f, "}}"); + + } +} + + diff --git a/coding/tree.h b/coding/tree.h @@ -1,13 +1,16 @@ +#include <stdio.h> #include "symbol.h" 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*); -symbol get_head (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*); + +void display_tree (FILE*, tree*); /* Guarantees: * - set(t, k, v), is_leaf(t) || get(t, k) == v;