More exception stuff
This commit is contained in:
+57
-27
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "hashtable.h"
|
||||
#include "lisp.h"
|
||||
#include "lisp_string.h"
|
||||
#include "list.h"
|
||||
#include "read.h"
|
||||
#include "stack.h"
|
||||
@@ -327,6 +328,12 @@ process_complex_native_args(LispFunction *fobj, LispVal *args,
|
||||
return PROCESS_ARGS_OK;
|
||||
}
|
||||
|
||||
static noreturn void signal_argument_error(enum ProcessArgsResult res) {
|
||||
const char *c_msg = process_args_strerror(res);
|
||||
LispVal *msg = make_lisp_string(c_msg, strlen(c_msg), false, false);
|
||||
lisp_signal(Qargument_error, LIST(msg));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE LispVal *call_native(LispVal *orig_func,
|
||||
LispFunction *fobj, LispVal *args) {
|
||||
StackFrame *stack_ref = LISP_STACK_REF();
|
||||
@@ -340,11 +347,7 @@ static ALWAYS_INLINE LispVal *call_native(LispVal *orig_func,
|
||||
enum ProcessArgsResult res =
|
||||
process_complex_native_args(fobj, args, arg_arr, &rest_idx);
|
||||
if (res != PROCESS_ARGS_OK) {
|
||||
// TODO better errors
|
||||
printf("Bad arguments to builtin \"");
|
||||
debug_print(stdout, orig_func);
|
||||
printf("\": %s\n", process_args_strerror(res));
|
||||
abort();
|
||||
signal_argument_error(res);
|
||||
}
|
||||
for (intptr_t i = 0; i < count; ++i) {
|
||||
if (!arg_arr[i]) {
|
||||
@@ -461,18 +464,12 @@ call_interpreted(LispVal *orig_func, LispFunction *fobj, LispVal *args) {
|
||||
enum ProcessArgsResult par =
|
||||
push_interpreted_args_to_lexenv(fobj, evaled_args);
|
||||
if (par != PROCESS_ARGS_OK) {
|
||||
// TODO better error handling
|
||||
fprintf(stderr, "Bad args to interp func: %s\n",
|
||||
process_args_strerror(par));
|
||||
abort();
|
||||
signal_argument_error(par);
|
||||
}
|
||||
return UNWIND_AND_RETURN(stack_ref, Fprogn(fobj->impl.interp.body));
|
||||
}
|
||||
|
||||
DEFUN(funcall, "funcall", (LispVal * func, LispVal *args), "(func &rest args)",
|
||||
"") {
|
||||
StackFrame *stack_ref = LISP_STACK_REF();
|
||||
push_call_frame(func, args);
|
||||
static LispFunction *coerce_to_function(LispVal *func) {
|
||||
LispFunction *fobj = func;
|
||||
if (SYMBOLP(func)) {
|
||||
fobj = Fsymbol_function(func, Qt);
|
||||
@@ -480,15 +477,19 @@ DEFUN(funcall, "funcall", (LispVal * func, LispVal *args), "(func &rest args)",
|
||||
fobj = Feval(func, Vlexical_environment);
|
||||
}
|
||||
if (NILP(fobj)) {
|
||||
// TODO throw exception
|
||||
fprintf(stderr, "Not a function: ");
|
||||
debug_print(stderr, func);
|
||||
fputc('\n', stderr);
|
||||
abort();
|
||||
signal_type_error(fobj, LIST(Qcallable));
|
||||
}
|
||||
// include symbol here for the error message
|
||||
CHECK_TYPE(fobj, TYPE_FUNCTION, TYPE_SYMBOL);
|
||||
assert(FUNCTIONP(fobj));
|
||||
return fobj;
|
||||
}
|
||||
|
||||
DEFUN(funcall, "funcall", (LispVal * func, LispVal *args), "(func &rest args)",
|
||||
"") {
|
||||
StackFrame *stack_ref = LISP_STACK_REF();
|
||||
push_call_frame(func, args);
|
||||
LispFunction *fobj = coerce_to_function(func);
|
||||
switch (fobj->type) {
|
||||
case FUNCTION_NATIVE:
|
||||
return UNWIND_AND_RETURN(stack_ref, call_native(func, fobj, args));
|
||||
@@ -506,9 +507,9 @@ static LispVal *parse_lambda_declare_form(LispFunction *fobj, LispVal *body) {
|
||||
if (EQ(XCAR(decl), Qname)) {
|
||||
CHECK_TYPE(SECOND(decl), TYPE_SYMBOL);
|
||||
if (!list_length_eq(decl, 2)) {
|
||||
// TODO better error
|
||||
fprintf(stderr, "Invalid (declare (name ...)) form!\n");
|
||||
abort();
|
||||
lisp_signal(
|
||||
Qfunction_declare_form_error,
|
||||
LIST(LISP_LITSTR("Invalid (declare (name ...)) form")));
|
||||
}
|
||||
fobj->name = SECOND(decl);
|
||||
}
|
||||
@@ -523,12 +524,9 @@ DEFSPECIAL(lambda, "lambda", (LispVal * args, LispVal *body),
|
||||
LambdaListParseResult llpr;
|
||||
parse_lambda_list(&llpr, args);
|
||||
if (llpr.status != LLPS_OK) {
|
||||
// TODO better handling
|
||||
fprintf(stderr,
|
||||
"Lambda list parse error: %s: ", llps_strerror(llpr.status));
|
||||
debug_print(stderr, args);
|
||||
fputc('\n', stderr);
|
||||
abort();
|
||||
const char *c_msg = llps_strerror(llpr.status);
|
||||
LispVal *msg = make_lisp_string(c_msg, strlen(c_msg), false, false);
|
||||
lisp_signal(Qlambda_list_error, msg);
|
||||
}
|
||||
CHECK_LISTP(body);
|
||||
LispFunction *fobj = lisp_alloc_object(sizeof(LispFunction), TYPE_FUNCTION);
|
||||
@@ -549,5 +547,37 @@ DEFSPECIAL(lambda, "lambda", (LispVal * args, LispVal *body),
|
||||
return fobj;
|
||||
}
|
||||
|
||||
DEFUN(callablep, "callablep", (LispVal * obj), "(obj)", "") {
|
||||
if (FUNCTIONP(obj) || (CONSP(obj) && EQ(XCAR(obj), Qlambda))
|
||||
|| (SYMBOLP(obj) && FUNCTIONP(Fsymbol_function(obj, Qt)))) {
|
||||
return Qt;
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
DEFUN(function_arity, "function-arity", (LispVal * func), "(func)",
|
||||
"Return a list of the form (NUM-REQ NUM-OPT KW-NAMES HAS-REST).") {
|
||||
LispFunction *fobj = coerce_to_function(func);
|
||||
LispVal *kw = Qnil;
|
||||
if (HASH_TABLE_P(fobj->args.kw)) {
|
||||
HT_FOREACH_INDEX(fobj->args.kw, i) {
|
||||
kw = CONS(SECOND(HASH_VALUE(fobj->args.kw, i)), kw);
|
||||
}
|
||||
}
|
||||
return LIST(MAKE_FIXNUM(fobj->args.n_req), MAKE_FIXNUM(fobj->args.n_opt),
|
||||
kw, NILP(fobj->args.rest) ? Qnil : Qt);
|
||||
}
|
||||
|
||||
DEFINE_SYMBOL(declare, "declare");
|
||||
DEFINE_SYMBOL(name, "name");
|
||||
|
||||
DEFINE_SYMBOL(callable, "callable");
|
||||
DEFINE_SYMBOL(argument_error, "argument-error");
|
||||
DEFINE_CONDITION_CLASS(argument_error, error);
|
||||
|
||||
DEFINE_SYMBOL(function_definition_error, "function-definition-error");
|
||||
DEFINE_CONDITION_CLASS(function_definition_error, error);
|
||||
DEFINE_SYMBOL(lambda_list_error, "lambda-list-error");
|
||||
DEFINE_CONDITION_CLASS(lambda_list_error, function_definition_error);
|
||||
DEFINE_SYMBOL(function_declare_form_error, "function-declare-form-error");
|
||||
DEFINE_CONDITION_CLASS(function_declare_form_error, function_definition_error);
|
||||
|
||||
Reference in New Issue
Block a user