diff --git a/src/ast.c b/src/ast.c index 8e84986..a0ba01c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -78,13 +78,25 @@ void ast_num_print(ASTNumData* data, int i) { INDENT_END; } -ASTExcData ast_exc_data_init(char* msg) { return (ASTExcData)msg; } +ASTExcData* ast_exc_data_init(char* msg, AST* trace) { + ASTExcData* data = malloc(sizeof(ASTExcData)); + data->msg = msg; + data->trace = trace; + return data; +} -void ast_exc_print(ASTExcData data, int i) { +void ast_exc_print(ASTExcData* data, int i) { INDENT_BEGIN(i); INDENT_TITLE("ASTExcData", data); - INDENT_FIELD("msg", "\"%s\"", data); + INDENT_FIELD("msg", "\"%s\"", data->msg); + if (data->trace == NULL) { + INDENT_FIELD("trace", "%p", NULL) + } else { + INDENT_FIELD_EXT_NONL_START("trace"); + ast_print_i(data->trace, i + 1); + INDENT_FIELD_NONL_END; + } INDENT_END; } diff --git a/src/builtin.c b/src/builtin.c index c243602..2ad2358 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -6,15 +6,19 @@ #include AST* builtin_sum(size_t argc, AST** argv) { - log_dbg("Got here"); ASTNumData total = 0; for (int i = 0; i < argc; i++) { AST* arg = exec_exp(argv[i]); + if (arg->type == AST_TYPE_EXC) + return ast_init( + AST_TYPE_EXC, + ast_exc_data_init("`sum` encountered an exception.", arg) + ); if (arg->type != AST_TYPE_NUM) return ast_init( AST_TYPE_EXC, - ast_exc_data_init("Sum can't sum some non-num arguments.") + ast_exc_data_init("Sum can't sum some non-num arguments.", NULL) ); total += *(ASTNumData*)arg->data; @@ -26,19 +30,30 @@ AST* builtin_sum(size_t argc, AST** argv) { AST* builtin_sub(size_t argc, AST** argv) { log_dbg("Got here"); AST* first = exec_exp(*argv); + if (first->type == AST_TYPE_EXC) + return ast_init( + AST_TYPE_EXC, + ast_exc_data_init("`sub` encountered an exception.", first) + ); if (first->type != AST_TYPE_NUM) return ast_init( - AST_TYPE_EXC, ast_exc_data_init("Can't subtract non-num arguments.") + AST_TYPE_EXC, + ast_exc_data_init("Can't subtract non-num arguments.", NULL) ); ASTNumData total = *(ASTNumData*)first->data; for (int i = 1; i < argc; i++) { AST* arg = exec_exp(argv[i]); + if (arg->type == AST_TYPE_EXC) + return ast_init( + AST_TYPE_EXC, + ast_exc_data_init("`sub` encountered an exception.", arg) + ); if (arg->type != AST_TYPE_NUM) return ast_init( AST_TYPE_EXC, - ast_exc_data_init("Can't subtract non-num arguments.") + ast_exc_data_init("Can't subtract non-num arguments.", NULL) ); total -= *(ASTNumData*)arg->data; @@ -50,19 +65,30 @@ AST* builtin_sub(size_t argc, AST** argv) { AST* builtin_mul(size_t argc, AST** argv) { log_dbg("Got here"); AST* first = exec_exp(*argv); + if (first->type == AST_TYPE_EXC) + return ast_init( + AST_TYPE_EXC, + ast_exc_data_init("`mul` encountered an expection.", first) + ); if (first->type != AST_TYPE_NUM) return ast_init( - AST_TYPE_EXC, ast_exc_data_init("Can't multiply non-num arguments.") + AST_TYPE_EXC, + ast_exc_data_init("Can't multiply non-num arguments.", NULL) ); ASTNumData total = *(ASTNumData*)first->data; for (int i = 1; i < argc; i++) { AST* arg = exec_exp(argv[i]); + if (arg->type == AST_TYPE_EXC) + return ast_init( + AST_TYPE_EXC, + ast_exc_data_init("`mul` encountered an execption.", arg) + ); if (arg->type != AST_TYPE_NUM) return ast_init( AST_TYPE_EXC, - ast_exc_data_init("Can't multiply non-num arguments.") + ast_exc_data_init("Can't multiply non-num arguments.", NULL) ); total *= *(ASTNumData*)arg->data; @@ -74,19 +100,30 @@ AST* builtin_mul(size_t argc, AST** argv) { AST* builtin_div(size_t argc, AST** argv) { log_dbg("Got here"); AST* first = exec_exp(*argv); + if (first->type == AST_TYPE_EXC) + return ast_init( + AST_TYPE_EXC, + ast_exc_data_init("`div` encountered an exception.", first) + ); if (first->type != AST_TYPE_NUM) return ast_init( - AST_TYPE_EXC, ast_exc_data_init("Can't divide non-num arguments.") + AST_TYPE_EXC, + ast_exc_data_init("Can't divide non-num arguments.", NULL) ); ASTNumData total = *(ASTNumData*)first->data; for (int i = 1; i < argc; i++) { AST* arg = exec_exp(argv[i]); + if (arg->type == AST_TYPE_EXC) + return ast_init( + AST_TYPE_EXC, + ast_exc_data_init("`div` encountered an exception.", arg) + ); if (arg->type != AST_TYPE_NUM) return ast_init( AST_TYPE_EXC, - ast_exc_data_init("Can't divide non-num arguments.") + ast_exc_data_init("Can't divide non-num arguments.", NULL) ); total /= *(ASTNumData*)arg->data; diff --git a/src/exec.c b/src/exec.c index 1dfc890..50ef05c 100644 --- a/src/exec.c +++ b/src/exec.c @@ -69,14 +69,15 @@ AST* exec_call(AST* ast) { if (fdef == NULL) return ast_init( - AST_TYPE_EXC, ast_exc_data_init(strdup("No such function found.")) + AST_TYPE_EXC, ast_exc_data_init("No such function found.", NULL) ); switch (fdef->type) { case AST_TYPE_BIF: ASTBIFData bifdata = fdef->data; return bifdata(argc, argv); - default: return ast_init(AST_TYPE_EXC, ast_exc_data_init("Good job!")); + default: + return ast_init(AST_TYPE_EXC, ast_exc_data_init("Good job!", NULL)); } } @@ -113,7 +114,7 @@ AST* exec_vref(AST* ast) { msg, sizeof(msg), "Could not find value in scope for `%s`.", vref->to ); - return ast_init(AST_TYPE_EXC, msg); + return ast_init(AST_TYPE_EXC, ast_exc_data_init(msg, NULL)); } return exec_exp(found); diff --git a/src/include/ast.h b/src/include/ast.h index 55e7343..1e33ee2 100644 --- a/src/include/ast.h +++ b/src/include/ast.h @@ -51,13 +51,16 @@ void ast_num_data_destroy(ASTNumData* num); void ast_num_print(ASTNumData*, int i); // An exception. -typedef char* ASTExcData; +typedef struct ASTEXCDATA { + char* msg; // The exception message. + AST* trace; // The previous exception. +} ASTExcData; // Create a new `ASTExecData. -ASTExcData ast_exc_data_init(char* msg); +ASTExcData* ast_exc_data_init(char* msg, AST* trace); // Destroy an `ASTExecData`. void ast_exc_data_destroy(ASTExcData* exc); // Print an `ASTExecData`. -void ast_exc_print(ASTExcData, int i); +void ast_exc_print(ASTExcData*, int i); // A built-in function. typedef AST* (*ASTBIFData)(size_t argc, AST** argv); diff --git a/src/stack.c b/src/stack.c index 92290e6..8102e82 100644 --- a/src/stack.c +++ b/src/stack.c @@ -21,7 +21,6 @@ void stack_destroy(Stack* stack) { } void stack_push(Stack* stack, void* val) { - log_dbgf("pushed to stack, inc ln to %ld", stack->ln); if (stack->ln >= STACK_MAX) { log_dbgf("Ran out of stack (max: %d)", STACK_MAX); return; @@ -29,6 +28,7 @@ void stack_push(Stack* stack, void* val) { stack->buf[stack->ln] = val; stack->ln++; + log_dbgf("pushed to stack, inc ln to %ld", stack->ln); } void* stack_pop(Stack* stack) {