tisp

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

commit 340fa4b70555fe29c3d0db26bdf58c2021cd7d79
parent 56064fb6d382250e9067beb303ba52b82aa3ca63
Author: Ed van Bruggen <edvb@uw.edu>
Date:   Mon, 12 Oct 2020 19:10:13 -0700

Seperate primitive type into special form

Special forms behave like primitives used to but now primitives have
all their arguments evaluated by default. The C equilivent of functions
and macros

Diffstat:
tib/io.c | 74+++++++++++++++++++++++++++++++-------------------------------------------
tib/math.c | 143+++++++++++++++++++++++++++++++++++++++++--------------------------------------
tib/os.c | 25++++++++++++-------------
tib/string.c | 29+++++++++++------------------
tisp.c | 142++++++++++++++++++++++++++++++++++---------------------------------------------
tisp.h | 37++++++++++++++++++++-----------------
6 files changed, 209 insertions(+), 241 deletions(-)

diff --git a/tib/io.c b/tib/io.c @@ -30,31 +30,28 @@ static Val prim_write(Tsp st, Hash env, Val args) { - Val v; FILE *f; const char *mode = "w"; tsp_arg_min(args, "write", 2); - if (!(v = tisp_eval_list(st, env, args))) - return NULL; /* if second argument is true, append file don't write over */ - if (!nilp(cadr(v))) + if (!nilp(cadr(args))) mode = "a"; /* first argument can either be the symbol stdout or stderr, * or the file as a string */ - if (car(v)->t == TSP_SYM) - f = !strncmp(car(v)->v.s, "stdout", 7) ? stdout : stderr; - else if (car(v)->t != TSP_STR) + if (car(args)->t == TSP_SYM) + f = !strncmp(car(args)->v.s, "stdout", 7) ? stdout : stderr; + else if (car(args)->t != TSP_STR) tsp_warnf("write: expected file name as string, received %s", - type_str(car(v)->t)); - else if (!(f = fopen(car(v)->v.s, mode))) - tsp_warnf("write: could not load file '%s'", car(v)->v.s); - if (f == stderr && strncmp(car(v)->v.s, "stderr", 7)) + type_str(car(args)->t)); + else if (!(f = fopen(car(args)->v.s, mode))) + tsp_warnf("write: could not load file '%s'", car(args)->v.s); + if (f == stderr && strncmp(car(args)->v.s, "stderr", 7)) tsp_warn("write: expected file name as string, " "or symbol stdout/stderr"); - for (v = cddr(v); !nilp(v); v = cdr(v)) - tisp_print(f, car(v)); + for (args = cddr(args); !nilp(args); args = cdr(args)) + tisp_print(f, car(args)); if (f == stdout || f == stderr) fflush(f); else @@ -66,15 +63,12 @@ prim_write(Tsp st, Hash env, Val args) static Val prim_read(Tsp st, Hash env, Val args) { - Val v; char *file, *fname = NULL; /* read from stdin by default */ if (list_len(args) > 1) tsp_warnf("read: expected 0 or 1 argument, received %d", list_len(args)); if (list_len(args) == 1) { /* if file name given as string, read it */ - if (!(v = tisp_eval(st, env, car(args)))) - return NULL; - tsp_arg_type(v, "read", TSP_STR); - fname = v->v.s; + tsp_arg_type(car(args), "read", TSP_STR); + fname = car(args)->v.s; } if (!(file = tisp_read_file(fname))) return st->nil; @@ -86,45 +80,41 @@ prim_read(Tsp st, Hash env, Val args) static Val prim_parse(Tsp st, Hash env, Val args) { - Val v; + Val expr; char *file = st->file; size_t filec = st->filec; tsp_arg_num(args, "parse", 1); - if (!(v = tisp_eval(st, env, car(args)))) - return NULL; - if (nilp(v)) + expr = car(args); + if (nilp(expr)) return mk_pair(mk_sym(st, "quit"), st->nil); - tsp_arg_type(v, "parse", TSP_STR); - st->file = v->v.s; + tsp_arg_type(expr, "parse", TSP_STR); + st->file = expr->v.s; st->filec = 0; - v = tisp_read(st); - /* for (; tsp_fget(st) && (v = tisp_read(st));) ; */ + expr = tisp_read(st); + /* for (; tsp_fget(st) && (expr = tisp_read(st));) ; */ st->file = file; st->filec = filec; - return v ? v : st->none; - /* return tisp_parse_file(st, v->v.s); */ + return expr ? expr : st->none; + /* return tisp_parse_file(st, expr->v.s); */ } /* save value as binary file to be quickly read again */ static Val prim_save(Tsp st, Hash env, Val args) { - Val v; char *fname; FILE *f; tsp_arg_min(args, "save", 2); - if (!(v = tisp_eval_list(st, env, args))) - return NULL; - tsp_arg_type(cadr(v), "save", TSP_STR); - fname = cadr(v)->v.s; + tsp_arg_type(cadr(args), "save", TSP_STR); + fname = cadr(args)->v.s; if (!(f = fopen(fname, "wb"))) tsp_warnf("save: could not load file '%s'", fname); - if (!(fwrite(&*car(v), sizeof(struct Val), 1, f))) { + if (!(fwrite(&*car(args), sizeof(struct Val), 1, f))) { fclose(f); tsp_warnf("save: could not save file '%s'", fname); } fclose(f); - return car(v); + return car(args); } /* return read binary value previously saved */ @@ -138,9 +128,7 @@ prim_open(Tsp st, Hash env, Val args) if (!(ret = malloc(sizeof(struct Val)))) perror("; malloc"), exit(1); tsp_arg_min(args, "open", 1); - if (!(args = tisp_eval_list(st, env, args))) - return NULL; - tsp_arg_type(car(args), "save", TSP_STR); + tsp_arg_type(car(args), "open", TSP_STR); fname = car(args)->v.s; if (!(f = fopen(fname, "rb"))) tsp_warnf("save: could not load file '%s'", fname); @@ -153,9 +141,9 @@ prim_open(Tsp st, Hash env, Val args) void tib_env_io(Tsp st) { - tsp_env_fn(write); - tsp_env_fn(read); - tsp_env_fn(parse); - tsp_env_fn(save); - tsp_env_fn(open); + tsp_env_prim(write); + tsp_env_prim(read); + tsp_env_prim(parse); + tsp_env_prim(save); + tsp_env_prim(open); } diff --git a/tib/math.c b/tib/math.c @@ -74,10 +74,11 @@ static Val static Val \ prim_##NAME(Tsp st, Hash vars, Val args) \ { \ - Val a; \ + Val n; \ tsp_arg_num(args, #NAME, 1); \ - EVAL_CHECK(a, car(args), #NAME, TSP_NUM); \ - return (mk_num(a->t, a->t, FORCE))(NAME(num(a)/den(a)), 1.); \ + n = car(args); \ + tsp_arg_type(n, #NAME, TSP_NUM); \ + return (mk_num(n->t, n->t, FORCE))(NAME(num(n)/den(n)), 1.); \ } /* define int and dec as identity functions to use them in the same macro */ @@ -96,8 +97,9 @@ prim_add(Tsp st, Hash vars, Val args) { Val a, b; tsp_arg_num(args, "+", 2); - EVAL_CHECK(a, car(args), "+", TSP_NUM); - EVAL_CHECK(b, car(cdr(args)), "+", TSP_NUM); + a = car(args), b = cadr(args); + tsp_arg_type(a, "+", TSP_NUM); + tsp_arg_type(b, "+", TSP_NUM); if (a->t & TSP_DEC || b->t & TSP_DEC) return mk_dec((num(a)/den(a)) + (num(b)/den(b))); return (mk_num(a->t, b->t, 0)) @@ -112,12 +114,14 @@ prim_sub(Tsp st, Hash vars, Val args) int len = list_len(args); if (len != 2 && len != 1) tsp_warnf("-: expected 1 or 2 arguments, recieved %d", len); - EVAL_CHECK(a, car(args), "-", TSP_NUM); + a = car(args); + tsp_arg_type(a, "-", TSP_NUM); if (len == 1) { b = a; a = mk_int(0); } else { - EVAL_CHECK(b, car(cdr(args)), "-", TSP_NUM); + b = cadr(args); + tsp_arg_type(b, "-", TSP_NUM); } if (a->t & TSP_DEC || b->t & TSP_DEC) return mk_dec((num(a)/den(a)) - (num(b)/den(b))); @@ -131,8 +135,9 @@ prim_mul(Tsp st, Hash vars, Val args) { Val a, b; tsp_arg_num(args, "*", 2); - EVAL_CHECK(a, car(args), "*", TSP_NUM); - EVAL_CHECK(b, car(cdr(args)), "*", TSP_NUM); + a = car(args), b = cadr(args); + tsp_arg_type(a, "*", TSP_NUM); + tsp_arg_type(b, "*", TSP_NUM); if (a->t & TSP_DEC || b->t & TSP_DEC) return mk_dec((num(a)/den(a)) * (num(b)/den(b))); return (mk_num(a->t, b->t, 0))(num(a) * num(b), den(a) * den(b)); @@ -146,12 +151,14 @@ prim_div(Tsp st, Hash vars, Val args) int len = list_len(args); if (len != 2 && len != 1) tsp_warnf("/: expected 1 or 2 arguments, recieved %d", len); - EVAL_CHECK(a, car(args), "/", TSP_NUM); + a = car(args); + tsp_arg_type(a, "/", TSP_NUM); if (len == 1) { b = a; a = mk_int(1); } else { - EVAL_CHECK(b, car(cdr(args)), "/", TSP_NUM); + b = cadr(args); + tsp_arg_type(b, "/", TSP_NUM); } if (a->t & TSP_DEC || b->t & TSP_DEC) return mk_dec((num(a)/den(a)) / (num(b)/den(b))); @@ -163,8 +170,9 @@ prim_mod(Tsp st, Hash vars, Val args) { Val a, b; tsp_arg_num(args, "mod", 2); - EVAL_CHECK(a, car(args), "mod", TSP_INT); - EVAL_CHECK(b, car(cdr(args)), "mod", TSP_INT); + a = car(args), b = cadr(args); + tsp_arg_type(a, "mod", TSP_INT); + tsp_arg_type(b, "mod", TSP_INT); if (num(b) == 0) tsp_warn("division by zero"); return mk_int((int)num(a) % abs((int)num(b))); @@ -174,11 +182,12 @@ prim_mod(Tsp st, Hash vars, Val args) static Val prim_pow(Tsp st, Hash vars, Val args) { - double bnum, bden; Val b, p; + double bnum, bden; tsp_arg_num(args, "pow", 2); - EVAL_CHECK(b, car(args), "pow", TSP_EXPR); - EVAL_CHECK(p, car(cdr(args)), "pow", TSP_EXPR); + b = car(args), p = cadr(args); + tsp_arg_type(b, "pow", TSP_EXPR); + tsp_arg_type(p, "pow", TSP_EXPR); bnum = pow(num(b), num(p)/den(p)); bden = pow(den(b), num(p)/den(p)); if ((bnum == (int)bnum && bden == (int)bden) || @@ -187,20 +196,17 @@ prim_pow(Tsp st, Hash vars, Val args) return mk_pair(mk_sym(st, "^"), mk_pair(b, mk_pair(p, st->nil))); } -#define PRIM_COMPARE(NAME, OP) \ -static Val \ -prim_##NAME(Tsp st, Hash vars, Val args) \ -{ \ - Val v; \ - if (!(v = tisp_eval_list(st, vars, args))) \ - return NULL; \ - if (list_len(v) != 2) \ - return st->t; \ - tsp_arg_type(car(v), #OP, TSP_NUM); \ - tsp_arg_type(car(cdr(v)), #OP, TSP_NUM); \ - return ((num(car(v))*den(car(cdr(v)))) OP \ - (num(car(cdr(v)))*den(car(v)))) ? \ - st->t : st->nil; \ +#define PRIM_COMPARE(NAME, OP) \ +static Val \ +prim_##NAME(Tsp st, Hash vars, Val args) \ +{ \ + if (list_len(args) != 2) \ + return st->t; \ + tsp_arg_type(car(args), #OP, TSP_NUM); \ + tsp_arg_type(car(cdr(args)), #OP, TSP_NUM); \ + return ((num(car(args))*den(car(cdr(args)))) OP \ + (num(car(cdr(args)))*den(car(args)))) ? \ + st->t : st->nil; \ } PRIM_COMPARE(lt, <) @@ -208,16 +214,15 @@ PRIM_COMPARE(gt, >) PRIM_COMPARE(lte, <=) PRIM_COMPARE(gte, >=) -#define PRIM_TRIG(NAME) \ -static Val \ -prim_##NAME(Tsp st, Hash vars, Val args) \ -{ \ - Val v; \ - tsp_arg_num(args, #NAME, 1); \ - EVAL_CHECK(v, car(args), #NAME, TSP_EXPR); \ - if (v->t & TSP_DEC) \ - return mk_dec(NAME(num(v))); \ - return mk_pair(mk_sym(st, #NAME), mk_pair(v, st->nil)); \ +#define PRIM_TRIG(NAME) \ +static Val \ +prim_##NAME(Tsp st, Hash vars, Val args) \ +{ \ + tsp_arg_num(args, #NAME, 1); \ + tsp_arg_type(car(args), #NAME, TSP_EXPR); \ + if (car(args)->t & TSP_DEC) \ + return mk_dec(NAME(num(car(args)))); \ + return mk_pair(mk_sym(st, #NAME), mk_pair(car(args), st->nil)); \ } PRIM_TRIG(sin) @@ -238,36 +243,36 @@ PRIM_TRIG(log) void tib_env_math(Tsp st) { - tsp_env_fn(Int); - tsp_env_fn(Dec); - tsp_env_fn(floor); - tsp_env_fn(ceil); - tsp_env_fn(round); + tsp_env_prim(Int); + tsp_env_prim(Dec); + tsp_env_prim(floor); + tsp_env_prim(ceil); + tsp_env_prim(round); - tsp_env_name_fn(+, add); - tsp_env_name_fn(-, sub); - tsp_env_name_fn(*, mul); - tsp_env_name_fn(/, div); - tsp_env_fn(mod); - tsp_env_name_fn(^, pow); + tsp_env_name_prim(+, add); + tsp_env_name_prim(-, sub); + tsp_env_name_prim(*, mul); + tsp_env_name_prim(/, div); + tsp_env_prim(mod); + tsp_env_name_prim(^, pow); - tsp_env_name_fn(<, lt); - tsp_env_name_fn(>, gt); - tsp_env_name_fn(<=, lte); - tsp_env_name_fn(>=, gte); + tsp_env_name_prim(<, lt); + tsp_env_name_prim(>, gt); + tsp_env_name_prim(<=, lte); + tsp_env_name_prim(>=, gte); - tsp_env_fn(sin); - tsp_env_fn(cos); - tsp_env_fn(tan); - tsp_env_fn(sinh); - tsp_env_fn(cosh); - tsp_env_fn(tanh); - tsp_env_name_fn(arcsin, asin); - tsp_env_name_fn(arccos, acos); - tsp_env_name_fn(arctan, atan); - tsp_env_name_fn(arcsinh, asinh); - tsp_env_name_fn(arccosh, acosh); - tsp_env_name_fn(arctanh, atanh); - tsp_env_fn(exp); - tsp_env_fn(log); + tsp_env_prim(sin); + tsp_env_prim(cos); + tsp_env_prim(tan); + tsp_env_prim(sinh); + tsp_env_prim(cosh); + tsp_env_prim(tanh); + tsp_env_name_prim(arcsin, asin); + tsp_env_name_prim(arccos, acos); + tsp_env_name_prim(arctan, atan); + tsp_env_name_prim(arcsinh, asinh); + tsp_env_name_prim(arccosh, acosh); + tsp_env_name_prim(arctanh, atanh); + tsp_env_prim(exp); + tsp_env_prim(log); } diff --git a/tib/os.c b/tib/os.c @@ -30,13 +30,12 @@ static Val prim_cd(Tsp st, Hash env, Val args) { - Val v; + Val dir; tsp_arg_num(args, "cd", 1); - if (!(v = tisp_eval(st, env, car(args)))) - return NULL; - if (!(v->t & (TSP_STR|TSP_SYM))) - tsp_warnf("strlen: expected string or symbol, received %s", type_str(v->t)); - if (chdir(v->v.s)) + dir = car(args); + if (!(dir->t & (TSP_STR|TSP_SYM))) + tsp_warnf("strlen: expected string or symbol, received %s", type_str(dir->t)); + if (chdir(dir->v.s)) return perror("; error: cd"), NULL; return st->none; } @@ -44,7 +43,7 @@ prim_cd(Tsp st, Hash env, Val args) /* TODO rename to cwd ? */ /* return string of current working directory */ static Val -prim_pwd(Tsp st, Hash env, Val args) +form_pwd(Tsp st, Hash env, Val args) { tsp_arg_num(args, "pwd", 0); char cwd[PATH_MAX]; @@ -55,7 +54,7 @@ prim_pwd(Tsp st, Hash env, Val args) /* return number of seconds since 1970 (unix time stamp) */ static Val -prim_time(Tsp st, Hash env, Val args) +form_time(Tsp st, Hash env, Val args) { tsp_arg_num(args, "time", 0); return mk_int(time(NULL)); @@ -63,7 +62,7 @@ prim_time(Tsp st, Hash env, Val args) /* return time taken to run command given */ static Val -prim_timeit(Tsp st, Hash env, Val args) +form_timeit(Tsp st, Hash env, Val args) { Val v; clock_t t; @@ -78,8 +77,8 @@ prim_timeit(Tsp st, Hash env, Val args) void tib_env_os(Tsp st) { - tsp_env_name_fn(cd!, cd); - tsp_env_fn(pwd); - tsp_env_fn(time); - tsp_env_fn(timeit); + tsp_env_name_prim(cd!, cd); + tsp_env_form(pwd); + tsp_env_form(time); + tsp_env_form(timeit); } diff --git a/tib/string.c b/tib/string.c @@ -26,7 +26,7 @@ typedef Val (*MkFn)(Tsp, char*); -/* TODO string tib: lower upper strpos strsub */ +/* TODO string tib: lower upper capitalize strpos strsub (python: dir(str))*/ /* TODO simplify by using fmemopen/funopen and tisp_print */ static Val @@ -88,40 +88,33 @@ val_string(Tsp st, Val args, MkFn mk_fn) static Val prim_Str(Tsp st, Hash env, Val args) { - Val v; tsp_arg_min(args, "Str", 1); - if (!(v = tisp_eval_list(st, env, args))) - return NULL; - return val_string(st, v, mk_str); + return val_string(st, args, mk_str); } static Val prim_Sym(Tsp st, Hash env, Val args) { - Val v; tsp_arg_min(args, "Sym", 1); - if (!(v = tisp_eval_list(st, env, args))) - return NULL; - return val_string(st, v, mk_sym); + return val_string(st, args, mk_sym); } static Val prim_strlen(Tsp st, Hash env, Val args) { - Val v; + Val str; tsp_arg_num(args, "strlen", 1); - if (!(v = tisp_eval(st, env, car(args)))) - return NULL; - if (!(v->t & (TSP_STR|TSP_SYM))) + str = car(args); + if (!(str->t & (TSP_STR|TSP_SYM))) tsp_warnf("strlen: expected string or symbol, received %s", - type_str(v->t)); - return mk_int(strlen(v->v.s)); + type_str(str->t)); + return mk_int(strlen(str->v.s)); } void tib_env_string(Tsp st) { - tsp_env_fn(Sym); - tsp_env_fn(Str); - tsp_env_fn(strlen); + tsp_env_prim(Sym); + tsp_env_prim(Str); + tsp_env_prim(strlen); } diff --git a/tisp.c b/tisp.c @@ -371,10 +371,10 @@ mk_sym(Tsp st, char *s) } Val -mk_prim(Prim pr, char *name) +mk_prim(TspType t, Prim pr, char *name) { Val ret = emalloc(sizeof(struct Val)); - ret->t = TSP_PRIM; + ret->t = t; ret->v.pr.name = name; ret->v.pr.pr = pr; return ret; @@ -704,14 +704,15 @@ eval_proc(Tsp st, Hash env, Val f, Val args) { Val ret; Hash e; + /* evaluate function and primitive arguments before being passed */ + if (f->t & (TSP_FUNC|TSP_PRIM)) + if (!(args = tisp_eval_list(st, env, args))) + return NULL; switch (f->t) { + case TSP_FORM: case TSP_PRIM: return (*f->v.pr.pr)(st, env, args); case TSP_FUNC: - /* tail call into the function body with the extended env */ - if (!(args = tisp_eval_list(st, env, args))) - return NULL; - /* FALLTHROUGH */ case TSP_MACRO: tsp_arg_num(args, f->v.f.name ? f->v.f.name : "anonymous", list_len(f->v.f.args)); @@ -813,40 +814,31 @@ tisp_print(FILE *f, Val v) static Val prim_car(Tsp st, Hash env, Val args) { - Val v; tsp_arg_num(args, "car", 1); - if (!(v = tisp_eval_list(st, env, args))) - return NULL; - tsp_arg_type(car(v), "car", TSP_PAIR); - return caar(v); + tsp_arg_type(car(args), "car", TSP_PAIR); + return caar(args); } /* return elements of a list after the first */ static Val prim_cdr(Tsp st, Hash env, Val args) { - Val v; tsp_arg_num(args, "cdr", 1); - if (!(v = tisp_eval_list(st, env, args))) - return NULL; - tsp_arg_type(car(v), "cdr", TSP_PAIR); - return cdar(v); + tsp_arg_type(car(args), "cdr", TSP_PAIR); + return cdar(args); } /* return new pair */ static Val prim_cons(Tsp st, Hash env, Val args) { - Val v; tsp_arg_num(args, "cons", 2); - if (!(v = tisp_eval_list(st, env, args))) - return NULL; - return mk_pair(car(v), cadr(v)); + return mk_pair(car(args), cadr(args)); } /* do not evaluate argument */ static Val -prim_quote(Tsp st, Hash env, Val args) +form_quote(Tsp st, Hash env, Val args) { tsp_arg_num(args, "quote", 1); return car(args); @@ -854,7 +846,7 @@ prim_quote(Tsp st, Hash env, Val args) /* returns nothing */ static Val -prim_Void(Tsp st, Hash env, Val args) +form_Void(Tsp st, Hash env, Val args) { return st->none; } @@ -865,29 +857,24 @@ prim_eval(Tsp st, Hash env, Val args) { Val v; tsp_arg_num(args, "eval", 1); - if (!(v = tisp_eval(st, env, car(args)))) - return NULL; - return (v = tisp_eval(st, st->global, v)) ? v : st->none; + return (v = tisp_eval(st, st->global, car(args))) ? v : st->none; } /* test equality of all values given */ static Val prim_eq(Tsp st, Hash env, Val args) { - Val v; - if (!(v = tisp_eval_list(st, env, args))) - return NULL; - if (nilp(v)) + if (nilp(args)) return st->t; - for (; !nilp(cdr(v)); v = cdr(v)) - if (!vals_eq(car(v), cadr(v))) + for (; !nilp(cdr(args)); args = cdr(args)) + if (!vals_eq(car(args), cadr(args))) return st->nil; return st->t; } /* evaluates all expressions if their conditions are met */ static Val -prim_cond(Tsp st, Hash env, Val args) +form_cond(Tsp st, Hash env, Val args) { Val v, cond; for (v = args; !nilp(v); v = cdr(v)) @@ -902,23 +889,19 @@ prim_cond(Tsp st, Hash env, Val args) static Val prim_typeof(Tsp st, Hash env, Val args) { - Val v; tsp_arg_num(args, "typeof", 1); - if (!(v = tisp_eval(st, env, car(args)))) - return NULL; - return mk_str(st, type_str(v->t)); + return mk_str(st, type_str(car(args)->t)); } +/* TODO rename get to getattr like python ? */ /* get a property of given value */ static Val prim_get(Tsp st, Hash env, Val args) { Val v, prop; tsp_arg_num(args, "get", 2); - if (!(v = tisp_eval(st, env, car(args)))) - return NULL; - if (!(prop = tisp_eval(st, env, cadr(args)))) - return NULL; + v = car(args); + prop = cadr(args); tsp_arg_type(prop, "get", TSP_SYM); switch (v->t) { case TSP_PRIM: @@ -959,7 +942,7 @@ prim_get(Tsp st, Hash env, Val args) /* creates new tisp lambda function */ static Val -prim_lambda(Tsp st, Hash env, Val args) +form_lambda(Tsp st, Hash env, Val args) { tsp_arg_min(args, "lambda", 2); return mk_func(TSP_FUNC, NULL, car(args), cdr(args), env); @@ -967,7 +950,7 @@ prim_lambda(Tsp st, Hash env, Val args) /* creates new tisp defined macro */ static Val -prim_macro(Tsp st, Hash env, Val args) +form_macro(Tsp st, Hash env, Val args) { tsp_arg_min(args, "macro", 2); return mk_func(TSP_MACRO, NULL, car(args), cdr(args), env); @@ -978,7 +961,7 @@ prim_macro(Tsp st, Hash env, Val args) * function name and the cdr the function arguments */ /* TODO if var not func error if more than 2 args */ static Val -prim_def(Tsp st, Hash env, Val args) +form_def(Tsp st, Hash env, Val args) { Val sym, val; tsp_arg_min(args, "def", 1); @@ -1004,7 +987,7 @@ prim_def(Tsp st, Hash env, Val args) /* set symbol to new value */ static Val -prim_set(Tsp st, Hash env, Val args) +form_set(Tsp st, Hash env, Val args) { Val val; Hash h; @@ -1032,7 +1015,7 @@ prim_set(Tsp st, Hash env, Val args) static Val prim_load(Tsp st, Hash env, Val args) { - Val v; + Val tib; void (*tibenv)(Tsp); char *name; const char *paths[] = { @@ -1040,14 +1023,13 @@ prim_load(Tsp st, Hash env, Val args) }; tsp_arg_num(args, "load", 1); - if (!(v = tisp_eval(st, env, car(args)))) - return NULL; - tsp_arg_type(v, "load", TSP_STR); + tib = car(args); + tsp_arg_type(tib, "load", TSP_STR); name = emalloc(PATH_MAX * sizeof(char)); for (int i = 0; paths[i]; i++) { strcpy(name, paths[i]); - strcat(name, v->v.s); + strcat(name, tib->v.s); strcat(name, ".tsp"); if (access(name, R_OK) != -1) { tisp_eval_seq(st, env, tisp_parse_file(st, name)); @@ -1059,23 +1041,23 @@ prim_load(Tsp st, Hash env, Val args) /* If not tisp file, try loading shared object library */ st->libh = erealloc(st->libh, (st->libhc+1)*sizeof(void*)); - name = erealloc(name, (strlen(v->v.s)+10) * sizeof(char)); + name = erealloc(name, (strlen(tib->v.s)+10) * sizeof(char)); strcpy(name, "libtib"); - strcat(name, v->v.s); + strcat(name, tib->v.s); strcat(name, ".so"); if (!(st->libh[st->libhc] = dlopen(name, RTLD_LAZY))) { free(name); - tsp_warnf("load: could not load '%s':\n%s", v->v.s, dlerror()); + tsp_warnf("load: could not load '%s':\n%s", tib->v.s, dlerror()); } dlerror(); - name = erealloc(name, (strlen(v->v.s)+9) * sizeof(char)); + name = erealloc(name, (strlen(tib->v.s)+9) * sizeof(char)); strcpy(name, "tib_env_"); - strcat(name, v->v.s); + strcat(name, tib->v.s); tibenv = dlsym(st->libh[st->libhc], name); if (dlerror()) { free(name); - tsp_warnf("load: could not run '%s':\n%s", v->v.s, dlerror()); + tsp_warnf("load: could not run '%s':\n%s", tib->v.s, dlerror()); } (*tibenv)(st); free(name); @@ -1088,22 +1070,20 @@ prim_load(Tsp st, Hash env, Val args) static Val prim_error(Tsp st, Hash env, Val args) { - Val v; - if (!(v = tisp_eval_list(st, env, args))) - return NULL; /* TODO have error auto print function name that was pre-defined */ - tsp_arg_min(v, "error", 2); - tsp_arg_type(car(v), "error", TSP_SYM); - fprintf(stderr, "; tisp: error: %s: ", car(v)->v.s); /* TODO specify error raised by error func */ - for (v = cdr(v); !nilp(v); v = cdr(v)) - tisp_print(stderr, car(v)); + tsp_arg_min(args, "error", 2); + tsp_arg_type(car(args), "error", TSP_SYM); + /* TODO specify error raised by error func */ + fprintf(stderr, "; tisp: error: %s: ", car(args)->v.s); + for (args = cdr(args); !nilp(args); args = cdr(args)) + tisp_print(stderr, car(args)); fputc('\n', stderr); return NULL; } /* list tisp version */ static Val -prim_version(Tsp st, Hash env, Val args) +form_version(Tsp st, Hash env, Val args) { return mk_str(st, "0.0"); } @@ -1138,23 +1118,23 @@ tisp_env_init(size_t cap) tisp_env_add(st, "True", st->t); tisp_env_add(st, "Nil", st->nil); tisp_env_add(st, "bt", st->nil); - tsp_env_fn(car); - tsp_env_fn(cdr); - tsp_env_fn(cons); - tsp_env_fn(quote); - tsp_env_fn(Void); - tsp_env_fn(eval); - tsp_env_name_fn(=, eq); - tsp_env_fn(cond); - tsp_env_fn(typeof); - tsp_env_fn(get); - tsp_env_fn(lambda); - tsp_env_fn(macro); - tsp_env_fn(def); - tsp_env_name_fn(set!, set); - tsp_env_fn(load); - tsp_env_fn(error); - tsp_env_fn(version); + tsp_env_prim(car); + tsp_env_prim(cdr); + tsp_env_prim(cons); + tsp_env_form(quote); + tsp_env_form(Void); + tsp_env_prim(eval); + tsp_env_name_prim(=, eq); + tsp_env_form(cond); + tsp_env_prim(typeof); + tsp_env_prim(get); + tsp_env_form(lambda); + tsp_env_form(macro); + tsp_env_form(def); + tsp_env_name_form(set!, set); + tsp_env_prim(load); + tsp_env_prim(error); + tsp_env_form(version); st->strs = hash_new(cap, NULL); st->syms = hash_new(cap, NULL); diff --git a/tisp.h b/tisp.h @@ -45,9 +45,11 @@ type_str(TYPE), type_str(ARG->t)); \ } while(0) -#define tsp_env_name_fn(NAME, FN) tisp_env_add(st, #NAME, mk_prim(prim_##FN, #NAME)) -#define tsp_env_fn(NAME) tsp_env_name_fn(NAME, NAME) -#define tsp_include_tib(NAME) void tib_env_##NAME(Tsp) +#define tsp_env_name_prim(NAME, FN) tisp_env_add(st, #NAME, mk_prim(TSP_PRIM, prim_##FN, #NAME)) +#define tsp_env_prim(NAME) tsp_env_name_prim(NAME, NAME) +#define tsp_env_name_form(NAME, FN) tisp_env_add(st, #NAME, mk_prim(TSP_FORM, form_##FN, #NAME)) +#define tsp_env_form(NAME) tsp_env_name_form(NAME, NAME) +#define tsp_include_tib(NAME) void tib_env_##NAME(Tsp) #define tsp_finc(ST) ST->filec++ #define tsp_fgetat(ST, O) ST->file[ST->filec+O] @@ -80,17 +82,18 @@ typedef struct Hash { /* possible tisp object types */ typedef enum { - TSP_NONE = 1 << 0, - TSP_NIL = 1 << 1, - TSP_INT = 1 << 2, - TSP_DEC = 1 << 3, - TSP_RATIO = 1 << 4, - TSP_STR = 1 << 5, - TSP_SYM = 1 << 6, - TSP_PRIM = 1 << 7, - TSP_FUNC = 1 << 8, - TSP_MACRO = 1 << 9, - TSP_PAIR = 1 << 10, + TSP_NONE = 1 << 0, /* void */ + TSP_NIL = 1 << 1, /* nil: false, empty list */ + TSP_INT = 1 << 2, /* integer: whole number */ + TSP_DEC = 1 << 3, /* decimal: floating point number */ + TSP_RATIO = 1 << 4, /* ratio: numerator/denominator */ + TSP_STR = 1 << 5, /* string: immutable characters */ + TSP_SYM = 1 << 6, /* symbol: variable names */ + TSP_PRIM = 1 << 7, /* primitive: built-in function */ + TSP_FORM = 1 << 8, /* special form: built-in macro */ + TSP_FUNC = 1 << 9, /* function: procedure written is tisp */ + TSP_MACRO = 1 << 10, /* macro: function without evaluated arguments */ + TSP_PAIR = 1 << 11, /* pair: building block for lists */ } TspType; #define TSP_RATIONAL (TSP_INT | TSP_RATIO) #define TSP_NUM (TSP_RATIONAL | TSP_DEC) @@ -106,8 +109,8 @@ struct Val { union { char *s; /* STRING, SYMBOL */ struct { double num, den; } n; /* NUMBER */ - struct { char *name; Prim pr; } pr; /* PRIMITIVE */ - struct { char *name; Val args, body; Hash env; } f; /* FUNCTION */ + struct { char *name; Prim pr; } pr; /* PRIMITIVE, FORM */ + struct { char *name; Val args, body; Hash env; } f; /* FUNCTION, MACRO */ struct { Val car, cdr; } p; /* PAIR */ } v; }; @@ -130,7 +133,7 @@ Val mk_dec(double d); Val mk_rat(int num, int den); Val mk_str(Tsp st, char *s); Val mk_sym(Tsp st, char *s); -Val mk_prim(Prim prim, char *name); +Val mk_prim(TspType t, Prim prim, char *name); Val mk_func(TspType t, char *name, Val args, Val body, Hash env); Val mk_pair(Val a, Val b); Val mk_list(Tsp st, int n, Val *a);