tisp

tiny lisp
git clone git://edryd.org/tisp
Log | Files | Refs | LICENSE

commit 1af37476220c8841a4d06b869cc1efb5ee23ac2b
parent a6572d30ab15356224c9b8aa655174ddc6cecf9e
Author: Ed van Bruggen <edvb@uw.edu>
Date:   Mon,  7 Jan 2019 13:05:00 -0800

Allow multiline functions, returns last value

Diffstat:
test.c | 7+++++++
tisp.c | 56+++++++++++++++++++++++++++++++++-----------------------
2 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/test.c b/test.c @@ -171,6 +171,13 @@ char *tests[][2] = { { "(add foo bar)", "8" }, { "(define (one x) (add x 1))", "" }, { "(one foo)", "5" }, + { "(define (more x)" + " (define term 3)" + " (+ x term))", "" }, + { "(more 8)", "11" }, + { "(define (add2 x)" + " (+ x 1) (+ x 2))", "" }, + { "(add2 2)", "4" }, { "lambda", NULL }, { "((lambda (x) x) 3)", "3" }, diff --git a/tisp.c b/tisp.c @@ -54,24 +54,6 @@ type_str(Type t) } } -int -list_len(Val v) -{ - int len = 0; - Val a; - for (a = v; a->t == PAIR; a = cdr(a)) - len++; - return a->t == NIL ? len : -1; -} - -void -skip_ws(Str str) -{ - str->d += strspn(str->d, " \t\n"); /* skip white space */ - for (; *str->d == ';'; str->d++) /* skip comments until newline */ - str->d += strcspn(str->d, "\n"); -} - static void die(const char *fmt, ...) { @@ -131,6 +113,32 @@ isnum(char *str) ((*str == '-' || *str == '+') && (isdigit(str[1]) || str[1] == '.')); } +void +skip_ws(Str str) +{ + str->d += strspn(str->d, " \t\n"); /* skip white space */ + for (; *str->d == ';'; str->d++) /* skip comments until newline */ + str->d += strcspn(str->d, "\n"); +} + +int +list_len(Val v) +{ + int len = 0; + Val a; + for (a = v; a->t == PAIR; a = cdr(a)) + len++; + return a->t == NIL ? len : -1; +} + +static Val +list_last(Val v) +{ + while (!(cdr(v)->t & NIL)) + v = cdr(v); + return car(v); +} + static int vals_eq(Val a, Val b) { @@ -580,7 +588,7 @@ tisp_eval(Env env, Val v) if (!(hash_extend(env->h, f->v.f.args, args))) return NULL; hash_merge(env->h, f->v.f.env->h); - return tisp_eval(env, f->v.f.body); + return list_last(tisp_eval_list(env, f->v.f.body)); default: tsp_warnf("attempt to evaluate non procedural type %s", type_str(f->t)); } @@ -710,20 +718,22 @@ prim_cond(Env env, Val args) static Val prim_lambda(Env env, Val args) { - tsp_arg_num(args, "lambda", 2); + if (list_len(args) < 2) + tsp_warnf("lambda: expected 2 or more arguments, received %d", list_len(args)); if (car(args)->t != PAIR && !nilp(car(args))) tsp_warn("lambda: incorrect format, no argument list found"); - return mk_func(car(args), car(cdr(args)), env); + return mk_func(car(args), cdr(args), env); } static Val prim_define(Env env, Val args) { Val sym, val; - tsp_arg_num(args, "define", 2); + if (list_len(args) < 2) + tsp_warnf("define: expected 2 or more arguments, received %d", list_len(args)); if (car(args)->t == PAIR) { sym = car(car(args)); - val = mk_func(cdr(car(args)), car(cdr(args)), env); + val = mk_func(cdr(car(args)), cdr(args), env); } else if (car(args)->t == SYMBOL) { sym = car(args); val = tisp_eval(env, car(cdr(args)));