tisp

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

commit 92de681c0470652695614b70aad64a75ed6cbd1b
parent 88e8204a8aa87f26569d037333fbfdeba932b667
Author: Ed van Bruggen <edvb@uw.edu>
Date:   Wed, 25 Apr 2018 10:37:19 -0700

Add Env struct to contain constants and Hash

Diffstat:
main.c | 12++++++------
tib/math.c | 40+++++++++++++++++++++-------------------
tib/math.h | 2+-
tisp.c | 104++++++++++++++++++++++++++++++++++++++++---------------------------------------
tisp.h | 28+++++++++++++++++-----------
5 files changed, 98 insertions(+), 88 deletions(-)

diff --git a/main.c b/main.c @@ -33,12 +33,12 @@ hints(const char *buf, int *color, int *bold) } static Val -read_val(Str cmd) +read_val(Env env, Str cmd) { struct Str str; if (cmd->d) - return tisp_read(cmd); + return tisp_read(env, cmd); if (SHOW_HINTS) linenoiseSetHintsCallback(hints); @@ -46,7 +46,7 @@ read_val(Str cmd) return NULL; linenoiseHistoryAdd(str.d); - return tisp_read(&str); + return tisp_read(env, &str); } static void @@ -72,8 +72,8 @@ main(int argc, char *argv[]) struct Str str = { NULL }; FILE *fp; Val v; - Hash env = tisp_init_env(64); - tib_math_env(env); + Env env = tisp_env_init(64); + tib_env_math(env); if (argc > 0) { if (!(fp = fopen(*argv, "r"))) @@ -82,7 +82,7 @@ main(int argc, char *argv[]) str.d = estrdup(buf); } - while ((v = read_val(&str))) { + while ((v = read_val(env, &str))) { if (!(v = tisp_eval(env, v))) continue; diff --git a/tib/math.c b/tib/math.c @@ -12,7 +12,7 @@ } while (0) static Val -prim_add(Hash env, Val args) +prim_add(Env env, Val args) { Val v; int i = 0; @@ -24,7 +24,7 @@ prim_add(Hash env, Val args) } static Val -prim_sub(Hash env, Val args) +prim_sub(Env env, Val args) { Val v; int i = 0; @@ -44,16 +44,18 @@ prim_sub(Hash env, Val args) warnf(FUNC ": expected integer, recieved type [%s]", type_str(V->t)); \ } while (0) -#define PRIM_COMPARE(NAME, OP, FUNC) \ -static Val \ -prim_##NAME(Hash env, Val args) \ -{ \ - Val v; \ - if (!(v = eval_list(env, args))) \ - return NULL; \ - INT_TEST(car(v), FUNC); \ - INT_TEST(car(cdr(v)), FUNC); \ - return (car(v)->v.i OP car(cdr(v))->v.i) ? &t : &nil; \ +#define PRIM_COMPARE(NAME, OP, FUNC) \ +static Val \ +prim_##NAME(Env env, Val args) \ +{ \ + Val v; \ + if (!(v = eval_list(env, args))) \ + return NULL; \ + if (list_len(v) != 2) \ + return &env->t; \ + INT_TEST(car(v), FUNC); \ + INT_TEST(car(cdr(v)), FUNC); \ + return (car(v)->v.i OP car(cdr(v))->v.i) ? &env->t : &env->nil; \ } PRIM_COMPARE(lt, <, "<") @@ -62,12 +64,12 @@ PRIM_COMPARE(lte, <=, "<=") PRIM_COMPARE(gte, >=, ">=") void -tib_math_env(Hash ht) +tib_env_math(Env env) { - hash_add(ht, "+", mk_prim(prim_add)); - hash_add(ht, "-", mk_prim(prim_sub)); - hash_add(ht, "<", mk_prim(prim_lt)); - hash_add(ht, ">", mk_prim(prim_gt)); - hash_add(ht, "<=", mk_prim(prim_lte)); - hash_add(ht, ">=", mk_prim(prim_gte)); + hash_add(env->h, "+", mk_prim(prim_add)); + hash_add(env->h, "-", mk_prim(prim_sub)); + hash_add(env->h, "<", mk_prim(prim_lt)); + hash_add(env->h, ">", mk_prim(prim_gt)); + hash_add(env->h, "<=", mk_prim(prim_lte)); + hash_add(env->h, ">=", mk_prim(prim_gte)); } diff --git a/tib/math.h b/tib/math.h @@ -1,3 +1,3 @@ /* See LICENSE file for copyright and license details. */ -void tib_math_env(Hash ht); +void tib_env_math(Env env); diff --git a/tisp.c b/tisp.c @@ -21,14 +21,14 @@ skip_spaces(Str str) str->d += strcspn(str->d, "\n"); } -static int +int issym(char c) { return BETWEEN(c, 'a', 'z') || BETWEEN(c, 'A', 'Z') || BETWEEN(c, '0', '9') || strchr("+-*/=<>?", c); } -static int +int list_len(Val v) { int len = 0; @@ -210,11 +210,11 @@ hash_merge(Hash ht, Hash ht2) } #define MK_TYPE(TYPE, TYPE_NAME, TYPE_FULL, FN_NAME) \ -Val FN_NAME(TYPE TYPE_NAME) { \ - Val ret = emalloc(sizeof(struct Val)); \ - ret->t = TYPE_FULL; \ - ret->v.TYPE_NAME = TYPE_NAME; \ - return ret; \ +Val FN_NAME(TYPE TYPE_NAME) { \ + Val ret = emalloc(sizeof(struct Val)); \ + ret->t = TYPE_FULL; \ + ret->v.TYPE_NAME = TYPE_NAME; \ + return ret; \ } MK_TYPE(int, i, INTEGER, mk_int) @@ -241,7 +241,7 @@ mk_rat(int num, int den) } Val -mk_func(Val args, Val body, Hash env) +mk_func(Val args, Val body, Env env) { Val ret = emalloc(sizeof(struct Val)); ret->t = FUNCTION; @@ -262,10 +262,10 @@ mk_pair(Val a, Val b) } Val -mk_list(int n, Val *a) +mk_list(Env env, int n, Val *a) { int i; - Val b = &nil; + Val b = &env->nil; for (i = n-1; i >= 0; i--) b = mk_pair(a[i], b); return b; @@ -324,7 +324,7 @@ read_sym(Str str) } Val -read_list(Str str) +read_list(Env env, Str str) { int n = 0; Val *a = emalloc(sizeof(Val)), b; @@ -332,10 +332,10 @@ read_list(Str str) skip_spaces(str); while (*str->d && *str->d != ')') { a = erealloc(a, (n+1) * sizeof(Val)); /* TODO realloc less */ - a[n++] = tisp_read(str); + a[n++] = tisp_read(env, str); skip_spaces(str); } - b = mk_list(n, a); + b = mk_list(env, n, a); free(a); str->d++; skip_spaces(str); @@ -343,7 +343,7 @@ read_list(Str str) } Val -tisp_read(Str str) +tisp_read(Env env, Str str) { skip_spaces(str); if (isdigit(*str->d) || ((*str->d == '-' || *str->d == '+') && isdigit(str->d[1]))) @@ -352,17 +352,17 @@ tisp_read(Str str) return read_str(str); if (*str->d == '\'') { str->d++; - return mk_pair(mk_sym("quote"), mk_pair(tisp_read(str), &nil)); + return mk_pair(mk_sym("quote"), mk_pair(tisp_read(env, str), &env->nil)); } if (issym(*str->d)) return read_sym(str); if (*str->d == '(') - return read_list(str); + return read_list(env, str); return NULL; } Val -eval_list(Hash env, Val v) +eval_list(Env env, Val v) { int cap = 1, size = 0; Val *new = emalloc(sizeof(Val)); @@ -374,13 +374,13 @@ eval_list(Hash env, Val v) new = erealloc(new, cap*sizeof(Val)); } } - Val ret = mk_list(size, new); + Val ret = mk_list(env, size, new); free(new); return ret; } Val -tisp_eval(Hash env, Val v) +tisp_eval(Env env, Val v) { Val f, args; switch (v->t) { @@ -390,7 +390,7 @@ tisp_eval(Hash env, Val v) case STRING: return v; case SYMBOL: - return hash_get(env, v->v.s); + return hash_get(env->h, v->v.s); case PAIR: if (!(f = tisp_eval(env, car(v)))) return NULL; @@ -402,9 +402,9 @@ tisp_eval(Hash env, Val v) /* tail call into the function body with the extended env */ if (!(args = eval_list(env, args))) return NULL; - if (!(hash_extend(env, f->v.f.args, args))) + if (!(hash_extend(env->h, f->v.f.args, args))) return NULL; - hash_merge(env, f->v.f.env); + hash_merge(env->h, f->v.f.env->h); return tisp_eval(env, f->v.f.body); default: warnf("attempt to evaluate non primitive type [%s]", type_str(f->t)); @@ -463,7 +463,7 @@ tisp_print(Val v) } static Val -prim_car(Hash env, Val args) +prim_car(Env env, Val args) { Val v; if (list_len(args) != 1) @@ -476,7 +476,7 @@ prim_car(Hash env, Val args) } static Val -prim_cdr(Hash env, Val args) +prim_cdr(Env env, Val args) { Val v; if (list_len(args) != 1) @@ -489,7 +489,7 @@ prim_cdr(Hash env, Val args) } static Val -prim_cons(Hash env, Val args) +prim_cons(Env env, Val args) { Val v; if (list_len(args) != 2) @@ -500,21 +500,21 @@ prim_cons(Hash env, Val args) } static Val -prim_eq(Hash env, Val args) +prim_eq(Env env, Val args) { Val v; if (!(v = eval_list(env, args))) return NULL; if (nilp(v)) - return &t; + return &env->t; for (; !nilp(cdr(v)); v = cdr(v)) if (!vals_eq(car(v), car(cdr(v)))) - return &nil; - return &t; + return &env->nil; + return &env->t; } static Val -prim_quote(Hash env, Val args) +prim_quote(Env env, Val args) { if (list_len(args) != 1) warnf("quote: expected 1 argument, received [%d]", list_len(args)); @@ -522,7 +522,7 @@ prim_quote(Hash env, Val args) } static Val -prim_cond(Hash env, Val args) +prim_cond(Env env, Val args) { Val v, cond; for (v = args; !nilp(v); v = cdr(v)) @@ -530,11 +530,11 @@ prim_cond(Hash env, Val args) return NULL; else if (!nilp(cond)) return tisp_eval(env, car(cdr(car(v)))); - return &nil; + return &env->nil; } static Val -prim_lambda(Hash env, Val args) +prim_lambda(Env env, Val args) { if (list_len(args) < 2 || (car(args)->t != PAIR && !nilp(car(args)))) warn("lambda: incorrect format"); @@ -542,35 +542,37 @@ prim_lambda(Hash env, Val args) } static Val -prim_define(Hash env, Val args) +prim_define(Env env, Val args) { Val v; if (list_len(args) != 2 || car(args)->t != SYMBOL) warn("define: incorrect format"); if (!(v = tisp_eval(env, car(cdr(args))))) return NULL; - hash_add(env, car(args)->v.s, v); + hash_add(env->h, car(args)->v.s, v); return NULL; } -Hash -tisp_init_env(size_t cap) +Env +tisp_env_init(size_t cap) { - nil.t = NIL; - t.t = SYMBOL; - t.v.s = estrdup("t"); + Env e = emalloc(sizeof(struct Env)); + e->nil.t = NIL; + e->t.t = SYMBOL; + e->t.v.s = "t"; - Hash h = hash_new(cap); - hash_add(h, "t", &t); - hash_add(h, "car", mk_prim(prim_car)); - hash_add(h, "cdr", mk_prim(prim_cdr)); - hash_add(h, "cons", mk_prim(prim_cons)); - hash_add(h, "=", mk_prim(prim_eq)); - hash_add(h, "quote", mk_prim(prim_quote)); - hash_add(h, "cond", mk_prim(prim_cond)); - hash_add(h, "lambda", mk_prim(prim_lambda)); - hash_add(h, "define", mk_prim(prim_define)); - return h; + e->h = hash_new(cap); + hash_add(e->h, "t", &e->t); + hash_add(e->h, "car", mk_prim(prim_car)); + hash_add(e->h, "cdr", mk_prim(prim_cdr)); + hash_add(e->h, "cons", mk_prim(prim_cons)); + hash_add(e->h, "=", mk_prim(prim_eq)); + hash_add(e->h, "quote", mk_prim(prim_quote)); + hash_add(e->h, "cond", mk_prim(prim_cond)); + hash_add(e->h, "lambda", mk_prim(prim_lambda)); + hash_add(e->h, "define", mk_prim(prim_define)); + + return e; } void diff --git a/tisp.h b/tisp.h @@ -18,6 +18,7 @@ struct Val; typedef struct Val *Val; +typedef struct Env *Env; /* improved interface for a pointer to a string */ typedef struct Str { @@ -46,13 +47,13 @@ typedef struct Hash { } *Hash; /* basic function written in C, not lisp */ -typedef Val (*Prim)(Hash, Val); +typedef Val (*Prim)(Env, Val); /* function written directly in lisp instead of C */ typedef struct { Val args; Val body; - Hash env; + Env env; } Func; typedef struct { @@ -82,27 +83,32 @@ struct Val { } v; }; -struct Val nil; -struct Val t; +struct Env { + struct Val nil; + struct Val t; + Hash h; +}; void skip_spaces(Str str); char *type_str(Type t); +int issym(char c); +int list_len(Val v); -Val hash_add(Hash ht, char *key, Val val); +void hash_add(Hash ht, char *key, Val val); Val mk_int(int i); Val mk_str(char *s); Val mk_prim(Prim prim); Val mk_rat(int num, int den); Val mk_sym(char *s); -Val mk_func(Val args, Val body, Hash env); +Val mk_func(Val args, Val body, Env env); Val mk_pair(Val a, Val b); -Val mk_list(int n, Val *a); +Val mk_list(Env env, int n, Val *a); -Val eval_list(Hash env, Val v); +Val eval_list(Env env, Val v); -Val tisp_read(Str str); +Val tisp_read(Env env, Str str); void tisp_print(Val v); -Val tisp_eval(Hash env, Val v); +Val tisp_eval(Env env, Val v); -Hash tisp_init_env(size_t cap); +Env tisp_env_init(size_t cap);