Apply and read errors
This commit is contained in:
+23
-4
@@ -1,6 +1,25 @@
|
|||||||
;; -*- mode: lisp-data -*-
|
;; -*- mode: lisp-data -*-
|
||||||
|
|
||||||
(prin1 (let ((l (block 'c (lambda () (return-from 'd 3)))))
|
(fset 'defmacro (cons 'macro
|
||||||
(block 'c
|
(lambda (name lambda-list &rest body)
|
||||||
(funcall l))))
|
"Define NAME to be a macro."
|
||||||
(write-byte ?\n)
|
(declare (name defmacro))
|
||||||
|
(list 'fset (list 'quote name)
|
||||||
|
(list 'cons
|
||||||
|
(quote 'macro)
|
||||||
|
(list* 'lambda lambda-list
|
||||||
|
(list 'declare (list 'name name))
|
||||||
|
body))))))
|
||||||
|
|
||||||
|
(defmacro defun (name lambda-list &rest body)
|
||||||
|
"Define NAME to be a function."
|
||||||
|
(list 'fset (list 'quote name)
|
||||||
|
(list* 'lambda lambda-list
|
||||||
|
(list 'declare (list 'name name))
|
||||||
|
body)))
|
||||||
|
|
||||||
|
(defun princln (datum &optional print-char-fun)
|
||||||
|
(princ datum print-char-fun)
|
||||||
|
(funcall (or print-char-fun 'write-byte) ?\n))
|
||||||
|
|
||||||
|
(princln (apply 'cons '(a b)))
|
||||||
|
|||||||
+12
-1
@@ -485,6 +485,14 @@ DEFUN(funcall, "funcall", (LispVal * func, LispVal *args), "(func &rest args)",
|
|||||||
return UNWIND_AND_RETURN(stack_ref, raw_funcall(res, args));
|
return UNWIND_AND_RETURN(stack_ref, raw_funcall(res, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN(apply, "apply", (LispVal * func, LispVal *args), "(func &rest args)",
|
||||||
|
"") {
|
||||||
|
if (NILP(args)) {
|
||||||
|
return CALL0(func);
|
||||||
|
}
|
||||||
|
return Ffuncall(func, Flist_star(XCAR(args), XCDR(args)));
|
||||||
|
}
|
||||||
|
|
||||||
static LispVal *parse_lambda_declare_form(LispFunction *fobj, LispVal *body) {
|
static LispVal *parse_lambda_declare_form(LispFunction *fobj, LispVal *body) {
|
||||||
while (CONSP(body) && CONSP(XCAR(body)) && EQ(XCAR(XCAR(body)), Qdeclare)) {
|
while (CONSP(body) && CONSP(XCAR(body)) && EQ(XCAR(XCAR(body)), Qdeclare)) {
|
||||||
LispVal *decls = XCDR(XCAR(body));
|
LispVal *decls = XCDR(XCAR(body));
|
||||||
@@ -588,7 +596,10 @@ DEFUN(special_form_p, "special-form-p", (LispVal * val), "(val)", "") {
|
|||||||
return builtin_function_p(val, true) ? Qt : Qnil;
|
return builtin_function_p(val, true) ? Qt : Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_SYMBOL(declare, "declare");
|
DEFSPECIAL(declare, "declare", (LispVal * forms), "(&rest forms)", "") {
|
||||||
|
lisp_signal(Qerror,
|
||||||
|
LIST(LISP_LITSTR("(declare ...) form in invalid position")));
|
||||||
|
}
|
||||||
DEFINE_SYMBOL(name, "name");
|
DEFINE_SYMBOL(name, "name");
|
||||||
|
|
||||||
DEFINE_SYMBOL(callable, "callable");
|
DEFINE_SYMBOL(callable, "callable");
|
||||||
|
|||||||
+5
-1
@@ -2,6 +2,9 @@
|
|||||||
#define INCLUDED_FUNCTION_H
|
#define INCLUDED_FUNCTION_H
|
||||||
|
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
|
#include "lisp_string.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
DECLARE_SYMBOL(and_optional);
|
DECLARE_SYMBOL(and_optional);
|
||||||
DECLARE_SYMBOL(and_rest);
|
DECLARE_SYMBOL(and_rest);
|
||||||
@@ -95,6 +98,7 @@ LispVal *raw_funcall(LispVal *func, LispVal *args);
|
|||||||
DECLARE_FUNCTION(funcall, (LispVal * func, LispVal *args));
|
DECLARE_FUNCTION(funcall, (LispVal * func, LispVal *args));
|
||||||
#define CALL(func, ...) (Ffuncall((func), LIST(__VA_ARGS__)))
|
#define CALL(func, ...) (Ffuncall((func), LIST(__VA_ARGS__)))
|
||||||
#define CALL0(func) (Ffuncall((func), Qnil))
|
#define CALL0(func) (Ffuncall((func), Qnil))
|
||||||
|
DECLARE_FUNCTION(apply, (LispVal * func, LispVal *args));
|
||||||
|
|
||||||
DECLARE_FUNCTION(lambda, (LispVal * args, LispVal *body));
|
DECLARE_FUNCTION(lambda, (LispVal * args, LispVal *body));
|
||||||
DECLARE_FUNCTION(callablep, (LispVal * obj));
|
DECLARE_FUNCTION(callablep, (LispVal * obj));
|
||||||
@@ -104,7 +108,7 @@ bool builtin_function_p(LispVal *val, bool special_form);
|
|||||||
DECLARE_FUNCTION(builtin_function_p, (LispVal * val));
|
DECLARE_FUNCTION(builtin_function_p, (LispVal * val));
|
||||||
DECLARE_FUNCTION(special_form_p, (LispVal * val));
|
DECLARE_FUNCTION(special_form_p, (LispVal * val));
|
||||||
|
|
||||||
DECLARE_SYMBOL(declare);
|
DECLARE_FUNCTION(declare, (LispVal * forms));
|
||||||
DECLARE_SYMBOL(name);
|
DECLARE_SYMBOL(name);
|
||||||
|
|
||||||
DECLARE_SYMBOL(callable);
|
DECLARE_SYMBOL(callable);
|
||||||
|
|||||||
+6
-1
@@ -22,13 +22,18 @@ LispVal *make_lisp_string(const char *data, size_t length, bool take,
|
|||||||
LispVal *lisp_sprintf(const char *format, ...) {
|
LispVal *lisp_sprintf(const char *format, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
LispVal *s = lisp_vsprintf(format, args);
|
||||||
|
va_end(args);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
LispVal *lisp_vsprintf(const char *format, va_list args) {
|
||||||
va_list args2;
|
va_list args2;
|
||||||
va_copy(args2, args);
|
va_copy(args2, args);
|
||||||
int needed = vsnprintf(NULL, 0, format, args2);
|
int needed = vsnprintf(NULL, 0, format, args2);
|
||||||
va_end(args2);
|
va_end(args2);
|
||||||
char *buffer = lisp_malloc(needed + 1);
|
char *buffer = lisp_malloc(needed + 1);
|
||||||
int printed = vsnprintf(buffer, needed + 1, format, args);
|
int printed = vsnprintf(buffer, needed + 1, format, args);
|
||||||
va_end(args);
|
|
||||||
assert(printed == needed);
|
assert(printed == needed);
|
||||||
return make_lisp_string(buffer, printed, true, false);
|
return make_lisp_string(buffer, printed, true, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
// LispString (the type) is defined in base.h
|
// LispString (the type) is defined in base.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,
|
||||||
@@ -11,6 +13,7 @@ LispVal *make_lisp_string(const char *data, size_t length, bool take,
|
|||||||
(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);
|
LispVal *lisp_sprintf(const char *format, ...) FORMAT(1, 2);
|
||||||
|
LispVal *lisp_vsprintf(const char *format, va_list args);
|
||||||
|
|
||||||
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));
|
||||||
|
|||||||
+16
@@ -106,6 +106,22 @@ DEFUN(list, "list", (LispVal * args), "(&rest args)", "") {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN(list_star, "list*", (LispVal * arg, LispVal *args), "(arg &rest args)",
|
||||||
|
"") {
|
||||||
|
if (NILP(args)) {
|
||||||
|
return arg;
|
||||||
|
} else if (NILP(XCDR(args))) {
|
||||||
|
return CONS(arg, XCAR(args));
|
||||||
|
}
|
||||||
|
LispVal *out = CONS(arg, args);
|
||||||
|
args = out;
|
||||||
|
while (CONSP(args) && CONSP(XCDR(args)) && CONSP(XCDR(XCDR(args)))) {
|
||||||
|
args = XCDR(args);
|
||||||
|
}
|
||||||
|
RPLACD(args, XCAR(XCDR(args)));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN(copy_list, "copy-list", (LispVal * list), "(list)", "") {
|
DEFUN(copy_list, "copy-list", (LispVal * list), "(list)", "") {
|
||||||
LispVal *start = Qnil;
|
LispVal *start = Qnil;
|
||||||
LispVal *end = NULL;
|
LispVal *end = NULL;
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ DECLARE_FUNCTION(proper_list_p, (LispVal * obj));
|
|||||||
DECLARE_FUNCTION(circular_list_p, (LispVal * obj));
|
DECLARE_FUNCTION(circular_list_p, (LispVal * obj));
|
||||||
DECLARE_FUNCTION(dotted_list_p, (LispVal * obj));
|
DECLARE_FUNCTION(dotted_list_p, (LispVal * obj));
|
||||||
DECLARE_FUNCTION(list, (LispVal * args));
|
DECLARE_FUNCTION(list, (LispVal * args));
|
||||||
|
DECLARE_FUNCTION(list_star, (LispVal * arg, LispVal *args));
|
||||||
DECLARE_FUNCTION(copy_list, (LispVal * list));
|
DECLARE_FUNCTION(copy_list, (LispVal * list));
|
||||||
LispVal *nth(size_t n, LispVal *list);
|
LispVal *nth(size_t n, LispVal *list);
|
||||||
DECLARE_FUNCTION(nth, (LispVal * n, LispVal *list));
|
DECLARE_FUNCTION(nth, (LispVal * n, LispVal *list));
|
||||||
|
|||||||
@@ -134,6 +134,8 @@ static LispVal *macroexpand_special_form(LispVal *fobj, LispVal *form,
|
|||||||
LispVal *prog =
|
LispVal *prog =
|
||||||
macroexpand_list(XCDR_SAFE(XCDR_SAFE(form)), lexical_macros);
|
macroexpand_list(XCDR_SAFE(XCDR_SAFE(form)), lexical_macros);
|
||||||
return CONS(XCAR(form), CONS(bindings, prog));
|
return CONS(XCAR(form), CONS(bindings, prog));
|
||||||
|
} else if (IS(declare)) {
|
||||||
|
return form;
|
||||||
}
|
}
|
||||||
abort();
|
abort();
|
||||||
#undef IS
|
#undef IS
|
||||||
|
|||||||
+12
-8
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "lisp_string.h"
|
#include "lisp_string.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@@ -64,17 +65,17 @@ static void skip_whitespace(ReadStream *stream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn void read_error(ReadStream *stream, size_t length, const char *msg,
|
FORMAT(3, 4)
|
||||||
...) {
|
static noreturn void read_error(ReadStream *stream, size_t length,
|
||||||
fprintf(stderr, "read-error at %zu:%zu: ", stream->line, stream->col);
|
const char *msg, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, msg);
|
va_start(args, msg);
|
||||||
vfprintf(stderr, msg, args);
|
LispVal *lmsg = lisp_vsprintf(msg, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
fprintf(stderr, ":\n context => ");
|
lisp_signal(Qread_error,
|
||||||
fwrite(stream->buffer + stream->off, 1, length, stderr);
|
LIST(MAKE_FIXNUM(stream->line), MAKE_FIXNUM(stream->col), lmsg,
|
||||||
fputc('\n', stderr);
|
make_lisp_string(stream->buffer + stream->off, length,
|
||||||
exit(1);
|
true, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE bool DOT_SYMBOL_P(LispVal *val) {
|
static ALWAYS_INLINE bool DOT_SYMBOL_P(LispVal *val) {
|
||||||
@@ -480,3 +481,6 @@ LispVal *read(ReadStream *stream) {
|
|||||||
return next_symbol(stream);
|
return next_symbol(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_SYMBOL(read_error, "read-error");
|
||||||
|
DEFINE_CONDITION_CLASS(read_error, error);
|
||||||
|
|||||||
@@ -32,4 +32,7 @@ void read_stream_init(ReadStream *stream, const char *buffer, size_t length);
|
|||||||
// NULL on eof
|
// NULL on eof
|
||||||
LispVal *read(ReadStream *stream);
|
LispVal *read(ReadStream *stream);
|
||||||
|
|
||||||
|
DECLARE_SYMBOL(read_error);
|
||||||
|
MAKE_CONDITION_CLASS(read_error);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user