loa

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

commit 7d12dd1a564c85f780c8aed3b463b7e3bf46ab25
parent 95ed9bfdc82db27442570086da1a85b4a4e656b9
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date:   Thu,  9 May 2024 15:18:07 +0200

Finish implementing zen commands

Diffstat:
Mcoding/default.o.do | 4++--
Mcoding/default.test.do | 4++--
Mcoding/gardener.c | 2+-
Mcoding/model.test.c | 2--
Mcoding/zen.c | 95++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mcoding/zen.test.c | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
6 files changed, 181 insertions(+), 36 deletions(-)

diff --git a/coding/default.o.do b/coding/default.o.do @@ -1,4 +1,4 @@ src=$(basename "$1" .o).c redo-ifchange $src echo cc -g -c $src -o "$1" >&2 -cc -g -c $src -o "$3" -\ No newline at end of file +cc -g -Wall -Wextra -fmax-errors=1 -g -c $src -o "$3" +\ No newline at end of file diff --git a/coding/default.test.do b/coding/default.test.do @@ -1,6 +1,6 @@ deps=$(grep '^#include ".*"$' $1.c | sed 's/#include "\(.*\)\.h"/\1.o/') redo-ifchange "$1.o" redo-ifchange $deps -src=$(ls *.o | grep -v .test.o) +src=$(ls *.h | sed 's/\.h$/\.o/') echo cc -o "$1" $src "$1.o" >&2 -cc -o "$3" $src "$1.o" +cc -o "$3" -g -Wall -Wextra -fmax-errors=1 $src "$1.o" diff --git a/coding/gardener.c b/coding/gardener.c @@ -183,7 +183,7 @@ show(FILE *f, gardener *g) schema *s = get_cur_schema(g); tree *cur = get_cur_tree(g); if (cur == NULL) { - fprintf(f, "schema %s\n", get_name(get_top(g))); + fprintf(f, "schema %s\n", repr(get_name(get_top(g)))); return; } symbol head = get_head(cur); diff --git a/coding/model.test.c b/coding/model.test.c @@ -123,9 +123,7 @@ test_use(void) 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)); } diff --git a/coding/zen.c b/coding/zen.c @@ -5,6 +5,9 @@ typedef enum { OP_START, OP_FILL, + OP_DONE, + OP_SUB, + OP_SUP, OP_NOOP } op_type; @@ -32,7 +35,20 @@ next_symbol_meaning(garden_status s, op_type next) return "value"; case OP_START: return "constructor"; + case OP_DONE: + return "enlightenment"; + case OP_SUB: + if (s == WAITING_FOR_B) + return "key"; + else + return "constructor"; + case OP_SUP: + if (s == WAITING_FOR_B) + return "constructor"; + else + return "key"; } + return "enlightenment"; } void @@ -65,6 +81,12 @@ symbol_to_op(symbol s) return OP_START; else if (s == intern("fill")) return OP_FILL; + else if (s == intern("done")) + return OP_DONE; + else if (s == intern("sub")) + return OP_SUB; + else if (s == intern("sup")) + return OP_SUP; else return OP_NOOP; } @@ -79,7 +101,14 @@ next_status_for_op(op_type op) return WAITING_FOR_A; case OP_FILL: return WAITING_FOR_B; + case OP_DONE: + return WAITING_FOR_OP; + case OP_SUB: + return WAITING_FOR_B; + case OP_SUP: + return WAITING_FOR_B; } + return ERROR; } void @@ -109,6 +138,21 @@ exec_op(garden *g) case OP_NOOP: g->status = ERROR; break; + + case OP_DONE: + done(g->gardener); + end_op(g); + break; + + case OP_SUB: + sub(g->gardener, g->b, g->a); + end_op(g); + break; + + case OP_SUP: + sup(g->gardener, g->b, g->a); + end_op(g); + break; } } @@ -116,23 +160,68 @@ void check_b(garden *g) { switch (g->next) { + case OP_START: g->status = ERROR; break; + case OP_NOOP: g->status = ERROR; break; + case OP_FILL: if (has_key(get_cur_schema(g->gardener), get_cur_constructor(g->gardener), + g->b) && + takes_leaf(get_cur_schema(g->gardener), + get_cur_constructor(g->gardener), + g->b)) { + g->status = WAITING_FOR_A; + } else { + g->status = ERROR; + } + break; + + case OP_DONE: + g->status = ERROR; + break; + + case OP_SUB: + if (has_key(get_cur_schema(g->gardener), + get_cur_constructor(g->gardener), g->b)) { g->status = WAITING_FOR_A; } else { g->status = ERROR; } + break; + + case OP_SUP: + if (is_constructor(get_cur_schema(g->gardener), + g->b)) { + g->status = WAITING_FOR_A; + } else { + g->status = ERROR; + } } } +bool +takes_args(op_type op) +{ + switch (op) { + case OP_FILL: + case OP_SUB: + case OP_SUP: + case OP_START: + return true; + case OP_NOOP: + case OP_DONE: + /* FALLTHROUGH */ + } + return false; +} + void instruct(garden *g, symbol s) { @@ -141,7 +230,11 @@ instruct(garden *g, symbol s) case WAITING_FOR_OP: g->next = symbol_to_op(s); - g->status = next_status_for_op(g->next); + if (takes_args(g->next)) { + g->status = next_status_for_op(g->next); + } else { + exec_op(g); + } break; case WAITING_FOR_A: diff --git a/coding/zen.test.c b/coding/zen.test.c @@ -5,14 +5,15 @@ #include "symbol.h" #include "schema.h" +#define ts(g,c,e) do {instruct(g, intern(c)); assert(get_status(g) == e);} while(0); + void test_start() { schema *s = new_schema(intern("a")); garden *g = new_garden(s); assert(get_status(g) == WAITING_FOR_OP); - instruct(g, intern("start")); - assert(get_status(g) == WAITING_FOR_A); + ts(g, "start", WAITING_FOR_A); } void @@ -20,11 +21,8 @@ test_invalid_constructor_start_fail() { schema *s = new_schema(intern("a")); garden *g = new_garden(s); - assert(get_status(g) == WAITING_FOR_OP); - instruct(g, intern("start")); - assert(get_status(g) == WAITING_FOR_A); - instruct(g, intern("anything")); - assert(get_status(g) == ERROR); + ts(g, "start", WAITING_FOR_A ); + ts(g, "anything", ERROR ); } void @@ -33,15 +31,11 @@ test_invalid_key_fail() schema *s = new_schema(intern("a")); add_constructor(s, intern("c")); garden *g = new_garden(s); - assert(get_status(g) == WAITING_FOR_OP); - instruct(g, intern("start")); - assert(get_status(g) == WAITING_FOR_A); - instruct(g, intern("c")); - assert(get_status(g) == WAITING_FOR_OP); - instruct(g, intern("fill")); - assert(get_status(g) == WAITING_FOR_B); - instruct(g, intern("anything")); - assert(get_status(g) == ERROR); + + ts(g, "start", WAITING_FOR_A); + ts(g, "c", WAITING_FOR_OP); + ts(g, "fill", WAITING_FOR_B); + ts(g, "anything", ERROR); } void @@ -50,21 +44,77 @@ test_valid_key_success() schema *s = new_schema(intern("a")); add_constructor(s, intern("c")); mark_as_leaf(s, intern("c"), intern("k")); + garden *g = new_garden(s); - assert(get_status(g) == WAITING_FOR_OP); - instruct(g, intern("start")); - assert(get_status(g) == WAITING_FOR_A); - instruct(g, intern("c")); - assert(get_status(g) == WAITING_FOR_OP); - instruct(g, intern("fill")); - assert(get_status(g) == WAITING_FOR_B); - instruct(g, intern("k")); - assert(get_status(g) == WAITING_FOR_A); - instruct(g, intern("anything")); - assert(get_status(g) == WAITING_FOR_OP); + ts(g, "start", WAITING_FOR_A); + ts(g, "c", WAITING_FOR_OP); + ts(g, "fill", WAITING_FOR_B); + ts(g, "k", WAITING_FOR_A); + ts(g, "anything", WAITING_FOR_OP); + ts(g, "done", WAITING_FOR_OP); } -/* PICK-UP: tests to implement all gardener ops through instruct */ +void +test_sub_success() +{ + schema *s = new_schema(intern("a")); + add_constructor(s, intern("c")); + schema *t = new_schema(intern("b")); + add_constructor(t, intern("d")); + assign_subschema(s, intern("c"), intern("k"), t); + + garden *g = new_garden(s); + + ts(g, "start", WAITING_FOR_A ); + ts(g, "c", WAITING_FOR_OP ); + ts(g, "sub", WAITING_FOR_B ); + ts(g, "k", WAITING_FOR_A ); + ts(g, "d", WAITING_FOR_OP ); + ts(g, "done", WAITING_FOR_OP ); + ts(g, "done", WAITING_FOR_OP ); +} + +void +test_sub_invalid_constructor_fail() +{ + schema *s = new_schema(intern("a")); + add_constructor(s, intern("c")); + garden *g = new_garden(s); + + ts(g, "start", WAITING_FOR_A ); + ts(g, "c", WAITING_FOR_OP ); + ts(g, "sub", WAITING_FOR_B ); + ts(g, "k", ERROR ); +} + +void +test_sup_invalid_constructor_fail() +{ + schema *s = new_schema(intern("a")); + add_constructor(s, intern("c")); + garden *g = new_garden(s); + + ts(g, "start", WAITING_FOR_A); + ts(g, "c", WAITING_FOR_OP); + ts(g, "sup", WAITING_FOR_B); + ts(g, "d", ERROR); +} + +void +test_sup_success() +{ + schema *s = new_schema(intern("a")); + add_constructor(s, intern("c")); + add_constructor(s, intern("nil")); + assign_subschema(s, intern("c"), intern("k"), s); + garden *g = new_garden(s); + + ts(g, "start", WAITING_FOR_A); + ts(g, "nil", WAITING_FOR_OP); + ts(g, "sup", WAITING_FOR_B); + ts(g, "c", WAITING_FOR_A); + ts(g, "k", WAITING_FOR_OP); +} int main() @@ -73,5 +123,9 @@ main() test_invalid_constructor_start_fail(); test_invalid_key_fail(); test_valid_key_success(); + test_sub_invalid_constructor_fail(); + test_sub_success(); + test_sup_invalid_constructor_fail(); + test_sup_success(); return 0; }