Better error reporting
This commit is contained in:
parent
a8882d1cb4
commit
c3065702e3
6 changed files with 72 additions and 23 deletions
|
@ -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++) {
|
||||
|
|
38
lval/error.c
38
lval/error.c
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
11
lval/error.h
11
lval/error.h
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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) {
|
||||
|
|
6
prompt.c
6
prompt.c
|
@ -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);
|
||||
}
|
Reference in a new issue