loa

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

commit 95ed9bfdc82db27442570086da1a85b4a4e656b9
parent 5a62b83bf91cab34389b7ab0e981c1804bc2ff54
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date:   Thu,  9 May 2024 12:57:30 +0200

Add a partial implementation of a language for commanding gardeners

Diffstat:
Mcoding/gardener.c | 12+++++++++++-
Mcoding/gardener.h | 4++++
Acoding/interpreter.c | 30++++++++++++++++++++++++++++++
Acoding/interpreter.do | 5+++++
Mcoding/model.c | 5+++++
Mcoding/model.test.c | 4++--
Acoding/zen.c | 161+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acoding/zen.h | 16++++++++++++++++
Acoding/zen.test.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 311 insertions(+), 3 deletions(-)

diff --git a/coding/gardener.c b/coding/gardener.c @@ -48,6 +48,12 @@ get_cur_tree(gardener *g) return g->result; } +symbol +get_cur_constructor(gardener *g) +{ + return get_head(get_cur_tree(g)); +} + schema* get_cur_schema(gardener *g) { @@ -149,6 +155,7 @@ start(gardener* g, symbol c) { ensure(g, is_empty(g->stack), START_ON_NONEMPTY_STACK); ensure(g, (g->result == NULL), OP_AFTER_RESULT); + ensure(g, is_constructor(g->top, c), START_WITH_INVALID_CONSTRUCTOR); frame *f = new_frame(); f->tree = new_node(c); @@ -175,7 +182,10 @@ show(FILE *f, gardener *g) { schema *s = get_cur_schema(g); tree *cur = get_cur_tree(g); - if (cur == NULL) return; + if (cur == NULL) { + fprintf(f, "schema %s\n", get_name(get_top(g))); + return; + } symbol head = get_head(cur); fprintf(f, "schema %s\n", repr(get_name(s))); diff --git a/coding/gardener.h b/coding/gardener.h @@ -4,6 +4,7 @@ typedef enum { OK, + START_WITH_INVALID_CONSTRUCTOR, SUB_INVALID_KEY, START_ON_NONEMPTY_STACK, SUB_WITH_INVALID_CONSTRUCTOR, @@ -14,6 +15,9 @@ typedef enum { typedef struct gardener gardener; +schema *get_cur_schema(gardener*); +symbol get_cur_constructor(gardener*); + gardener* new_gardener(schema*); gardener_status get_error(gardener*); tree* result(gardener*); diff --git a/coding/interpreter.c b/coding/interpreter.c @@ -0,0 +1,30 @@ +#include <stdio.h> + +#include "model.h" +#include "zen.h" +#include "tokenizer.h" + +int +main(size_t argc, char **argv) +{ + garden *g = new_garden(schema(context)); + FILE *src; + + if (argc > 1) { + src = fopen(argv[1], "r"); + if (!src) { + fprintf(stderr, "No such file: %s\n", argv[1]); + return 1; + } + } else { + src = stdin; + } + + tokenizer *t = new_tokenizer(src); + + while (!eos(t)) + instruct(g, next_token(t)); + display_garden(stdout, g); + + return 0; +} diff --git a/coding/interpreter.do b/coding/interpreter.do @@ -0,0 +1,5 @@ +deps=$(grep '^#include ".*\.h"' interpreter.c | sed 's/#include "\(.*\).h"/\1.o/') +redo-ifchange $deps +src=$(ag -L '^main\(' | grep '\.c$' | sed 's/\.c/.o/') +echo cc $src interpreter.c -o $1 >&2 +cc $src interpreter.c -o $3 diff --git a/coding/model.c b/coding/model.c @@ -23,11 +23,16 @@ start_schema(context) mark_as_leaf (it, I("attitude"), I("name") ); assign_subschema (it, I("attitude"), I("vars"), schema(vars) ); assign_subschema (it, I("attitude"), I("pressupositions"), schema(term_list) ); + assign_subschema (it, I("attitude"), I("precontext"), schema(context) ); add_constructor (it, I("assumption") ); mark_as_leaf (it, I("assumption"), I("name") ); assign_subschema (it, I("assumption"), I("judgment"), schema(term) ); assign_subschema (it, I("assumption"), I("proof"), schema(proof) ); + assign_subschema (it, I("assumption"), I("precontext"), schema(context) ); + assign_subschema (it, I("assumption"), I("subcontext"), schema(context) ); + + add_constructor (it, I("being") ); end_schema(context); start_schema(term) diff --git a/coding/model.test.c b/coding/model.test.c @@ -125,8 +125,8 @@ test_use(void) done (g ); assert(get_error(g) == OK); done (g ); assert(get_error(g) == OK); - show(stdout, g); - display_tree(stdout, result(g)); + // show(stdout, g); + // display_tree(stdout, result(g)); } int diff --git a/coding/zen.c b/coding/zen.c @@ -0,0 +1,161 @@ +#include "zen.h" +#include "schema.h" +#include "gardener.h" + +typedef enum { + OP_START, + OP_FILL, + OP_NOOP +} op_type; + +struct garden { + gardener *gardener; + garden_status status; + op_type next; + symbol a; + symbol b; +}; + +char* +next_symbol_meaning(garden_status s, op_type next) +{ + if (s == ERROR) return "enlightenment"; + if (s == WAITING_FOR_OP) return "operation"; + + switch (next) { + case OP_NOOP: + return "nothing"; + case OP_FILL: + if (s == WAITING_FOR_B) + return "key"; + else + return "value"; + case OP_START: + return "constructor"; + } +} + +void +display_garden(FILE *f, garden *g) +{ + show(f, g->gardener); + fprintf(f, "\nWaiting for %s.\n", + next_symbol_meaning(g->status, g->next)); +} + +garden* +new_garden(schema* s) +{ + garden *g = malloc(sizeof(garden)); + g->gardener = new_gardener(s); + g->status = WAITING_FOR_OP; + return g; +} + +garden_status +get_status(garden *g) +{ + return g->status; +} + +op_type +symbol_to_op(symbol s) +{ + if (s == intern("start")) + return OP_START; + else if (s == intern("fill")) + return OP_FILL; + else + return OP_NOOP; +} + +garden_status +next_status_for_op(op_type op) +{ + switch (op) { + case OP_NOOP: + return ERROR; + case OP_START: + return WAITING_FOR_A; + case OP_FILL: + return WAITING_FOR_B; + } +} + +void +end_op(garden *g) +{ + if (get_error(g->gardener) != OK) + g->status = ERROR; + else + g->status = WAITING_FOR_OP; +} + +void +exec_op(garden *g) +{ + switch (g->next) { + + case OP_START: + start(g->gardener, g->a); + end_op(g); + break; + + case OP_FILL: + fill(g->gardener, g->b, g->a); + end_op(g); + break; + + case OP_NOOP: + g->status = ERROR; + break; + } +} + +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)) { + g->status = WAITING_FOR_A; + } else { + g->status = ERROR; + } + } +} + +void +instruct(garden *g, symbol s) +{ + (void)s; + switch (g->status) { + + case WAITING_FOR_OP: + g->next = symbol_to_op(s); + g->status = next_status_for_op(g->next); + break; + + case WAITING_FOR_A: + g->a = s; + exec_op(g); + break; + + case WAITING_FOR_B: + g->b = s; + check_b(g); + break; + + case ERROR: + break; + + } +} diff --git a/coding/zen.h b/coding/zen.h @@ -0,0 +1,16 @@ +#include <stdio.h> +#include "schema.h" + +typedef enum { + WAITING_FOR_OP, + WAITING_FOR_A, + WAITING_FOR_B, + ERROR +} garden_status; + +typedef struct garden garden; + +garden *new_garden(schema*); +void instruct(garden*, symbol); +garden_status get_status(garden*); +void display_garden(FILE*, garden*); diff --git a/coding/zen.test.c b/coding/zen.test.c @@ -0,0 +1,77 @@ +#include <stdio.h> +#include <assert.h> + +#include "zen.h" +#include "symbol.h" +#include "schema.h" + +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); +} + +void +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); +} + +void +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); +} + +void +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); +} + +/* PICK-UP: tests to implement all gardener ops through instruct */ + +int +main() +{ + test_start(); + test_invalid_constructor_start_fail(); + test_invalid_key_fail(); + test_valid_key_success(); + return 0; +}