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);