summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lisp.c94
-rw-r--r--lisp.h7
-rw-r--r--lisp.y10
3 files changed, 74 insertions, 37 deletions
diff --git a/lisp.c b/lisp.c
index 95d8670..b195352 100644
--- a/lisp.c
+++ b/lisp.c
@@ -48,6 +48,17 @@ value *cons(value *car, value *cdr) {
return val;
}
+value *car(value *cons) {
+ //TODO: more robust implementation with error catching
+ return cons->as.pair.car;
+}
+
+value *cdr(value *cons) {
+ //TODO: more robust implementation with error catching
+ return cons->as.pair.cdr;
+}
+
+
void *print_value(value *val){
char *str;
switch (val->type) {
@@ -118,45 +129,58 @@ value *env_lookup(env *e, const char *sym) {
return NULL;
}
-int main(void) {
- /* TEST; DANKE CHATGPT
- // create global environment
- env *global = env_create(NULL);
- // define some variables
- env_define(global, "x", make_int(10));
- env_define(global, "y", make_int(42));
-
- // lookup variables
- value *vx = env_lookup(global, "x");
- value *vy = env_lookup(global, "y");
- value *vz = env_lookup(global, "z"); // undefined
- //
- if (vx) {
- printf("x = ");
- print_value(vx);
- printf("\n");
+value *eval(env *e, value *v) {
+ value *found;
+
+ if (v->type == VALTYPE_NIL) {
+ return v;
}
- if (vx) {
- printf("y = ");
- print_value(vy);
- printf("\n");
+
+ if (v->type == VALTYPE_SYMBOL &&
+ (found = env_lookup(e, v->as.sym))) {
+ return found;
+ }
+
+ if (v->type == VALTYPE_SYMBOL) {
+ printf("symbol %s not found\n", v->as.sym);
+ return v;
}
- if (vz) {
- printf("z = ");
- print_value(vz);
- printf("\n");
+
+ if (v->type == VALTYPE_PAIR) {
+ return eval_pair(e, v);
}
- // create nested environment
- env *local = env_create(global);
- env_define(local, "x", make_int(99)); // shadow global x
-
- value *lx = env_lookup(local, "x"); // should find local
- value *ly = env_lookup(local, "y"); // should find global
-
- printf("local x = %d\n", lx ? lx->as.i : -1);
- printf("local y = %d\n", ly ? ly->as.i : -1);
- */
+ return v;
+}
+
+value *eval_pair(env *e, value *v) {
+ value *head = v->as.pair.car;
+ value *tail = v->as.pair.cdr;
+
+ if (head->type == VALTYPE_SYMBOL &&
+ tail->type == VALTYPE_PAIR) {
+ if(!strcmp(head->as.str, "define")) {
+ value *defargs = cdr(v);
+ value *defname = car(defargs);
+ value *defval = eval(e, car(cdr(defargs)));
+
+ if (defname->type != VALTYPE_SYMBOL) {
+ printf("error, expected symbol, found: ");
+ print_value(defname);
+ printf("\n");
+ return v;
+ }
+ env_define(e, defname->as.sym, defval);
+ }
+ }
+ return v;
+}
+
+env *global_env = NULL;
+
+int main(void) {
+ // init global env
+ global_env = env_create(NULL);
// START REPL
char* line;
while ((line = readline("λ > ")) != NULL) {
diff --git a/lisp.h b/lisp.h
index 4053bd5..6ebf9a2 100644
--- a/lisp.h
+++ b/lisp.h
@@ -31,6 +31,8 @@ value *make_symbol(const char *sym);
value *make_string(const char *str);
value *make_nil();
value *cons(value *car, value *cdr);
+value *car(value *cons);
+value *cdr(value *cons);
void *print_value(value *val);
// environments, TODO: make this use hashtable
@@ -47,4 +49,9 @@ env *env_create(env *parent);
env *env_define(env *e, const char *sym, value *val);
value *env_lookup(env *e, const char *sym);
+extern env *global_env;
+
+value *eval(env *e, value *val);
+value *eval_pair(env *e, value *val);
+
#endif
diff --git a/lisp.y b/lisp.y
index 93dd877..8ed479d 100644
--- a/lisp.y
+++ b/lisp.y
@@ -28,8 +28,14 @@ static int is_integer(double x) {
%start sexprs
%%
-sexprs: sexpr { print_value($1); printf("\n"); }
- | sexprs sexpr { print_value($2); printf("\n"); };
+sexprs: sexpr
+ {
+ print_value(eval(global_env, $1)); printf("\n");
+ }
+ | sexprs sexpr
+ {
+ print_value(eval(global_env, $2)); printf("\n");
+ };
sexpr: atom
| list