diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/interp.c | 78 | ||||
| -rw-r--r-- | src/interp.h | 7 | ||||
| -rw-r--r-- | src/main.c | 14 | ||||
| -rw-r--r-- | src/parser.c | 7 | ||||
| -rw-r--r-- | src/parser.h | 6 | ||||
| -rw-r--r-- | src/prelude.c | 2 | ||||
| -rw-r--r-- | src/prelude.lisp | 7 |
7 files changed, 107 insertions, 14 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) { diff --git a/src/interp.h b/src/interp.h index 4e358eb..4329442 100644 --- a/src/interp.h +++ b/src/interp.h @@ -8,6 +8,9 @@ #include "algds/vec.h" #include "sexp.h" +struct parser; +typedef struct parser Parser; + struct interp; typedef struct interp Interp; @@ -32,6 +35,7 @@ struct interp { SExpRef top_level; SExpRef nil; char *errmsg_buf; + Parser *parser; }; void Interp_init(Interp *self); @@ -42,8 +46,7 @@ void Interp_add_primitive(Interp *self, const char *name, LispPrimitive fn); void Interp_add_userfunc(Interp *self, const char *name, LispUserFunc fn); SExpRef Interp_eval_string(Interp *interp, const char * str); -void Interp_load_file(Interp *interp, const char *filename); -void Interp_eval_readline(Interp *interp); +SExpRef Interp_load_file(Interp *interp, const char *filename); #define REF(_x) (&(interp->objs.buffer)[(_x).idx]) #define CONS(_x, _y) (lisp_cons(interp, (_x), (_y))) @@ -5,20 +5,17 @@ int main() { int ret = -1; Interp interp; - Parser parser; Interp_init(&interp); - Parser_init(&parser); - parser.ctx = &interp; - Parser_set_readline(&parser); + Parser_set_readline(interp.parser); SExpRef sexp, res; ParseResult parse_result; while (1) { - parse_result = parse_sexp(&parser); + parse_result = parse_sexp(interp.parser); if (parse_result.errmsg != NULL) { - if (Parser_peek(&parser) == EOF) goto end; + if (Parser_peek(interp.parser) == EOF) goto end; fprintf(stderr, "Parsing error: %s", parse_result.errmsg); - free((void*)parser.string); - Parser_set_readline(&parser); + free((void*)interp.parser->string); + Parser_set_readline(interp.parser); continue; } @@ -36,7 +33,6 @@ int main() { lisp_print(&interp, res, stdout); } end: - Parser_free(&parser); Interp_free(&interp); return 0; } diff --git a/src/parser.c b/src/parser.c index c692794..87690c8 100644 --- a/src/parser.c +++ b/src/parser.c @@ -11,12 +11,19 @@ #define BUFSIZE 1024 + static void skip_spaces(Parser *parser) { while (isspace(Parser_peek(parser))) { Parser_getchar(parser); } } +bool Parser_is_end(Parser *parser) { + skip_spaces(parser); + if (Parser_peek(parser) == EOF) return true; + return false; +} + ParseResult ParseOk(SExpRef ref) { return (ParseResult){ .val = ref, .errmsg = NULL }; } diff --git a/src/parser.h b/src/parser.h index ff55f90..0721675 100644 --- a/src/parser.h +++ b/src/parser.h @@ -12,7 +12,7 @@ typedef enum { kParseReadline, } ParseType; -typedef struct { +struct parser { Interp *ctx; char *errmsg_buf; char *token_buf; @@ -26,7 +26,8 @@ typedef struct { }; FILE *fp; }; -} Parser; +}; +typedef struct parser Parser; void Parser_init(Parser *self); void Parser_free(Parser *self); @@ -35,6 +36,7 @@ int Parser_peek(Parser *self); void Parser_set_string(Parser *parser, const char *str); void Parser_set_file(Parser *parser, FILE *fp); void Parser_set_readline(Parser *parser); +bool Parser_is_end(Parser *parser); typedef struct { SExpRef val; diff --git a/src/prelude.c b/src/prelude.c index 50fdbba..f810262 100644 --- a/src/prelude.c +++ b/src/prelude.c @@ -1,6 +1,6 @@ #include "prelude.h" -const char *prelude = "(defvar nil \'())\n\n(defvar pi 3.1415926)\n\n"; +const char *bamboo_lisp_prelude = "(defvar nil \'())\n\n(defvar pi 3.1415926)\n\n(defmacro incq (i)\n `(setq ,i (+ ,i 1)))\n\n(defmacro decq (i)\n `(setq ,i (- ,i 1)))\n\n(defun zerop (x) (= x 0))\n"; diff --git a/src/prelude.lisp b/src/prelude.lisp index 6c48743..3e7ab81 100644 --- a/src/prelude.lisp +++ b/src/prelude.lisp @@ -2,3 +2,10 @@ (defvar pi 3.1415926) +(defmacro incq (i) + `(setq ,i (+ ,i 1))) + +(defmacro decq (i) + `(setq ,i (- ,i 1))) + +(defun zerop (x) (= x 0)) |
