loa

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

commit 13a9ecc93ef4334db0fca4aa33e38b2fa759ebfc
parent 067e31f554978b45b84448433b18dc7ba98b6b0e
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date:   Thu, 18 Jan 2024 18:05:34 -0300

Add somewhat proper error handling to VM

Diffstat:
Mcoding/formating.c | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcoding/formating.h | 1+
Mcoding/tactics.c | 11++++++++---
Mcoding/tactics.h | 10+++++-----
Mcoding/vm.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mcoding/vm.h | 23+++++++++++++++++++++++
6 files changed, 219 insertions(+), 47 deletions(-)

diff --git a/coding/formating.c b/coding/formating.c @@ -1,5 +1,6 @@ #include <stdio.h> #include <stdlib.h> +#include <assert.h> #include "formating.h" @@ -124,3 +125,114 @@ print_state(FILE *f, struct state *st) } } +void +print_tape(FILE *f, struct tape *t) +{ + size_t c = 0; + struct op op; + fputs("TAPE\n", f); + do { + if (t->cur == c) + fputs("> ", f); + else + fputs(" ", f); + + op = t->code[c]; + switch (op.code) { + case TOP: + fputs("TOP ", f); + fputc(type_variable(op.type), f); + fputc('\n', f); + break; + case SYM: + fprintf(f, "SYM %s\n", op.sym->name); + break; + case NUM: + fprintf(f, "NUM %d\n", op.num); + break; + case HLT: + fputs("HLT\n", f); + break; + } + + c++; + } while(op.code != HLT); +} + +void +print_opcode(FILE *f, enum opcode code) +{ + switch(code) { + case TOP: + fputs("TOP", f); + break; + case SYM: + fputs("SYM", f); + break; + case NUM: + fputs("NUM", f); + break; + case HLT: + fputs("HLT", f); + break; + } +} + +void +print_error(FILE *f, struct vm *m) +{ + struct tape *t = m->tape; + + switch (m->err) { + case OK: + return; + break; + case NONEXISTENT_ATTITUDE: + fputs("No attitude with name '", f); + print_symbol(f, t->code[t->cur].sym); + fputs("'\n", f); + break; + case INVALID_TOP_GOAL_TYPE: + fputs("Invalid top goal type '", f); + print_symbol(f, t->code[t->cur].sym); + fputs("'\n", f); + break; + case ADDING_TOP_GOAL_WHEN_FOCUS: + fputs("Tried creating a top goal while focused\n", f); + break; + case ADDING_SUBGOAL_WITHOUT_FOCUS: + fputs("Tried adding a subgoal while unfocused\n", f); + break; + case COMMITING_WITHOUT_FOCUS: + fputs("Tried commiting while unfocused\n", f); + break; + case SOLVING_WITHOUT_FOCUS: + fputs("Tried solving while unfocused\n", f); + break; + case EXPECTED_SYMBOL: + fputs("Expected a symbol, but found ", f); + print_opcode(f, t->code[t->cur].code); + fputc('\n', f); + break; + case EXPECTED_NUMBER: + fputs("Expected a number, but found ", f); + print_opcode(f, t->code[t->cur].code); + fputc('\n', f); + break; + case EXPECTED_TOP: + fputs("Expected a goal creation, but found ", f); + print_opcode(f, t->code[t->cur].code); + fputc('\n', f); + break; + } +} + +void +print_machine(FILE *f, struct vm *m) +{ + fputs("VM\n", f); + print_error(f, m); + print_state(f, m->state); + fputc('\n', f); + print_tape(f, m->tape); +} diff --git a/coding/formating.h b/coding/formating.h @@ -10,3 +10,4 @@ void print_goal(FILE *f, struct goal *g, unsigned int level); void print_attitude(FILE *f, struct state *st, struct attitude *a); void print_assumption(FILE *f, struct state *st, struct assumption a); void print_proof(FILE *f, struct state *st, struct proof p); +void print_machine(FILE *f, struct vm *m); diff --git a/coding/tactics.c b/coding/tactics.c @@ -1,6 +1,6 @@ #include "tactics.h" -void +res_t tactic_term(struct state *st, struct symbol *head, size_t arity) { assert(!st->focus || st->focus->type == TERM); @@ -14,9 +14,11 @@ tactic_term(struct state *st, struct symbol *head, size_t arity) } commit(st); + + return OK; } -void +res_t tactic_attitude(struct state *st, struct symbol *marker, size_t nvars, size_t npres) { assert(st->focus && st->focus->type == ATTITUDE); @@ -31,14 +33,17 @@ tactic_attitude(struct state *st, struct symbol *marker, size_t nvars, size_t np solve(st, a); commit(st); + + return OK; } -void +res_t tactic_symbol(struct state *st, struct symbol *s) { assert(st->focus && st->focus->type == SYMBOL); solve(st, s); commit(st); + return OK; } // void diff --git a/coding/tactics.h b/coding/tactics.h @@ -23,9 +23,9 @@ // }; // // void tactic(struct state *st, struct tactic_args); -void tactic_term(struct state *st, struct symbol *head, size_t arity); -void tactic_symbol(struct state *st, struct symbol *s); -void tactic_attitude(struct state *st, struct symbol *marker, size_t nvars, size_t npres); -void tactic_assumption(struct state *st, struct symbol *name, struct symbol *marker, size_t nvars, size_t nsub); -void tactic_proof(struct state *st, struct term *thesis); +res_t tactic_term(struct state *st, struct symbol *head, size_t arity); +res_t tactic_symbol(struct state *st, struct symbol *s); +res_t tactic_attitude(struct state *st, struct symbol *marker, size_t nvars, size_t npres); +res_t tactic_assumption(struct state *st, struct symbol *name, struct symbol *marker, size_t nvars, size_t nsub); +res_t tactic_proof(struct state *st, struct term *thesis); diff --git a/coding/vm.c b/coding/vm.c @@ -16,6 +16,7 @@ state new_state(void) s.focus = NULL; s.cursor = NULL; s.head = NULL; + s.err = OK; return s; } @@ -104,8 +105,11 @@ void add_top_goal(struct state *st, ref_t type) { void *addr; - assert(type == ATTITUDE); - assert(!st->focus); + + check_ok(st); + check(st, type == ATTITUDE, INVALID_TOP_GOAL_TYPE); + check(st, !st->focus, ADDING_TOP_GOAL_WHEN_FOCUS); + if (type == ATTITUDE) { addr = reserve(st, attitude); } @@ -115,7 +119,8 @@ add_top_goal(struct state *st, ref_t type) void add_subgoal(struct state *st, ref_t type, void *target) { - assert(st->focus); + check_ok(st); + check(st, st->focus, ADDING_SUBGOAL_WITHOUT_FOCUS); struct goal *new = create_goal(type, target); if (st->cursor) { @@ -133,7 +138,9 @@ add_subgoal(struct state *st, ref_t type, void *target) void commit(struct state *st) { - assert(st->focus); + check_ok(st); + check(st, st->focus, COMMITING_WITHOUT_FOCUS); + if (st->focus->sub) { st->focus = st->focus->sub; } else if (st->focus->next) { @@ -150,7 +157,8 @@ commit(struct state *st) void solve(struct state *st, void *dest) { - assert(st->focus); + check_ok(st); + check(st, st->focus, SOLVING_WITHOUT_FOCUS); switch (st->focus->type) { case TERM: *st->focus->target = (struct term*)dest; @@ -170,60 +178,74 @@ solve(struct state *st, void *dest) } } -struct symbol -*read_symbol(struct tape *program) +struct symbol* +read_symbol(struct vm *m) { - assert(program->code[program->cur].code == SYM); - return program->code[program->cur++].sym; + if (m->tape->code[m->tape->cur].code == SYM) { + return m->tape->code[m->tape->cur++].sym; + } else { + m->err = EXPECTED_SYMBOL; + return NULL; + } } unsigned int -read_number(struct tape *program) +read_number(struct vm *m) { - assert(program->code[program->cur].code == NUM); - return program->code[program->cur++].num; + if (m->tape->code[m->tape->cur].code == NUM) { + return m->tape->code[m->tape->cur++].num; + } else { + m->err = EXPECTED_NUMBER; + return 0; + } } ref_t -read_top(struct tape *program) +read_top(struct vm *m) { - assert(program->code[program->cur].code == TOP); - return program->code[program->cur++].type; + if (m->tape->code[m->tape->cur].code == TOP) { + return m->tape->code[m->tape->cur++].type; + } else { + m->err = EXPECTED_TOP; + return 0; + } } void -step(struct state *st, struct tape *program) +step(struct vm *m) { - unsigned int n, m; + unsigned int n, k; struct symbol *sym; // , *mk; - if (!st->focus) { + check_ok(m); + + if (!m->state->focus) { /* No active goal. Expect goal creation */ - ref_t ty = read_top(program); - add_top_goal(st, ty); + ref_t ty = read_top(m); + add_top_goal(m->state, ty); } else { - switch (st->focus->type) { + switch (m->state->focus->type) { case SYMBOL: - sym = read_symbol(program); - tactic_symbol(st, sym); + sym = read_symbol(m); + tactic_symbol(m->state, sym); break; case ATTITUDE: - sym = read_symbol(program); - n = read_number(program); - m = read_number(program); - tactic_attitude(st, sym, n, m); + sym = read_symbol(m); + n = read_number(m); + k = read_number(m); + tactic_attitude(m->state, sym, n, k); break; case ASSUMPTION: - // sym = read_symbol(program); - // mk = read_symbol(program); - // n = read_number(program); - // m = read_number(program); + // sym = read_symbol(m); + // mk = read_symbol(m); + // n = read_number(m); + // m = read_number(m); // tactic_assumption(st, sym, mk, n, m); break; case TERM: - sym = read_symbol(program); - n = read_number(program); - tactic_term(st, sym, n); + sym = read_symbol(m); + n = read_number(m); + tactic_term(m->state, sym, n); break; case PROOF: exit(1); @@ -233,10 +255,13 @@ step(struct state *st, struct tape *program) } void -run(struct state *st, struct tape *program) +run(struct vm *m) { - while (program->code[program->cur].code != HLT) - step(st, program); + while ( + m->tape->code[m->tape->cur].code != HLT && + m->err == OK + ) + step(m); } int @@ -283,8 +308,14 @@ main(void) { .cur = 0 }; - run(&s, &t); - print_state(stdout, &s); + struct vm machine = { + .state = &s, + .tape = &t + }; + + run(&machine); + print_machine(stdout, &machine); + // run(&machine); return 0; } diff --git a/coding/vm.h b/coding/vm.h @@ -9,6 +9,22 @@ typedef enum { PROOF, } ref_t; +typedef enum { + OK, + NONEXISTENT_ATTITUDE, + INVALID_TOP_GOAL_TYPE, + ADDING_TOP_GOAL_WHEN_FOCUS, + ADDING_SUBGOAL_WITHOUT_FOCUS, + COMMITING_WITHOUT_FOCUS, + SOLVING_WITHOUT_FOCUS, + EXPECTED_SYMBOL, + EXPECTED_NUMBER, + EXPECTED_TOP +} res_t; + +#define check_ok(st) if (st->err != OK) return; +#define check(st, expr, e) if (!(expr)) {st->err = e; return;} + struct ref { ref_t type; void *addr; @@ -122,10 +138,17 @@ struct state { struct goal *cursor; struct goal *next; struct assumption *head; + res_t err; list(attitude); }; +struct vm { + struct state *state; + struct tape *tape; + res_t err; +}; + struct state new_state(void); struct ref *allocate_refs(struct state *st, size_t n, ref_t type);