Files
simple-lisp/src/main.c
T

103 lines
3.3 KiB
C
Raw Normal View History

2025-06-28 16:47:23 +09:00
#include "lisp.h"
#include "read.h"
2025-06-30 23:29:02 +09:00
static int exit_status = 0;
2025-09-19 14:41:32 -07:00
STATIC_DEFUN(toplevel_exit_handler, "toplevel-exit-handler",
(LispVal * except)) {
2025-09-10 02:57:48 -07:00
LispVal *detail = TAIL(HEAD(except));
if (NILP(detail) || NILP(HEAD(detail))) {
2025-06-30 23:29:02 +09:00
exit_status = 0;
2025-09-10 02:57:48 -07:00
} else if (!INTEGERP(HEAD(detail))) {
2025-06-30 23:29:02 +09:00
exit_status = 1;
} else {
2025-09-10 02:57:48 -07:00
exit_status = ((LispInteger *) HEAD(detail))->value;
2025-06-30 23:29:02 +09:00
}
return Qnil;
}
2025-09-19 14:41:32 -07:00
STATIC_DEFUN(toplevel_error_handler, "toplevel-error-handler",
(LispVal * except)) {
2025-09-10 02:57:48 -07:00
LispVal *type = HEAD(HEAD(except));
LispVal *detail = TAIL(HEAD(except));
LispVal *backtrace = HEAD(TAIL(except));
2025-06-30 23:29:02 +09:00
fprintf(stderr, "Caught signal of type ");
debug_dump(stderr, type, true);
if (!NILP(detail)) {
fprintf(stderr, "Details: ");
debug_dump(stderr, detail, true);
}
fprintf(stderr, "\nBacktrace (toplevel comes last):\n");
FOREACH(frame, backtrace) {
fprintf(stderr, " ");
debug_dump(stderr, frame, true);
}
exit_status = 1;
return Qnil;
}
2025-06-28 16:47:23 +09:00
DEF_STATIC_SYMBOL(toplevel_read, "toplevel-read");
2025-06-28 16:47:23 +09:00
int main(int argc, const char **argv) {
2025-09-11 03:10:59 -07:00
if (argc < 2) {
fprintf(stderr, "No input file!\n");
return 1;
}
FILE *in = fopen(argv[1], "r");
if (!in) {
perror("fopen");
return 1;
}
fseek(in, 0, SEEK_END);
off_t file_len = ftello(in);
rewind(in);
char buffer[file_len];
fread(buffer, 1, file_len, in);
fclose(in);
2025-06-28 16:47:23 +09:00
lisp_init();
2025-09-11 03:10:59 -07:00
REGISTER_SYMBOL(toplevel_read);
2025-09-19 14:41:32 -07:00
REGISTER_STATIC_FUNCTION(toplevel_error_handler, "(e)", "");
REGISTER_STATIC_FUNCTION(toplevel_exit_handler, "(e)", "");
2025-09-11 03:10:59 -07:00
size_t pos = 0;
WITH_PUSH_FRAME(Qtoplevel, Qnil, false, {
2025-09-22 15:37:36 -07:00
the_stack->hidden = false;
2025-09-22 04:08:24 -07:00
LispVal *err_var = INTERN_STATIC("err-var", system_package);
2025-09-14 02:45:44 -07:00
puthash(the_stack->handlers, Qt,
// simply call the above function
2025-09-19 14:41:32 -07:00
const_list(true, 3, err_var, Qtoplevel_error_handler, err_var));
2025-09-14 02:45:44 -07:00
puthash(the_stack->handlers, Qshutdown_signal,
// simply call the above function
2025-09-19 14:41:32 -07:00
const_list(true, 3, err_var, Qtoplevel_exit_handler, err_var));
2025-09-14 02:45:44 -07:00
LispVal *nil_nil = Fpair(Qnil, Qnil);
puthash(the_stack->handlers, Qeof_error,
// ignore
nil_nil);
refcount_unref(nil_nil);
refcount_unref(err_var);
2025-09-11 03:10:59 -07:00
while (true) {
LispVal *tv;
WITH_PUSH_FRAME(Qtoplevel_read, Qnil, false, {
2025-09-22 04:08:24 -07:00
size_t res = read_from_buffer(buffer + pos, file_len - pos,
current_package, &tv);
2025-09-11 03:10:59 -07:00
if (res == LISP_EOF) {
break;
}
pos += res;
});
WITH_CLEANUP(tv, {
2025-09-22 04:08:24 -07:00
// this is not needed right now as we eval right after reading,
// but it will be later when we read the whole file before
// evaling, so I am testing this here
if (PAIRP(tv) && HEAD(tv) == Qin_package
&& list_length(tv) == 2) {
refcount_unref(Fset_current_package(HEAD(TAIL(tv))));
} else {
refcount_unref(Feval(tv)); //
}
2025-09-11 03:10:59 -07:00
});
}
});
2025-09-10 02:57:48 -07:00
lisp_shutdown();
return exit_status;
2025-06-28 16:47:23 +09:00
}