Use setjmp/longjmp to recover after errors.

Wow!  That was easy!
This commit is contained in:
Simon Forman 2023-02-06 00:30:25 -08:00
parent 0611aa3c05
commit 437e0af91d
1 changed files with 23 additions and 14 deletions

View File

@ -29,6 +29,7 @@ along with Thun. If not see <http://www.gnu.org/licenses/>.
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <setjmp.h>
#include <gc.h> #include <gc.h>
#include <gmp.h> #include <gmp.h>
@ -37,6 +38,7 @@ along with Thun. If not see <http://www.gnu.org/licenses/>.
#include "definitions.h" #include "definitions.h"
static jmp_buf jbuf;
const char *BLANKS = " \t"; const char *BLANKS = " \t";
const char *FALSE = "false"; const char *FALSE = "false";
@ -166,7 +168,7 @@ pop_any(JoyListPtr stack)
JoyList result; JoyList result;
if (!(*stack)) { if (!(*stack)) {
printf("Not enough values on stack.\n"); printf("Not enough values on stack.\n");
exit(1); longjmp(jbuf, 1);
} }
result = *stack; result = *stack;
*stack = (*stack)->tail; *stack = (*stack)->tail;
@ -183,7 +185,7 @@ pop_int(JoyListPtr stack)
return &(node->head->value.i); return &(node->head->value.i);
default: default:
printf("Not an integer.\n"); printf("Not an integer.\n");
exit(1); longjmp(jbuf, 1);
} }
} }
@ -200,7 +202,7 @@ pop_bool(JoyListPtr stack)
return 0; return 0;
default: default:
printf("Not a Boolean.\n"); printf("Not a Boolean.\n");
exit(1); longjmp(jbuf, 1);
} }
} }
@ -215,7 +217,7 @@ pop_list_node(JoyListPtr stack)
return node; return node;
default: default:
printf("Not a list.\n"); printf("Not a list.\n");
exit(1); longjmp(jbuf, 1);
} }
} }
@ -372,14 +374,14 @@ Extract terms from the text until a closing bracket is found.
/* NULL string input? */ /* NULL string input? */
if (NULL == *text) { if (NULL == *text) {
printf("Missing ']' bracket. A\n"); printf("Missing ']' bracket. A\n");
exit(1); longjmp(jbuf, 1);
}; };
*text = trim_leading_blanks(*text); *text = trim_leading_blanks(*text);
if (NULL == *text) { if (NULL == *text) {
printf("Missing ']' bracket. B\n"); printf("Missing ']' bracket. B\n");
exit(1); longjmp(jbuf, 1);
}; };
/* Look for blanks or brackets. */ /* Look for blanks or brackets. */
@ -392,7 +394,7 @@ Extract terms from the text until a closing bracket is found.
*/ */
if (NULL == rest) { if (NULL == rest) {
printf("Missing ']' bracket. C\n"); printf("Missing ']' bracket. C\n");
exit(1); longjmp(jbuf, 1);
}; };
/* How many chars have we got? */ /* How many chars have we got? */
@ -460,7 +462,7 @@ parse_node(char **text)
} }
if (']' == rest[0]) { if (']' == rest[0]) {
printf("Extra ']' bracket.\n"); printf("Extra ']' bracket.\n");
exit(1); longjmp(jbuf, 1);
} }
printf("Should be unreachable."); printf("Should be unreachable.");
exit(1); exit(1);
@ -680,7 +682,7 @@ first(JoyListPtr stack, __attribute__((unused)) JoyListPtr expression)
JoyList quote = pop_list(stack); JoyList quote = pop_list(stack);
if (!quote) { if (!quote) {
printf("Cannot take first of empty list.\n"); printf("Cannot take first of empty list.\n");
exit(1); longjmp(jbuf, 1);
} }
push_thing(quote->head, stack); push_thing(quote->head, stack);
} }
@ -692,7 +694,7 @@ rest(JoyListPtr stack, __attribute__((unused)) JoyListPtr expression)
JoyList quote = pop_list(stack); JoyList quote = pop_list(stack);
if (!quote) { if (!quote) {
printf("Cannot take rest of empty list.\n"); printf("Cannot take rest of empty list.\n");
exit(1); longjmp(jbuf, 1);
} }
push_quote(quote->tail, stack); push_quote(quote->tail, stack);
} }
@ -749,7 +751,7 @@ truthy(JoyListPtr stack, __attribute__((unused)) JoyListPtr expression)
break; break;
default: default:
printf("Cannot Boolify.\n"); printf("Cannot Boolify.\n");
exit(1); longjmp(jbuf, 1);
} }
} }
@ -790,7 +792,7 @@ joy(JoyListPtr stack, JoyListPtr expression)
interned = in_word_set(sym, strlen(sym)); interned = in_word_set(sym, strlen(sym));
if (!interned) { if (!interned) {
printf("Unknown: %s\n", sym); printf("Unknown: %s\n", sym);
exit(1); longjmp(jbuf, 1);
} }
interned->func(stack, expression); interned->func(stack, expression);
} }
@ -804,6 +806,7 @@ main(void)
char *status; char *status;
JoyList stack = EMPTY_LIST; JoyList stack = EMPTY_LIST;
JoyList expression = EMPTY_LIST; JoyList expression = EMPTY_LIST;
JoyList s;
/* Initialize Boolean singleton values. */ /* Initialize Boolean singleton values. */
JoyTrue = newJoyType; JoyTrue = newJoyType;
@ -847,8 +850,14 @@ main(void)
printf("bye\n"); printf("bye\n");
break; break;
} }
s = stack;
if (!setjmp(jbuf)) {
expression = text_to_expression(line); expression = text_to_expression(line);
joy(&stack, &expression); joy(&stack, &expression);
} else {
/* err */
stack = s;
}
print_stack(stack); print_stack(stack);
printf("\n"); printf("\n");
} }