step: add error checking

This commit is contained in:
NunoSempere 2023-04-30 12:27:27 -04:00
parent 77409407d9
commit 6d4850e38b
2 changed files with 25 additions and 20 deletions

BIN
mumble

Binary file not shown.

View File

@ -32,7 +32,7 @@ lispval lispval_err(int i){
void print_lispval(lispval l){ void print_lispval(lispval l){
switch(l.type){ switch(l.type){
case LISPVAL_NUM: case LISPVAL_NUM:
printf("%li", l.num); printf("\n%li", l.num);
break; break;
case LISPVAL_ERR: case LISPVAL_ERR:
switch(l.err){ switch(l.err){
@ -52,7 +52,6 @@ void print_lispval(lispval l){
default: default:
printf("Unknown lispval type"); printf("Unknown lispval type");
} }
printf("\n");
} }
// Utils // Utils
@ -80,45 +79,51 @@ void print_ast(mpc_ast_t* ast, int num_tabs)
} }
// Operations // Operations
long evaluate_unary_operation(char* op, long x) lispval evaluate_unary_operation(char* op, lispval x)
{ {
if(x.type == LISPVAL_ERR) return x;
if (!strcmp(op, "+")) { if (!strcmp(op, "+")) {
return x; return lispval_num(x.num);
} else if (!strcmp(op, "-")) { } else if (!strcmp(op, "-")) {
return -x; return lispval_num(-x.num);
} }
return 0; return lispval_err(LISPERR_BAD_OP);
} }
long evaluate_operation(char* op, long x, long y) lispval evaluate_operation(char* op, lispval x, lispval y)
{ {
if(x.type == LISPVAL_ERR) return x;
if(y.type == LISPVAL_ERR) return y;
if (!strcmp(op, "+")) { if (!strcmp(op, "+")) {
return x + y; return lispval_num(x.num + y.num);
} else if (!strcmp(op, "-")) { } else if (!strcmp(op, "-")) {
return x - y; return lispval_num(x.num - y.num);
} else if (!strcmp(op, "*")) { } else if (!strcmp(op, "*")) {
return x * y; return lispval_num(x.num * y.num);
} else if (!strcmp(op, "/")) { } else if (!strcmp(op, "/")) {
return x / y; if (y.num == 0) return lispval_err(LISPERR_DIV_ZERO);
return lispval_num(x.num / y.num);
} }
return 0; return lispval_err(LISPERR_BAD_OP);
} }
// Evaluate the AST // Evaluate the AST
long evaluate_ast(mpc_ast_t* t) lispval evaluate_ast(mpc_ast_t* t)
{ {
// Base case #1: It's a number // Base case #1: It's a number
if (strstr(t->tag, "number")) { if (strstr(t->tag, "number")) {
if (VERBOSE) if (VERBOSE)
printf("\nCase #1, %s", t->contents); printf("\nCase #1, %s", t->contents);
return atoi(t->contents); errno = 0;
long x = strtol(t->contents, NULL, 10);
return errno != ERANGE ? lispval_num(x) : lispval_err(LISPERR_BAD_NUM);
} }
// Base case #2: It's a number inputted into the REPL // Base case #2: It's a number inputted into the REPL
// note: strcmp returns a 0 if both chars* have the same contents. // note: strcmp returns a 0 if both chars* have the same contents.
if (t->children_num == 2 && strstr(t->children[0]->tag, "number") && !strcmp(t->children[1]->tag, "regex")) { if (t->children_num == 2 && strstr(t->children[0]->tag, "number") && !strcmp(t->children[1]->tag, "regex")) {
if (VERBOSE) if (VERBOSE)
printf("\nCase #2, %s", t->children[0]->contents); printf("\nCase #2, top level num");
return atoi(t->children[0]->contents); return evaluate_ast(t->children[0]);
} }
// Base case #3: Top level parenthesis // Base case #3: Top level parenthesis
@ -129,7 +134,7 @@ long evaluate_ast(mpc_ast_t* t)
} }
// "Real" cases // "Real" cases
long x; lispval x;
char* operation; char* operation;
// Case #4: Unary operations case // Case #4: Unary operations case
@ -150,7 +155,7 @@ long evaluate_ast(mpc_ast_t* t)
int i = 3; int i = 3;
while ((i < t->children_num) && strstr(t->children[i]->tag, "expr")) { while ((i < t->children_num) && strstr(t->children[i]->tag, "expr")) {
// note that when reaching a closing parenthesis, ^ returns false // note that when reaching a closing parenthesis, ^ returns false
long y = evaluate_ast(t->children[i]); lispval y = evaluate_ast(t->children[i]);
x = evaluate_operation(operation, x, y); x = evaluate_operation(operation, x, y);
i++; i++;
} }
@ -204,8 +209,8 @@ int main(int argc, char** argv)
// Evaluate the AST // Evaluate the AST
if(VERBOSE) printf("\n\nEvaluating the AST"); if(VERBOSE) printf("\n\nEvaluating the AST");
long result = evaluate_ast(ast); lispval result = evaluate_ast(ast);
printf("\nResult: %li\n", result); print_lispval(result);
} else { } else {
/* Otherwise Print the Error */ /* Otherwise Print the Error */
mpc_err_print(result.error); mpc_err_print(result.error);