diff options
| author | Mistivia <i@mistivia.com> | 2025-06-21 12:00:31 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2025-06-21 12:00:31 +0800 |
| commit | 1caa0e8862905cc7d4ed0cba4082e4d5ce12e6ed (patch) | |
| tree | 0452c5b38b99625fd9fdea6fb3beede56e325134 /src/interp.c | |
| parent | 86742c415b34ae063bf8597d9228e9d37f0d7294 (diff) | |
load prelude
Diffstat (limited to 'src/interp.c')
| -rw-r--r-- | src/interp.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/interp.c b/src/interp.c index 7579502..639fe4b 100644 --- a/src/interp.c +++ b/src/interp.c @@ -9,6 +9,8 @@ #include "sexp.h" #include "builtins.h" #include "primitives.h" +#include "parser.h" +#include "prelude.h" #define BUFSIZE 1024 @@ -18,6 +20,9 @@ VECTOR_IMPL(PrimitiveEntry); SExpRef unbound = {-1}; void Interp_init(Interp *self) { + self->parser = malloc(sizeof(Parser)); + Parser_init(self->parser); + self->parser->ctx = self; self->errmsg_buf = malloc(BUFSIZE); SExpVector_init(&self->objs); IntVector_init(&self->empty_space); @@ -93,6 +98,71 @@ void Interp_init(Interp *self) { Interp_add_userfunc(self, "<=", builtin_le); Interp_add_userfunc(self, "not", builtin_not); Interp_add_userfunc(self, "gcstat", builtin_gcstat); + + SExpRef ret = Interp_eval_string(self, bamboo_lisp_prelude); + Interp *interp = self; + if (VALTYPE(ret) == kErrSignal) { + fprintf(stderr, "Failed to load prelude: %s", REF(ret)->str); + } +} + +SExpRef Interp_eval_string(Interp *interp, const char * str) { + Parser_set_string(interp->parser, str); + SExpRef sexp, ret; + ParseResult parse_result; + while (1) { + parse_result = parse_sexp(interp->parser); + if (parse_result.errmsg != NULL) { + ret = new_error(interp, "Parsing error: %s", parse_result.errmsg); + goto end; + } + ret = lisp_eval(interp, parse_result.val, false); + if (Interp_ref(interp, ret)->type == kErrSignal) { + goto end; + } + if (Interp_ref(interp, ret)->type == kBreakSignal + || Interp_ref(interp, ret)->type == kContinueSignal + || Interp_ref(interp, ret)->type == kReturnSignal) { + ret = new_error(interp, "Eval error: unexpected control flow signal.\n"); + goto end; + } + if (Parser_is_end(interp->parser)) goto end; + } +end: + return ret; +} + +SExpRef Interp_load_file(Interp *interp, const char *filename) { + FILE *fp = NULL; + fp = fopen(filename, "r"); + if (fp == NULL) { + return new_error(interp, "Failed to open file: %s\n", filename); + goto end; + } + Parser_set_file(interp->parser, fp); + SExpRef sexp, ret; + ParseResult parse_result; + while (1) { + parse_result = parse_sexp(interp->parser); + if (parse_result.errmsg != NULL) { + ret = new_error(interp, "Parsing error: %s", parse_result.errmsg); + goto end; + } + ret = lisp_eval(interp, parse_result.val, false); + if (Interp_ref(interp, ret)->type == kErrSignal) { + goto end; + } + if (Interp_ref(interp, ret)->type == kBreakSignal + || Interp_ref(interp, ret)->type == kContinueSignal + || Interp_ref(interp, ret)->type == kReturnSignal) { + ret = new_error(interp, "Eval error: unexpected control flow signal.\n"); + goto end; + } + if (Parser_is_end(interp->parser)) goto end; + } +end: + fclose(fp); + return ret; } void Interp_add_userfunc(Interp *interp, const char *name, LispUserFunc fn) { @@ -117,6 +187,8 @@ void Interp_free(Interp *self) { IntVector_free(&self->empty_space); PrimitiveEntryVector_free(&self->primitives); free(self->errmsg_buf); + Parser_free(self->parser); + free(self->parser); } SExp* Interp_ref(Interp *self, SExpRef ref) { @@ -172,6 +244,11 @@ void Interp_gc(Interp *interp, SExpRef tmproot) { } else if (obj->type == kMacroSExp) { SExpRefVector_push_back(&gcstack, obj->macro.args); SExpRefVector_push_back(&gcstack, obj->macro.body); + } else if (obj->type == kReturnSignal || obj->type == kBreakSignal) { + SExpRefVector_push_back(&gcstack, obj->ret); + } else if (obj->type == kTailcallSExp) { + SExpRefVector_push_back(&gcstack, obj->tailcall.args); + SExpRefVector_push_back(&gcstack, obj->tailcall.fn); } } SExpRefVector_free(&gcstack); @@ -548,6 +625,7 @@ SExpRef lisp_eval(Interp *interp, SExpRef sexp, bool istail) { || type == kBreakSignal || type == kContinueSignal || type == kReturnSignal + || type == kTailcallSExp || type == kFuncSExp || type == kUserFuncSExp || type == kRealSExp) { |
