commit 8419dd813c09022f358a68f1a751f402ebbe5fa9
parent a9edbec57fdb9fc69af23507043fbf9fa76c15d0
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date: Wed, 8 May 2024 19:11:45 +0200
Add sup
Diffstat:
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;