Archived
1
0
Fork 0

Better error reporting

This commit is contained in:
Brandon Rozek 2018-06-09 21:22:14 -04:00
parent a8882d1cb4
commit c3065702e3
6 changed files with 72 additions and 23 deletions

View file

@ -33,7 +33,7 @@ lval* lenv_get(lenv* e, lval* k) {
}
// If no symbol found return error
return lval_err("unbounded symbol!");
return lval_err("Unbounded symbol %s", k->sym);
}
void lenv_put(lenv* e, lval* k, lval* v) {
@ -95,11 +95,13 @@ void lenv_add_builtins(lenv* e) {
lenv_add_builtin(e, "max", builtin_max);
lenv_add_builtin(e, "def", builtin_def);
lenv_add_builtin(e, "ls", builtin_ls);
}
lval* builtin_def(lenv* e, lval* a) {
LASSERT(a, a->cell[0]->type == LVAL_QEXPR,
"Function 'def' passed incorrect type")
"Function 'def' passed incorrect type. Got %s, expected %s",
ltype_name(a->cell[0]->type), ltype_name(LVAL_QEXPR))
// First argument is the symbol list
lval* syms = a->cell[0];
@ -112,7 +114,7 @@ lval* builtin_def(lenv* e, lval* a) {
// Check correct number of symbols and values
LASSERT(a, syms->count == a->count - 1,
"Function 'def' cannot define incorrect number of values to symbols")
"Function 'def' cannot define incorrect number of values to symbols. Left side %i, right side %i", syms->count, a->count - 1)
// Assign copies of values to symbols
for (int i = 0; i < syms->count; i++) {

View file

@ -1,11 +1,41 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
lval* lval_err(char* m) {
lval* lval_err(char* fmt, ...) {
lval* v = (lval *) malloc(sizeof(lval));
v->type = LVAL_ERR;
v->err = (char *) malloc(strlen(m) + 1);
strcpy(v->err, m);
// Create a va list and initialize it
va_list va;
va_start(va, fmt);
// Allocate 512 bytes of space
v->err = (char *) malloc(512);
//printf the error string with a maximum of 511 characters
vsnprintf(v->err, 511, fmt, va);
// Reallocate to the number of actual bytes
v->err = realloc(v->err, strlen(v->err) + 1);
// Cleanup our va list
va_end(va);
return v;
}
}
char* ltype_name(int t) {
switch(t) {
case LVAL_FUN: return "Function";
case LVAL_LONG: return "Long";
case LVAL_DOUBLE: return "Double";
case LVAL_ERR: return "Error";
case LVAL_SYM: return "Symbol";
case LVAL_SEXPR: return "S-Expression";
case LVAL_QEXPR: return "Q-Expression";
default: return "Unknown";
}
}

View file

@ -3,9 +3,14 @@
#include <stdbool.h>
#include "base.h"
lval* lval_err(char* m);
lval* lval_err(char* fmt, ...);
char* ltype_name(int t);
#define LASSERT(args, cond, err) \
if (!(cond)) { lval_del(args); return lval_err(err); }
#define LASSERT(args, cond, fmt, ...) \
if (!(cond)) { \
lval* err = lval_err(fmt, ##__VA_ARGS__); \
lval_del(args); \
return err; \
}
#endif

View file

@ -86,8 +86,9 @@ lval* lval_eval_sexpr(lenv* e, lval* v) {
lval* builtin_headn(lenv* e, lval* a, int n) {
LASSERT(a, a->count == 1, "Function 'head' passed too many arguments")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'head' passed incorrect type")
LASSERT(a, a->count == 1, "Function 'head' passed too many arguments. Got %i, Expected %i.", a->count, 1)
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'head' passed incorrect type. Got %s, expected %s.",
ltype_name(a->cell[0]->type), ltype_name(LVAL_QEXPR))
LASSERT(a, a->cell[0]->count != 0, "Function 'head' passed {}")
lval* v = lval_take(a, 0);
@ -101,7 +102,8 @@ lval* builtin_head(lenv* e, lval* a) {
lval* builtin_init(lenv* e, lval* a) {
LASSERT(a, a->count == 1, "Function 'init' passed too many arguments")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'init' passed incorrect type")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'init' passed incorrect type. Got %s, expeced %s.",
ltype_name(a->cell[0]->type), ltype_name(LVAL_QEXPR))
LASSERT(a, a->cell[0]->count != 0, "Function 'init' passed {}")
return builtin_headn(e, a, a->cell[0]->count - 1);
@ -109,8 +111,9 @@ lval* builtin_init(lenv* e, lval* a) {
lval* builtin_tail(lenv* e, lval* a) {
LASSERT(a, a->count == 1, "Function 'tail' passed too many arguments")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'tail' passed incorrect type")
LASSERT(a, a->count == 1, "Function 'tail' passed too many arguments. Got %i, expected %i.", a->count, 1)
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'tail' passed incorrect type. Got %s, expected %s.",
ltype_name(a->cell[0]->type), ltype_name(LVAL_QEXPR))
LASSERT(a, a->cell[0]->count != 0, "Function 'tail' passed {}")
lval* v = lval_take(a, 0);
@ -125,7 +128,8 @@ lval* builtin_list(lenv* e, lval* a) {
lval* builtin_eval(lenv* e, lval* a) {
LASSERT(a, a->count == 1, "Function 'eval' passed too many arguments")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'eval' passed incorrect type")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'eval' passed incorrect type. Got %s, expected %s.",
ltype_name(a->cell[0]->type), ltype_name(LVAL_QEXPR))
lval* x = lval_take(a, 0);
x->type = LVAL_SEXPR;
@ -145,7 +149,8 @@ lval* lval_join(lenv* e, lval* x, lval* y) {
lval* builtin_join(lenv* e, lval* a) {
for (int i = 0 ; i < a->count; i++) {
LASSERT(a, a->cell[i]->type == LVAL_QEXPR, "Function 'join' passed incorrect type")
LASSERT(a, a->cell[i]->type == LVAL_QEXPR, "Function 'join' passed incorrect type. Got %s, expected %s",
ltype_name(a->cell[i]->type), ltype_name(LVAL_QEXPR))
}
lval* x = lval_pop(a, 0);
@ -159,7 +164,8 @@ lval* builtin_join(lenv* e, lval* a) {
}
lval* builtin_len(lenv* e, lval* a) {
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'len' passed incorrect type")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'len' passed incorrect type. Got %s, expected %s.",
ltype_name(a->cell[0]->type), ltype_name(LVAL_QEXPR))
lval* x = lval_long(a->cell[0]->count);
lval_del(a);
@ -167,9 +173,12 @@ lval* builtin_len(lenv* e, lval* a) {
}
lval* builtin_cons(lenv* e, lval* a) {
LASSERT(a, a->cell[0]->type != LVAL_QEXPR, "Function 'cons' passed incorrect type on first argument")
LASSERT(a, a->cell[1]->type == LVAL_QEXPR, "Function 'cons' passed incorrect type on second argument")
LASSERT(a, a->count == 2, "Function 'cons' passed an incorrect number of arguments")
LASSERT(a, a->cell[0]->type != LVAL_QEXPR, "Function 'cons' passed incorrect type on first argument. Got %s, expected not %s",
ltype_name(a->cell[0]->type), ltype_name(LVAL_QEXPR))
LASSERT(a, a->cell[1]->type == LVAL_QEXPR, "Function 'cons' passed incorrect type on second argument. Got %s, expected %s.",
ltype_name(a->cell[1]->type), ltype_name(LVAL_QEXPR))
LASSERT(a, a->count == 2, "Function 'cons' passed an incorrect number of arguments. Got %i, expected %i.",
a->count, 2)
lval* x = lval_qexpr();
x = lval_add(x, lval_pop(a, 0));

View file

@ -1,4 +1,5 @@
#include <stdio.h>
#include "environment.h"
#include "io.h"
void flval_expr_print(FILE* stream, lval* v, char open, char close) {

View file

@ -121,8 +121,10 @@ lval* builtin_op(lenv* e, lval* a, char* op) {
// Ensure all arguments are numbers
for (int i = 0; i < a->count; i++) {
if (a->cell[i]->type != LVAL_LONG && a->cell[i]->type != LVAL_DOUBLE) {
lval* x = lval_err("Function '%s' passed incorrect type for argument %i. Got %s, expected %s or %s.",
op, i, ltype_name(a->cell[i]->type), ltype_name(LVAL_LONG), ltype_name(LVAL_DOUBLE));
lval_del(a);
return lval_err("Cannot run operation on non-number");
return x;
}
}
@ -171,5 +173,5 @@ lval* builtin(lenv* e, lval* a, char* func) {
if (strcmp("max", func) == 0) { return builtin_op(e, a, func); }
lval_del(a);
return lval_err("Unknown Function!");
return lval_err("Unknown Function %s", func);
}