aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/interp.c78
-rw-r--r--src/interp.h7
-rw-r--r--src/main.c14
-rw-r--r--src/parser.c7
-rw-r--r--src/parser.h6
-rw-r--r--src/prelude.c2
-rw-r--r--src/prelude.lisp7
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)))
diff --git a/src/main.c b/src/main.c
index d41809e..4fddea9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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))