More exception stuff
This commit is contained in:
+1
-5
@@ -1,7 +1,3 @@
|
|||||||
;; -*- mode: lisp-data -*-
|
;; -*- mode: lisp-data -*-
|
||||||
|
|
||||||
(fset 'test-fun (lambda (x)
|
(function-arity (lambda (y &optional x x)))
|
||||||
(error (list x))))
|
|
||||||
|
|
||||||
(test-fun "hi")
|
|
||||||
|
|
||||||
|
|||||||
+10
-4
@@ -173,8 +173,7 @@ DEFUN(set, "set", (LispVal * sym, LispVal *value), "(sym value)", "") {
|
|||||||
DEFUN(fset, "fset", (LispVal * sym, LispVal *value), "(sym value)", "") {
|
DEFUN(fset, "fset", (LispVal * sym, LispVal *value), "(sym value)", "") {
|
||||||
CHECK_TYPE(sym, TYPE_SYMBOL);
|
CHECK_TYPE(sym, TYPE_SYMBOL);
|
||||||
if (CONST_FUNCTION_P(sym)) {
|
if (CONST_FUNCTION_P(sym)) {
|
||||||
// TODO throw
|
signal_value_constant(sym);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
((LispSymbol *) sym)->function = value;
|
((LispSymbol *) sym)->function = value;
|
||||||
MARK_OBJECT_ADDED(value, sym);
|
MARK_OBJECT_ADDED(value, sym);
|
||||||
@@ -199,6 +198,10 @@ DEFUN(put, "put", (LispVal * sym, LispVal *key, LispVal *val), "(sym key val)",
|
|||||||
return Fsetplist(sym, Fplist_put(Fsymbol_plist(sym), key, val));
|
return Fsetplist(sym, Fplist_put(Fsymbol_plist(sym), key, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
noreturn void signal_value_constant(LispVal *value) {
|
||||||
|
lisp_signal(Qvalue_constant_error, LIST(value));
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_SYMBOL(fixnum, "fixnum");
|
DEFINE_SYMBOL(fixnum, "fixnum");
|
||||||
DEFINE_SYMBOL(float, "float");
|
DEFINE_SYMBOL(float, "float");
|
||||||
// cons defined in list.c
|
// cons defined in list.c
|
||||||
@@ -275,8 +278,8 @@ static void check_handler_bind_handlers(LispVal *handlers) {
|
|||||||
DOLIST(handler, handlers) {
|
DOLIST(handler, handlers) {
|
||||||
CHECK_LISTP(handler);
|
CHECK_LISTP(handler);
|
||||||
if (!list_length_eq(handler, 2)) {
|
if (!list_length_eq(handler, 2)) {
|
||||||
// TODO error
|
lisp_signal(Qargument_error,
|
||||||
abort();
|
LIST(LISP_LITSTR("Wrong number of arguments.")));
|
||||||
}
|
}
|
||||||
CHECK_TYPE(XCDR(handler), TYPE_FUNCTION);
|
CHECK_TYPE(XCDR(handler), TYPE_FUNCTION);
|
||||||
if (LISTP(XCAR(handler))) {
|
if (LISTP(XCAR(handler))) {
|
||||||
@@ -330,6 +333,9 @@ DEFINE_CONDITION_CLASS(error, t);
|
|||||||
DEFINE_SYMBOL(type_error, "type-error");
|
DEFINE_SYMBOL(type_error, "type-error");
|
||||||
DEFINE_CONDITION_CLASS(type_error, error);
|
DEFINE_CONDITION_CLASS(type_error, error);
|
||||||
|
|
||||||
|
DEFINE_SYMBOL(value_constant_error, "value-constant-error");
|
||||||
|
DEFINE_CONDITION_CLASS(value_constant_error, error);
|
||||||
|
|
||||||
DEFINE_SYMBOL(backquote, "`");
|
DEFINE_SYMBOL(backquote, "`");
|
||||||
DEFINE_SYMBOL(comma, ",");
|
DEFINE_SYMBOL(comma, ",");
|
||||||
DEFINE_SYMBOL(comma_at, ",@");
|
DEFINE_SYMBOL(comma_at, ",@");
|
||||||
|
|||||||
+7
-3
@@ -353,6 +353,8 @@ DECLARE_FUNCTION(setplist, (LispVal * sym, LispVal *plist));
|
|||||||
DECLARE_FUNCTION(get, (LispVal * sym, LispVal *key, LispVal *def));
|
DECLARE_FUNCTION(get, (LispVal * sym, LispVal *key, LispVal *def));
|
||||||
DECLARE_FUNCTION(put, (LispVal * sym, LispVal *key, LispVal *val));
|
DECLARE_FUNCTION(put, (LispVal * sym, LispVal *key, LispVal *val));
|
||||||
|
|
||||||
|
noreturn void signal_value_constant(LispVal *value);
|
||||||
|
|
||||||
static ALWAYS_INLINE LispVal *SYMBOL_VALUE(LispVal *sym) {
|
static ALWAYS_INLINE LispVal *SYMBOL_VALUE(LispVal *sym) {
|
||||||
assert(SYMBOLP(sym));
|
assert(SYMBOLP(sym));
|
||||||
LispSymbol *s = (LispSymbol *) sym;
|
LispSymbol *s = (LispSymbol *) sym;
|
||||||
@@ -379,12 +381,11 @@ static ALWAYS_INLINE bool DYNAMIC_SYMBOL_P(LispVal *sym) {
|
|||||||
return ((LispSymbol *) sym)->flags & SYMBOL_DYNAMIC;
|
return ((LispSymbol *) sym)->flags & SYMBOL_DYNAMIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE void SET_SYMBOL_VALUE(LispVal *sym, LispVal *value) {
|
static inline void SET_SYMBOL_VALUE(LispVal *sym, LispVal *value) {
|
||||||
assert(SYMBOLP(sym));
|
assert(SYMBOLP(sym));
|
||||||
LispSymbol *s = (LispSymbol *) sym;
|
LispSymbol *s = (LispSymbol *) sym;
|
||||||
if (CONST_VALUE_P(sym)) {
|
if (CONST_VALUE_P(sym)) {
|
||||||
// TODO throw
|
signal_value_constant(sym);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
switch (s->value_type) {
|
switch (s->value_type) {
|
||||||
case SYMBOL_NORMAL:
|
case SYMBOL_NORMAL:
|
||||||
@@ -425,6 +426,9 @@ MAKE_CONDITION_CLASS(error);
|
|||||||
DECLARE_SYMBOL(type_error);
|
DECLARE_SYMBOL(type_error);
|
||||||
MAKE_CONDITION_CLASS(type_error);
|
MAKE_CONDITION_CLASS(type_error);
|
||||||
|
|
||||||
|
DECLARE_SYMBOL(value_constant_error);
|
||||||
|
MAKE_CONDITION_CLASS(value_constant_error);
|
||||||
|
|
||||||
// Defined in lisp code (eventually) but used in read.c
|
// Defined in lisp code (eventually) but used in read.c
|
||||||
DECLARE_SYMBOL(backquote);
|
DECLARE_SYMBOL(backquote);
|
||||||
DECLARE_SYMBOL(comma);
|
DECLARE_SYMBOL(comma);
|
||||||
|
|||||||
+57
-27
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "hashtable.h"
|
#include "hashtable.h"
|
||||||
#include "lisp.h"
|
#include "lisp.h"
|
||||||
|
#include "lisp_string.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "read.h"
|
#include "read.h"
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
@@ -327,6 +328,12 @@ process_complex_native_args(LispFunction *fobj, LispVal *args,
|
|||||||
return PROCESS_ARGS_OK;
|
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,
|
static ALWAYS_INLINE LispVal *call_native(LispVal *orig_func,
|
||||||
LispFunction *fobj, LispVal *args) {
|
LispFunction *fobj, LispVal *args) {
|
||||||
StackFrame *stack_ref = LISP_STACK_REF();
|
StackFrame *stack_ref = LISP_STACK_REF();
|
||||||
@@ -340,11 +347,7 @@ static ALWAYS_INLINE LispVal *call_native(LispVal *orig_func,
|
|||||||
enum ProcessArgsResult res =
|
enum ProcessArgsResult res =
|
||||||
process_complex_native_args(fobj, args, arg_arr, &rest_idx);
|
process_complex_native_args(fobj, args, arg_arr, &rest_idx);
|
||||||
if (res != PROCESS_ARGS_OK) {
|
if (res != PROCESS_ARGS_OK) {
|
||||||
// TODO better errors
|
signal_argument_error(res);
|
||||||
printf("Bad arguments to builtin \"");
|
|
||||||
debug_print(stdout, orig_func);
|
|
||||||
printf("\": %s\n", process_args_strerror(res));
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
for (intptr_t i = 0; i < count; ++i) {
|
for (intptr_t i = 0; i < count; ++i) {
|
||||||
if (!arg_arr[i]) {
|
if (!arg_arr[i]) {
|
||||||
@@ -461,18 +464,12 @@ call_interpreted(LispVal *orig_func, LispFunction *fobj, LispVal *args) {
|
|||||||
enum ProcessArgsResult par =
|
enum ProcessArgsResult par =
|
||||||
push_interpreted_args_to_lexenv(fobj, evaled_args);
|
push_interpreted_args_to_lexenv(fobj, evaled_args);
|
||||||
if (par != PROCESS_ARGS_OK) {
|
if (par != PROCESS_ARGS_OK) {
|
||||||
// TODO better error handling
|
signal_argument_error(par);
|
||||||
fprintf(stderr, "Bad args to interp func: %s\n",
|
|
||||||
process_args_strerror(par));
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
return UNWIND_AND_RETURN(stack_ref, Fprogn(fobj->impl.interp.body));
|
return UNWIND_AND_RETURN(stack_ref, Fprogn(fobj->impl.interp.body));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN(funcall, "funcall", (LispVal * func, LispVal *args), "(func &rest args)",
|
static LispFunction *coerce_to_function(LispVal *func) {
|
||||||
"") {
|
|
||||||
StackFrame *stack_ref = LISP_STACK_REF();
|
|
||||||
push_call_frame(func, args);
|
|
||||||
LispFunction *fobj = func;
|
LispFunction *fobj = func;
|
||||||
if (SYMBOLP(func)) {
|
if (SYMBOLP(func)) {
|
||||||
fobj = Fsymbol_function(func, Qt);
|
fobj = Fsymbol_function(func, Qt);
|
||||||
@@ -480,15 +477,19 @@ DEFUN(funcall, "funcall", (LispVal * func, LispVal *args), "(func &rest args)",
|
|||||||
fobj = Feval(func, Vlexical_environment);
|
fobj = Feval(func, Vlexical_environment);
|
||||||
}
|
}
|
||||||
if (NILP(fobj)) {
|
if (NILP(fobj)) {
|
||||||
// TODO throw exception
|
signal_type_error(fobj, LIST(Qcallable));
|
||||||
fprintf(stderr, "Not a function: ");
|
|
||||||
debug_print(stderr, func);
|
|
||||||
fputc('\n', stderr);
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
// include symbol here for the error message
|
// include symbol here for the error message
|
||||||
CHECK_TYPE(fobj, TYPE_FUNCTION, TYPE_SYMBOL);
|
CHECK_TYPE(fobj, TYPE_FUNCTION, TYPE_SYMBOL);
|
||||||
assert(FUNCTIONP(fobj));
|
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) {
|
switch (fobj->type) {
|
||||||
case FUNCTION_NATIVE:
|
case FUNCTION_NATIVE:
|
||||||
return UNWIND_AND_RETURN(stack_ref, call_native(func, fobj, args));
|
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)) {
|
if (EQ(XCAR(decl), Qname)) {
|
||||||
CHECK_TYPE(SECOND(decl), TYPE_SYMBOL);
|
CHECK_TYPE(SECOND(decl), TYPE_SYMBOL);
|
||||||
if (!list_length_eq(decl, 2)) {
|
if (!list_length_eq(decl, 2)) {
|
||||||
// TODO better error
|
lisp_signal(
|
||||||
fprintf(stderr, "Invalid (declare (name ...)) form!\n");
|
Qfunction_declare_form_error,
|
||||||
abort();
|
LIST(LISP_LITSTR("Invalid (declare (name ...)) form")));
|
||||||
}
|
}
|
||||||
fobj->name = SECOND(decl);
|
fobj->name = SECOND(decl);
|
||||||
}
|
}
|
||||||
@@ -523,12 +524,9 @@ DEFSPECIAL(lambda, "lambda", (LispVal * args, LispVal *body),
|
|||||||
LambdaListParseResult llpr;
|
LambdaListParseResult llpr;
|
||||||
parse_lambda_list(&llpr, args);
|
parse_lambda_list(&llpr, args);
|
||||||
if (llpr.status != LLPS_OK) {
|
if (llpr.status != LLPS_OK) {
|
||||||
// TODO better handling
|
const char *c_msg = llps_strerror(llpr.status);
|
||||||
fprintf(stderr,
|
LispVal *msg = make_lisp_string(c_msg, strlen(c_msg), false, false);
|
||||||
"Lambda list parse error: %s: ", llps_strerror(llpr.status));
|
lisp_signal(Qlambda_list_error, msg);
|
||||||
debug_print(stderr, args);
|
|
||||||
fputc('\n', stderr);
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
CHECK_LISTP(body);
|
CHECK_LISTP(body);
|
||||||
LispFunction *fobj = lisp_alloc_object(sizeof(LispFunction), TYPE_FUNCTION);
|
LispFunction *fobj = lisp_alloc_object(sizeof(LispFunction), TYPE_FUNCTION);
|
||||||
@@ -549,5 +547,37 @@ DEFSPECIAL(lambda, "lambda", (LispVal * args, LispVal *body),
|
|||||||
return fobj;
|
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(declare, "declare");
|
||||||
DEFINE_SYMBOL(name, "name");
|
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);
|
||||||
|
|||||||
@@ -94,8 +94,21 @@ DECLARE_FUNCTION(funcall, (LispVal * func, LispVal *args));
|
|||||||
#define CALL0(func) (Ffuncall((func), Qnil))
|
#define CALL0(func) (Ffuncall((func), Qnil))
|
||||||
|
|
||||||
DECLARE_FUNCTION(lambda, (LispVal * args, LispVal *body));
|
DECLARE_FUNCTION(lambda, (LispVal * args, LispVal *body));
|
||||||
|
DECLARE_FUNCTION(callablep, (LispVal * obj));
|
||||||
|
DECLARE_FUNCTION(function_arity, (LispVal * func));
|
||||||
|
|
||||||
DECLARE_SYMBOL(declare);
|
DECLARE_SYMBOL(declare);
|
||||||
DECLARE_SYMBOL(name);
|
DECLARE_SYMBOL(name);
|
||||||
|
|
||||||
|
DECLARE_SYMBOL(callable);
|
||||||
|
DECLARE_SYMBOL(argument_error);
|
||||||
|
MAKE_CONDITION_CLASS(argument_error);
|
||||||
|
|
||||||
|
DECLARE_SYMBOL(function_definition_error);
|
||||||
|
MAKE_CONDITION_CLASS(function_definition_error);
|
||||||
|
DECLARE_SYMBOL(lambda_list_error);
|
||||||
|
MAKE_CONDITION_CLASS(lambda_list_error);
|
||||||
|
DECLARE_SYMBOL(function_declare_form_error);
|
||||||
|
MAKE_CONDITION_CLASS(function_declare_form_error);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+11
-5
@@ -1,5 +1,6 @@
|
|||||||
#include "hashtable.h"
|
#include "hashtable.h"
|
||||||
|
|
||||||
|
#include "lisp.h"
|
||||||
#include "lisp_string.h"
|
#include "lisp_string.h"
|
||||||
|
|
||||||
#define INITIAL_SIZE 32
|
#define INITIAL_SIZE 32
|
||||||
@@ -49,9 +50,11 @@ static uintptr_t hash_key_for_table(LispHashTable *ht, LispVal *key) {
|
|||||||
return (uintptr_t) key;
|
return (uintptr_t) key;
|
||||||
} else if (ht->hash_fn == Qhash_string) { // needed for initialization
|
} else if (ht->hash_fn == Qhash_string) { // needed for initialization
|
||||||
return XFIXNUM(Fhash_string(key));
|
return XFIXNUM(Fhash_string(key));
|
||||||
|
} else {
|
||||||
|
LispVal *hash = CALL(ht->hash_fn, key);
|
||||||
|
CHECK_TYPE(hash, TYPE_FIXNUM);
|
||||||
|
return XFIXNUM(hash);
|
||||||
}
|
}
|
||||||
// TODO change
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compare_keys(LispHashTable *ht, LispVal *key1, LispVal *key2) {
|
static bool compare_keys(LispHashTable *ht, LispVal *key1, LispVal *key2) {
|
||||||
@@ -59,9 +62,9 @@ static bool compare_keys(LispHashTable *ht, LispVal *key1, LispVal *key2) {
|
|||||||
return EQ(key1, key2);
|
return EQ(key1, key2);
|
||||||
} else if (ht->eq_fn == Qstrings_equal) { // needed for initialization
|
} else if (ht->eq_fn == Qstrings_equal) { // needed for initialization
|
||||||
return !NILP(Fstrings_equal(key1, key2));
|
return !NILP(Fstrings_equal(key1, key2));
|
||||||
|
} else {
|
||||||
|
return !NILP(CALL(ht->eq_fn, key1, key2));
|
||||||
}
|
}
|
||||||
// TODO change
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct HashTableBucket *
|
static struct HashTableBucket *
|
||||||
@@ -101,9 +104,9 @@ static void maybe_rehash(LispHashTable *ht) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO type checking
|
|
||||||
DEFUN(gethash, "gethash", (LispVal * ht, LispVal *key, LispVal *def),
|
DEFUN(gethash, "gethash", (LispVal * ht, LispVal *key, LispVal *def),
|
||||||
"(ht key &optional def)", "") {
|
"(ht key &optional def)", "") {
|
||||||
|
CHECK_TYPE(ht, TYPE_HASH_TABLE);
|
||||||
LispHashTable *obj = ht;
|
LispHashTable *obj = ht;
|
||||||
if (obj->cache_bucket && key == obj->cache_bucket->key) {
|
if (obj->cache_bucket && key == obj->cache_bucket->key) {
|
||||||
return obj->cache_bucket->value;
|
return obj->cache_bucket->value;
|
||||||
@@ -116,6 +119,7 @@ DEFUN(gethash, "gethash", (LispVal * ht, LispVal *key, LispVal *def),
|
|||||||
|
|
||||||
DEFUN(puthash, "puthash", (LispVal * ht, LispVal *key, LispVal *val),
|
DEFUN(puthash, "puthash", (LispVal * ht, LispVal *key, LispVal *val),
|
||||||
"(ht key val)", "") {
|
"(ht key val)", "") {
|
||||||
|
CHECK_TYPE(ht, TYPE_HASH_TABLE);
|
||||||
LispHashTable *obj = ht;
|
LispHashTable *obj = ht;
|
||||||
if (obj->cache_bucket && key == obj->cache_bucket->key) {
|
if (obj->cache_bucket && key == obj->cache_bucket->key) {
|
||||||
obj->cache_bucket->value = val;
|
obj->cache_bucket->value = val;
|
||||||
@@ -138,6 +142,7 @@ DEFUN(puthash, "puthash", (LispVal * ht, LispVal *key, LispVal *val),
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEFUN(remhash, "remhash", (LispVal * ht, LispVal *key), "(ht key)", "") {
|
DEFUN(remhash, "remhash", (LispVal * ht, LispVal *key), "(ht key)", "") {
|
||||||
|
CHECK_TYPE(ht, TYPE_HASH_TABLE);
|
||||||
LispHashTable *obj = ht;
|
LispHashTable *obj = ht;
|
||||||
uintptr_t hash = hash_key_for_table(ht, key);
|
uintptr_t hash = hash_key_for_table(ht, key);
|
||||||
struct HashTableBucket *b;
|
struct HashTableBucket *b;
|
||||||
@@ -170,5 +175,6 @@ DEFUN(remhash, "remhash", (LispVal * ht, LispVal *key), "(ht key)", "") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEFUN(hash_table_count, "hash-table-count", (LispVal * ht), "(ht)", "") {
|
DEFUN(hash_table_count, "hash-table-count", (LispVal * ht), "(ht)", "") {
|
||||||
|
CHECK_TYPE(ht, TYPE_HASH_TABLE);
|
||||||
return MAKE_FIXNUM(((LispHashTable *) ht)->count);
|
return MAKE_FIXNUM(((LispHashTable *) ht)->count);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-11
@@ -79,11 +79,7 @@ static inline LispVal *lookup_variable(LispSymbol *name, LispVal *lexenv) {
|
|||||||
return lexval;
|
return lexval;
|
||||||
}
|
}
|
||||||
if (SYMBOL_VALUE(name) == Qunbound) {
|
if (SYMBOL_VALUE(name) == Qunbound) {
|
||||||
// TODO better error
|
lisp_signal(Qunbound_variable_error, LIST(name));
|
||||||
printf("Unbound symbol: ");
|
|
||||||
debug_print(stdout, name);
|
|
||||||
fputc('\n', stdout);
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
return SYMBOL_VALUE(name);
|
return SYMBOL_VALUE(name);
|
||||||
}
|
}
|
||||||
@@ -133,8 +129,8 @@ DEFSPECIAL(progn, "progn", (LispVal * forms), "(&rest forms)", "") {
|
|||||||
DEFSPECIAL(setq, "setq", (LispVal * bindings), "(&rest bindings)", "") {
|
DEFSPECIAL(setq, "setq", (LispVal * bindings), "(&rest bindings)", "") {
|
||||||
size_t nbindings = list_length(bindings);
|
size_t nbindings = list_length(bindings);
|
||||||
if (nbindings < 2 || (nbindings & 1) != 0) {
|
if (nbindings < 2 || (nbindings & 1) != 0) {
|
||||||
// TODO error
|
lisp_signal(Qargument_error,
|
||||||
abort();
|
LIST(LISP_LITSTR("Wrong number of arguments.")));
|
||||||
}
|
}
|
||||||
LispVal *value = Qnil;
|
LispVal *value = Qnil;
|
||||||
for (LispVal *rest = bindings; !NILP(bindings);
|
for (LispVal *rest = bindings; !NILP(bindings);
|
||||||
@@ -153,13 +149,11 @@ DEFSPECIAL(let, "let", (LispVal * bindings, LispVal *body),
|
|||||||
DOLIST(binding, bindings) {
|
DOLIST(binding, bindings) {
|
||||||
if (CONSP(binding) && list_length_eq(binding, 2)) {
|
if (CONSP(binding) && list_length_eq(binding, 2)) {
|
||||||
if (!SYMBOLP(XCAR(binding))) {
|
if (!SYMBOLP(XCAR(binding))) {
|
||||||
// TODO better error
|
signal_type_error(XCAR(binding), LIST(Qsymbol));
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
RPLACA(XCDR(binding), Feval(SECOND(binding), Vlexical_environment));
|
RPLACA(XCDR(binding), Feval(SECOND(binding), Vlexical_environment));
|
||||||
} else if (!SYMBOLP(binding)) {
|
} else if (!SYMBOLP(binding)) {
|
||||||
// TODO better error
|
signal_type_error(binding, LIST(Qsymbol));
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
push_copy_lexenv();
|
push_copy_lexenv();
|
||||||
@@ -209,3 +203,6 @@ DEFSPECIAL(or, "or", (LispVal * forms), "(&rest forms)", "") {
|
|||||||
DEFUN(null, "null", (LispVal * datum), "(datum)", "") {
|
DEFUN(null, "null", (LispVal * datum), "(datum)", "") {
|
||||||
return NILP(datum) ? Qt : Qnil;
|
return NILP(datum) ? Qt : Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_SYMBOL(unbound_variable_error, "unbound-variable-error");
|
||||||
|
DEFINE_CONDITION_CLASS(unbound_variable_error, error);
|
||||||
|
|||||||
@@ -24,4 +24,7 @@ DECLARE_FUNCTION(and, (LispVal * forms));
|
|||||||
DECLARE_FUNCTION(or, (LispVal * forms));
|
DECLARE_FUNCTION(or, (LispVal * forms));
|
||||||
DECLARE_FUNCTION(null, (LispVal * datum));
|
DECLARE_FUNCTION(null, (LispVal * datum));
|
||||||
|
|
||||||
|
DECLARE_SYMBOL(unbound_variable_error);
|
||||||
|
MAKE_CONDITION_CLASS(unbound_variable_error);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+29
-2
@@ -1,5 +1,7 @@
|
|||||||
#include "lisp_string.h"
|
#include "lisp_string.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
LispVal *make_lisp_string(const char *data, size_t length, bool take,
|
LispVal *make_lisp_string(const char *data, size_t length, bool take,
|
||||||
@@ -17,9 +19,24 @@ LispVal *make_lisp_string(const char *data, size_t length, bool take,
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LispVal *lisp_sprintf(const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
va_list args2;
|
||||||
|
va_copy(args2, args);
|
||||||
|
int needed = vsnprintf(NULL, 0, format, args2);
|
||||||
|
va_end(args2);
|
||||||
|
char *buffer = lisp_malloc(needed + 1);
|
||||||
|
int printed = vsnprintf(buffer, needed + 1, format, args);
|
||||||
|
va_end(args);
|
||||||
|
assert(printed == needed);
|
||||||
|
return make_lisp_string(buffer, printed, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN(strings_equal, "strings-equal", (LispVal * string1, LispVal *string2),
|
DEFUN(strings_equal, "strings-equal", (LispVal * string1, LispVal *string2),
|
||||||
"(string1 string2)", "") {
|
"(string1 string2)", "") {
|
||||||
// TODO type checking
|
CHECK_TYPE(string1, TYPE_STRING);
|
||||||
|
CHECK_TYPE(string2, TYPE_STRING);
|
||||||
if (((LispString *) string1)->length != ((LispString *) string2)->length) {
|
if (((LispString *) string1)->length != ((LispString *) string2)->length) {
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
@@ -32,7 +49,7 @@ DEFUN(strings_equal, "strings-equal", (LispVal * string1, LispVal *string2),
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEFUN(hash_string, "hash-string", (LispVal * string), "(string)", "") {
|
DEFUN(hash_string, "hash-string", (LispVal * string), "(string)", "") {
|
||||||
// TODO type checking
|
CHECK_TYPE(string, TYPE_STRING);
|
||||||
size_t len = ((LispString *) string)->length;
|
size_t len = ((LispString *) string)->length;
|
||||||
const char *str = ((LispString *) string)->data;
|
const char *str = ((LispString *) string)->data;
|
||||||
uintptr_t hash = 5381;
|
uintptr_t hash = 5381;
|
||||||
@@ -41,3 +58,13 @@ DEFUN(hash_string, "hash-string", (LispVal * string), "(string)", "") {
|
|||||||
}
|
}
|
||||||
return MAKE_FIXNUM(hash);
|
return MAKE_FIXNUM(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN(charp, "charp", (LispVal * obj), "(obj)", "") {
|
||||||
|
if (!FIXNUMP(obj)) {
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
fixnum_t val = XFIXNUM(obj);
|
||||||
|
return (val >= 0 && val <= 255) ? Qt : Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_SYMBOL(char, "char");
|
||||||
|
|||||||
@@ -10,7 +10,12 @@ LispVal *make_lisp_string(const char *data, size_t length, bool take,
|
|||||||
#define LISP_LITSTR(litstr) \
|
#define LISP_LITSTR(litstr) \
|
||||||
(make_lisp_string(litstr, sizeof(litstr) - 1, false, false))
|
(make_lisp_string(litstr, sizeof(litstr) - 1, false, false))
|
||||||
|
|
||||||
|
LispVal *lisp_sprintf(const char *format, ...) FORMAT(1, 2);
|
||||||
|
|
||||||
DECLARE_FUNCTION(strings_equal, (LispVal * string1, LispVal *string2));
|
DECLARE_FUNCTION(strings_equal, (LispVal * string1, LispVal *string2));
|
||||||
DECLARE_FUNCTION(hash_string, (LispVal * string));
|
DECLARE_FUNCTION(hash_string, (LispVal * string));
|
||||||
|
|
||||||
|
DECLARE_FUNCTION(charp, (LispVal * obj));
|
||||||
|
DECLARE_SYMBOL(char);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -37,9 +37,13 @@ int main(int argc, const char **argv) {
|
|||||||
LispVal *args = FOURTH(frame);
|
LispVal *args = FOURTH(frame);
|
||||||
fprintf(stderr, " %c ", evaled ? '-' : '*');
|
fprintf(stderr, " %c ", evaled ? '-' : '*');
|
||||||
Fprinc(name, Qerror_write_byte);
|
Fprinc(name, Qerror_write_byte);
|
||||||
|
if (NILP(args)) {
|
||||||
|
fprintf(stderr, "()\n");
|
||||||
|
} else {
|
||||||
Fprinc(args, Qerror_write_byte);
|
Fprinc(args, Qerror_write_byte);
|
||||||
fputc('\n', stderr);
|
fputc('\n', stderr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
CLEAR_EXCEPTION();
|
CLEAR_EXCEPTION();
|
||||||
had_toplevel_error = true;
|
had_toplevel_error = true;
|
||||||
goto toplevel_error;
|
goto toplevel_error;
|
||||||
|
|||||||
+34
-10
@@ -14,16 +14,17 @@ DEFVAR(print_base, "print-base", "", MAKE_FIXNUM(10));
|
|||||||
DEFVAR(print_base_upper, "print-base-upper", "", Qt);
|
DEFVAR(print_base_upper, "print-base-upper", "", Qt);
|
||||||
DEFVAR(print_precision, "print-precision", "", MAKE_FIXNUM(6));
|
DEFVAR(print_precision, "print-precision", "", MAKE_FIXNUM(6));
|
||||||
DEFVAR(print_quoted, "print-quoted", "", Qt);
|
DEFVAR(print_quoted, "print-quoted", "", Qt);
|
||||||
|
DEFVAR(print_empty_list, "print-empty-list", "", Qnil);
|
||||||
|
|
||||||
static void lisp_fputc(LispVal *ch, FILE *file) {
|
static void lisp_fputc(LispVal *ch, FILE *file) {
|
||||||
if (NILP(ch)) {
|
if (NILP(ch)) {
|
||||||
fflush(file);
|
fflush(file);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
CHECK_TYPE(ch, TYPE_FIXNUM);
|
CHECK_TYPE(ch, TYPE_FIXNUM);
|
||||||
fixnum_t f = XFIXNUM(ch);
|
fixnum_t f = XFIXNUM(ch);
|
||||||
if (f < 0 || f > 255) {
|
if (f < 0 || f > 255) {
|
||||||
// TODO error
|
signal_type_error(ch, Qchar);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
fputc(f, file);
|
fputc(f, file);
|
||||||
}
|
}
|
||||||
@@ -47,6 +48,7 @@ struct PrintOptions {
|
|||||||
bool base_upper;
|
bool base_upper;
|
||||||
fixnum_t precision;
|
fixnum_t precision;
|
||||||
bool quoted;
|
bool quoted;
|
||||||
|
bool empty_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PrintContext {
|
struct PrintContext {
|
||||||
@@ -56,6 +58,20 @@ struct PrintContext {
|
|||||||
LispVal *length_stack;
|
LispVal *length_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void check_print_base(fixnum_t base) {
|
||||||
|
switch (base) {
|
||||||
|
case 2:
|
||||||
|
case 8:
|
||||||
|
case 10:
|
||||||
|
case 16:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lisp_signal(
|
||||||
|
Qprint_error,
|
||||||
|
LIST(lisp_sprintf("Invalid base: %" LISP_FIXNUM_PRINTF(d), base)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void init_print_options(struct PrintOptions *opts, bool readable) {
|
static void init_print_options(struct PrintOptions *opts, bool readable) {
|
||||||
opts->readable = readable;
|
opts->readable = readable;
|
||||||
opts->circle = !NILP(Vprint_circular);
|
opts->circle = !NILP(Vprint_circular);
|
||||||
@@ -73,9 +89,7 @@ static void init_print_options(struct PrintOptions *opts, bool readable) {
|
|||||||
}
|
}
|
||||||
CHECK_TYPE(Vprint_base, TYPE_FIXNUM);
|
CHECK_TYPE(Vprint_base, TYPE_FIXNUM);
|
||||||
opts->base = XFIXNUM(Vprint_base);
|
opts->base = XFIXNUM(Vprint_base);
|
||||||
if (opts->base < 2 || opts->base > 16) {
|
check_print_base(opts->base);
|
||||||
opts->base = 10;
|
|
||||||
}
|
|
||||||
opts->base_upper = !NILP(Vprint_base_upper);
|
opts->base_upper = !NILP(Vprint_base_upper);
|
||||||
CHECK_TYPE(Vprint_precision, TYPE_FIXNUM);
|
CHECK_TYPE(Vprint_precision, TYPE_FIXNUM);
|
||||||
opts->precision = XFIXNUM(Vprint_precision);
|
opts->precision = XFIXNUM(Vprint_precision);
|
||||||
@@ -85,6 +99,7 @@ static void init_print_options(struct PrintOptions *opts, bool readable) {
|
|||||||
opts->precision = LISP_FLOAT_MAX_PRECISION;
|
opts->precision = LISP_FLOAT_MAX_PRECISION;
|
||||||
}
|
}
|
||||||
opts->quoted = !NILP(Vprint_quoted);
|
opts->quoted = !NILP(Vprint_quoted);
|
||||||
|
opts->empty_list = !NILP(Vprint_empty_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_print_context(struct PrintContext *restrict pc, bool readable,
|
static void init_print_context(struct PrintContext *restrict pc, bool readable,
|
||||||
@@ -130,7 +145,6 @@ static void print_fixnum_base(struct PrintContext *restrict pc, LispVal *val) {
|
|||||||
print_char(pc, '6');
|
print_char(pc, '6');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// TODO error
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
print_char(pc, '#');
|
print_char(pc, '#');
|
||||||
@@ -139,7 +153,7 @@ static void print_fixnum_base(struct PrintContext *restrict pc, LispVal *val) {
|
|||||||
static void print_fixnum(struct PrintContext *restrict pc, LispVal *val) {
|
static void print_fixnum(struct PrintContext *restrict pc, LispVal *val) {
|
||||||
fixnum_t fn = XFIXNUM(val);
|
fixnum_t fn = XFIXNUM(val);
|
||||||
if (fn == 0) {
|
if (fn == 0) {
|
||||||
Ffuncall(pc->print_char_fun, MAKE_FIXNUM('0'));
|
CALL(pc->print_char_fun, MAKE_FIXNUM('0'));
|
||||||
} else {
|
} else {
|
||||||
if (pc->opts.base != 10 && pc->opts.readable) {
|
if (pc->opts.base != 10 && pc->opts.readable) {
|
||||||
print_fixnum_base(pc, val);
|
print_fixnum_base(pc, val);
|
||||||
@@ -270,6 +284,10 @@ static void print_pretty_string(struct PrintContext *restrict pc,
|
|||||||
|
|
||||||
static void print_readable_symbol(struct PrintContext *restrict pc,
|
static void print_readable_symbol(struct PrintContext *restrict pc,
|
||||||
LispVal *val) {
|
LispVal *val) {
|
||||||
|
if (NILP(val) && pc->opts.empty_list) {
|
||||||
|
print_buffer(pc, "()", 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
LispSymbol *sym = val;
|
LispSymbol *sym = val;
|
||||||
assert(STRINGP(sym->name));
|
assert(STRINGP(sym->name));
|
||||||
LispString *n = sym->name;
|
LispString *n = sym->name;
|
||||||
@@ -292,6 +310,10 @@ static void print_readable_symbol(struct PrintContext *restrict pc,
|
|||||||
|
|
||||||
static void print_pretty_symbol(struct PrintContext *restrict pc,
|
static void print_pretty_symbol(struct PrintContext *restrict pc,
|
||||||
LispVal *val) {
|
LispVal *val) {
|
||||||
|
if (NILP(val) && pc->opts.empty_list) {
|
||||||
|
print_buffer(pc, "()", 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
LispSymbol *sym = val;
|
LispSymbol *sym = val;
|
||||||
assert(STRINGP(sym->name));
|
assert(STRINGP(sym->name));
|
||||||
print_pretty_string(pc, sym->name);
|
print_pretty_string(pc, sym->name);
|
||||||
@@ -405,13 +427,12 @@ DEFUN(print_condition, "print-condition",
|
|||||||
(LispVal * name, LispVal *data, LispVal *print_char_fun),
|
(LispVal * name, LispVal *data, LispVal *print_char_fun),
|
||||||
"(name data &optional print-char-fun)", "") {
|
"(name data &optional print-char-fun)", "") {
|
||||||
if (NILP(Fcondition_class_p(name))) {
|
if (NILP(Fcondition_class_p(name))) {
|
||||||
// TODO type error
|
signal_type_error(name, Qcondition_class);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
LispVal *printer = Fcondition_printer(name);
|
LispVal *printer = Fcondition_printer(name);
|
||||||
if (NILP(printer)) {
|
if (NILP(printer)) {
|
||||||
// default format
|
// default format
|
||||||
Fprinc(CONS(name, data), print_char_fun);
|
Fprin1(CONS(name, data), print_char_fun);
|
||||||
} else {
|
} else {
|
||||||
// custom format
|
// custom format
|
||||||
CALL(printer, data, print_char_fun);
|
CALL(printer, data, print_char_fun);
|
||||||
@@ -419,6 +440,9 @@ DEFUN(print_condition, "print-condition",
|
|||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_SYMBOL(print_error, "print-error");
|
||||||
|
DEFINE_CONDITION_CLASS(print_error, error);
|
||||||
|
|
||||||
void debug_print(FILE *file, LispVal *obj) {
|
void debug_print(FILE *file, LispVal *obj) {
|
||||||
switch (TYPE_OF(obj)) {
|
switch (TYPE_OF(obj)) {
|
||||||
case TYPE_FIXNUM:
|
case TYPE_FIXNUM:
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ DECLARE_VARIABLE(print_base);
|
|||||||
DECLARE_VARIABLE(print_base_upper);
|
DECLARE_VARIABLE(print_base_upper);
|
||||||
DECLARE_VARIABLE(print_precision);
|
DECLARE_VARIABLE(print_precision);
|
||||||
DECLARE_VARIABLE(print_quoted);
|
DECLARE_VARIABLE(print_quoted);
|
||||||
|
DECLARE_VARIABLE(print_empty_list);
|
||||||
|
|
||||||
// For now, a print character function takes nil to mean flush
|
// For now, a print character function takes nil to mean flush
|
||||||
DECLARE_FUNCTION(write_byte, (LispVal * ch));
|
DECLARE_FUNCTION(write_byte, (LispVal * ch));
|
||||||
@@ -26,6 +27,9 @@ DECLARE_FUNCTION(prin1, (LispVal * val, LispVal *print_char_fun));
|
|||||||
DECLARE_FUNCTION(print_condition,
|
DECLARE_FUNCTION(print_condition,
|
||||||
(LispVal * name, LispVal *data, LispVal *print_char_fun));
|
(LispVal * name, LispVal *data, LispVal *print_char_fun));
|
||||||
|
|
||||||
|
DECLARE_SYMBOL(print_error);
|
||||||
|
MAKE_CONDITION_CLASS(print_error);
|
||||||
|
|
||||||
__attribute__((no_sanitize("address"))) void debug_print(FILE *file,
|
__attribute__((no_sanitize("address"))) void debug_print(FILE *file,
|
||||||
LispVal *obj);
|
LispVal *obj);
|
||||||
|
|
||||||
|
|||||||
+8
-7
@@ -56,9 +56,8 @@ void lisp_teardown_stack(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE StackFrame *PUSH_NEW_FRAME(enum StackFrameKind kind) {
|
static ALWAYS_INLINE StackFrame *PUSH_NEW_FRAME(enum StackFrameKind kind) {
|
||||||
if (the_stack.depth == the_stack.max_depth) {
|
if (the_stack.depth == LISP_STACK_SOFT_MAX_DEPTH) {
|
||||||
// TODO error
|
lisp_signal(Qexcessive_lisp_nesting_error, Qnil);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
StackFrame *last_refs =
|
StackFrame *last_refs =
|
||||||
the_stack.depth ? the_stack.frames[the_stack.depth - 1].last_references
|
the_stack.depth ? the_stack.frames[the_stack.depth - 1].last_references
|
||||||
@@ -250,8 +249,7 @@ void push_dynamic_binding(LispVal *name, LispVal *new_value) {
|
|||||||
void set_lexical_variable(LispVal *name, LispVal *value) {
|
void set_lexical_variable(LispVal *name, LispVal *value) {
|
||||||
assert(SYMBOLP(name));
|
assert(SYMBOLP(name));
|
||||||
if (CONST_VALUE_P(name)) {
|
if (CONST_VALUE_P(name)) {
|
||||||
// TODO throw
|
signal_value_constant(name);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
if (DYNAMIC_SYMBOL_P(name)) {
|
if (DYNAMIC_SYMBOL_P(name)) {
|
||||||
SET_SYMBOL_VALUE(name, value);
|
SET_SYMBOL_VALUE(name, value);
|
||||||
@@ -263,8 +261,7 @@ void set_lexical_variable(LispVal *name, LispVal *value) {
|
|||||||
void new_lexical_variable(LispVal *name, LispVal *value) {
|
void new_lexical_variable(LispVal *name, LispVal *value) {
|
||||||
assert(SYMBOLP(name));
|
assert(SYMBOLP(name));
|
||||||
if (CONST_VALUE_P(name)) {
|
if (CONST_VALUE_P(name)) {
|
||||||
// TODO throw
|
signal_value_constant(name);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
if (DYNAMIC_SYMBOL_P(name)) {
|
if (DYNAMIC_SYMBOL_P(name)) {
|
||||||
push_dynamic_binding(name, value);
|
push_dynamic_binding(name, value);
|
||||||
@@ -366,6 +363,7 @@ noreturn void continue_unwinding(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
noreturn void lisp_signal(LispVal *name, LispVal *data) {
|
noreturn void lisp_signal(LispVal *name, LispVal *data) {
|
||||||
|
CHECK_LISTP(data);
|
||||||
if (NILP(Fcondition_class_p(name))) {
|
if (NILP(Fcondition_class_p(name))) {
|
||||||
signal_type_error(name, LIST(Qcondition_class));
|
signal_type_error(name, LIST(Qcondition_class));
|
||||||
}
|
}
|
||||||
@@ -392,3 +390,6 @@ DEFUN(backtrace, "backtrace", (void), "()", "") {
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_SYMBOL(excessive_lisp_nesting_error, "excessive-lisp-nesting-error");
|
||||||
|
DEFINE_CONDITION_CLASS(excessive_lisp_nesting_error, error);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ enum StackFrameKind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define LISP_STACK_MAX_DEPTH 4096
|
#define LISP_STACK_MAX_DEPTH 4096
|
||||||
|
#define LISP_STACK_SOFT_MAX_DEPTH 4000
|
||||||
#define LOCAL_REFERENCES_BLOCK_LENGTH 64
|
#define LOCAL_REFERENCES_BLOCK_LENGTH 64
|
||||||
|
|
||||||
#define LISP_LONGJMP_FOR_UNWIND 1
|
#define LISP_LONGJMP_FOR_UNWIND 1
|
||||||
@@ -231,4 +232,7 @@ DECLARE_FUNCTION(backtrace, (void) );
|
|||||||
} \
|
} \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECLARE_SYMBOL(excessive_lisp_nesting_error);
|
||||||
|
MAKE_CONDITION_CLASS(excessive_lisp_nesting_error);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user