Skip to content

Commit

Permalink
All: TCO let* and quasiquote.
Browse files Browse the repository at this point in the history
  • Loading branch information
kanaka committed Apr 24, 2014
1 parent 89bd4de commit 6301e0b
Show file tree
Hide file tree
Showing 70 changed files with 296 additions and 148 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ ruby_RUNSTEP = ruby ../$(2) $(3)

# Extra options to pass to runtest.py
cs_TEST_OPTS = --redirect
mal_TEST_OPTS = --start-timeout 30 --test-timeout 120
mal_TEST_OPTS = --start-timeout 60 --test-timeout 120


# Derived lists
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Description

Mal is an interpreter for a subset of the Clojure programming
language. Mal is implemented from scratch in 12 different languages:
language. Mal is implemented from scratch in 13 different languages:

* Bash shell
* C
Expand All @@ -13,6 +13,7 @@ language. Mal is implemented from scratch in 12 different languages:
* Javascript
* GNU Make
* mal itself
* Perl
* PHP
* Postscript
* Python
Expand Down
6 changes: 4 additions & 2 deletions bash/step5_tco.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ EVAL () {
ENV_SET "${let_env}" "${ANON["${let_pairs[${idx}]}"]}" "${r}"
idx=$(( idx + 2))
done
EVAL "${a2}" "${let_env}"
return ;;
ast="${a2}"
env="${let_env}"
# Continue loop
;;
do) _count "${ast}"
_slice "${ast}" 1 $(( ${r} - 2 ))
EVAL_AST "${r}" "${env}"
Expand Down
6 changes: 4 additions & 2 deletions bash/step6_file.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ EVAL () {
ENV_SET "${let_env}" "${ANON["${let_pairs[${idx}]}"]}" "${r}"
idx=$(( idx + 2))
done
EVAL "${a2}" "${let_env}"
return ;;
ast="${a2}"
env="${let_env}"
# Continue loop
;;
do) _count "${ast}"
_slice "${ast}" 1 $(( ${r} - 2 ))
EVAL_AST "${r}" "${env}"
Expand Down
11 changes: 7 additions & 4 deletions bash/step7_quote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,18 @@ EVAL () {
ENV_SET "${let_env}" "${ANON["${let_pairs[${idx}]}"]}" "${r}"
idx=$(( idx + 2))
done
EVAL "${a2}" "${let_env}"
return ;;
ast="${a2}"
env="${let_env}"
# Continue loop
;;
quote)
r="${a1}"
return ;;
quasiquote)
QUASIQUOTE "${a1}"
EVAL "${r}" "${env}"
return ;;
ast="${r}"
# Continue loop
;;
do) _count "${ast}"
_slice "${ast}" 1 $(( ${r} - 2 ))
EVAL_AST "${r}" "${env}"
Expand Down
11 changes: 7 additions & 4 deletions bash/step8_macros.sh
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,18 @@ EVAL () {
ENV_SET "${let_env}" "${ANON["${let_pairs[${idx}]}"]}" "${r}"
idx=$(( idx + 2))
done
EVAL "${a2}" "${let_env}"
return ;;
ast="${a2}"
env="${let_env}"
# Continue loop
;;
quote)
r="${a1}"
return ;;
quasiquote)
QUASIQUOTE "${a1}"
EVAL "${r}" "${env}"
return ;;
ast="${r}"
# Continue loop
;;
defmacro!)
local k="${ANON["${a1}"]}"
EVAL "${a2}" "${env}"
Expand Down
11 changes: 7 additions & 4 deletions bash/step9_interop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,18 @@ EVAL () {
ENV_SET "${let_env}" "${ANON["${let_pairs[${idx}]}"]}" "${r}"
idx=$(( idx + 2))
done
EVAL "${a2}" "${let_env}"
return ;;
ast="${a2}"
env="${let_env}"
# Continue loop
;;
quote)
r="${a1}"
return ;;
quasiquote)
QUASIQUOTE "${a1}"
EVAL "${r}" "${env}"
return ;;
ast="${r}"
# Continue loop
;;
defmacro!)
local k="${ANON["${a1}"]}"
EVAL "${a2}" "${env}"
Expand Down
11 changes: 7 additions & 4 deletions bash/stepA_more.sh
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,18 @@ EVAL () {
ENV_SET "${let_env}" "${ANON["${let_pairs[${idx}]}"]}" "${r}"
idx=$(( idx + 2))
done
EVAL "${a2}" "${let_env}"
return ;;
ast="${a2}"
env="${let_env}"
# Continue loop
;;
quote)
r="${a1}"
return ;;
quasiquote)
QUASIQUOTE "${a1}"
EVAL "${r}" "${env}"
return ;;
ast="${r}"
# Continue loop
;;
defmacro!)
local k="${ANON["${a1}"]}"
EVAL "${a2}" "${env}"
Expand Down
4 changes: 3 additions & 1 deletion c/step5_tco.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
assert_type(key, MAL_SYMBOL, "let* bind to non-symbol");
env_set(let_env, key->val.string, EVAL(val, let_env));
}
return EVAL(a2, let_env);
ast = a2;
env = let_env;
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("do", a0->val.string) == 0) {
//g_print("eval apply do\n");
Expand Down
4 changes: 3 additions & 1 deletion c/step6_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
assert_type(key, MAL_SYMBOL, "let* bind to non-symbol");
env_set(let_env, key->val.string, EVAL(val, let_env));
}
return EVAL(a2, let_env);
ast = a2;
env = let_env;
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("do", a0->val.string) == 0) {
//g_print("eval apply do\n");
Expand Down
7 changes: 5 additions & 2 deletions c/step7_quote.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
assert_type(key, MAL_SYMBOL, "let* bind to non-symbol");
env_set(let_env, key->val.string, EVAL(val, let_env));
}
return EVAL(a2, let_env);
ast = a2;
env = let_env;
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("quote", a0->val.string) == 0) {
//g_print("eval apply quote\n");
Expand All @@ -137,7 +139,8 @@ MalVal *EVAL(MalVal *ast, Env *env) {
strcmp("quasiquote", a0->val.string) == 0) {
//g_print("eval apply quasiquote\n");
MalVal *a1 = _nth(ast, 1);
return EVAL(quasiquote(a1), env);
ast = quasiquote(a1);
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("do", a0->val.string) == 0) {
//g_print("eval apply do\n");
Expand Down
7 changes: 5 additions & 2 deletions c/step8_macros.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
assert_type(key, MAL_SYMBOL, "let* bind to non-symbol");
env_set(let_env, key->val.string, EVAL(val, let_env));
}
return EVAL(a2, let_env);
ast = a2;
env = let_env;
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("quote", a0->val.string) == 0) {
//g_print("eval apply quote\n");
Expand All @@ -161,7 +163,8 @@ MalVal *EVAL(MalVal *ast, Env *env) {
strcmp("quasiquote", a0->val.string) == 0) {
//g_print("eval apply quasiquote\n");
MalVal *a1 = _nth(ast, 1);
return EVAL(quasiquote(a1), env);
ast = quasiquote(a1);
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("defmacro!", a0->val.string) == 0) {
//g_print("eval apply defmacro!\n");
Expand Down
7 changes: 5 additions & 2 deletions c/step9_interop.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
assert_type(key, MAL_SYMBOL, "let* bind to non-symbol");
env_set(let_env, key->val.string, EVAL(val, let_env));
}
return EVAL(a2, let_env);
ast = a2;
env = let_env;
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("quote", a0->val.string) == 0) {
//g_print("eval apply quote\n");
Expand All @@ -162,7 +164,8 @@ MalVal *EVAL(MalVal *ast, Env *env) {
strcmp("quasiquote", a0->val.string) == 0) {
//g_print("eval apply quasiquote\n");
MalVal *a1 = _nth(ast, 1);
return EVAL(quasiquote(a1), env);
ast = quasiquote(a1);
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("defmacro!", a0->val.string) == 0) {
//g_print("eval apply defmacro!\n");
Expand Down
7 changes: 5 additions & 2 deletions c/stepA_more.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
assert_type(key, MAL_SYMBOL, "let* bind to non-symbol");
env_set(let_env, key->val.string, EVAL(val, let_env));
}
return EVAL(a2, let_env);
ast = a2;
env = let_env;
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("quote", a0->val.string) == 0) {
//g_print("eval apply quote\n");
Expand All @@ -162,7 +164,8 @@ MalVal *EVAL(MalVal *ast, Env *env) {
strcmp("quasiquote", a0->val.string) == 0) {
//g_print("eval apply quasiquote\n");
MalVal *a1 = _nth(ast, 1);
return EVAL(quasiquote(a1), env);
ast = quasiquote(a1);
// Continue loop
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("defmacro!", a0->val.string) == 0) {
//g_print("eval apply defmacro!\n");
Expand Down
2 changes: 1 addition & 1 deletion clojure/src/step5_tco.clj
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
(let [let-env (env/env env)]
(doseq [[b e] (partition 2 a1)]
(env/env-set let-env b (EVAL e let-env)))
(EVAL a2 let-env))
(recur a2 let-env))

'do
(do (eval-ast (->> ast (drop-last) (drop 1)) env)
Expand Down
2 changes: 1 addition & 1 deletion clojure/src/step6_file.clj
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
(let [let-env (env/env env)]
(doseq [[b e] (partition 2 a1)]
(env/env-set let-env b (EVAL e let-env)))
(EVAL a2 let-env))
(recur a2 let-env))

'do
(do (eval-ast (->> ast (drop-last) (drop 1)) env)
Expand Down
4 changes: 2 additions & 2 deletions clojure/src/step7_quote.clj
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@
(let [let-env (env/env env)]
(doseq [[b e] (partition 2 a1)]
(env/env-set let-env b (EVAL e let-env)))
(EVAL a2 let-env))
(recur a2 let-env))

'quote
a1

'quasiquote
(EVAL (quasiquote a1) env)
(recur (quasiquote a1) env)

'do
(do (eval-ast (->> ast (drop-last) (drop 1)) env)
Expand Down
4 changes: 2 additions & 2 deletions clojure/src/step8_macros.clj
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@
(let [let-env (env/env env)]
(doseq [[b e] (partition 2 a1)]
(env/env-set let-env b (EVAL e let-env)))
(EVAL a2 let-env))
(recur a2 let-env))

'quote
a1

'quasiquote
(EVAL (quasiquote a1) env)
(recur (quasiquote a1) env)

'defmacro!
(let [func (with-meta (EVAL a2 env)
Expand Down
4 changes: 2 additions & 2 deletions clojure/src/step9_interop.clj
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@
(let [let-env (env/env env)]
(doseq [[b e] (partition 2 a1)]
(env/env-set let-env b (EVAL e let-env)))
(EVAL a2 let-env))
(recur a2 let-env))

'quote
a1

'quasiquote
(EVAL (quasiquote a1) env)
(recur (quasiquote a1) env)

'defmacro!
(let [func (with-meta (EVAL a2 env)
Expand Down
4 changes: 2 additions & 2 deletions clojure/src/stepA_more.clj
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@
(let [let-env (env/env env)]
(doseq [[b e] (partition 2 a1)]
(env/env-set let-env b (EVAL e let-env)))
(EVAL a2 let-env))
(recur a2 let-env))

'quote
a1

'quasiquote
(EVAL (quasiquote a1) env)
(recur (quasiquote a1) env)

'defmacro!
(let [func (with-meta (EVAL a2 env)
Expand Down
4 changes: 3 additions & 1 deletion cs/step5_tco.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ static MalVal EVAL(MalVal orig_ast, Env env) {
val = ((MalList)a1)[i+1];
let_env.set(key.getName(), EVAL(val, let_env));
}
return EVAL(a2, let_env);
orig_ast = a2;
env = let_env;
break;
case "do":
eval_ast(ast.slice(1, ast.size()-1), env);
orig_ast = ast[ast.size()-1];
Expand Down
4 changes: 3 additions & 1 deletion cs/step6_file.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ static MalVal EVAL(MalVal orig_ast, Env env) {
val = ((MalList)a1)[i+1];
let_env.set(key.getName(), EVAL(val, let_env));
}
return EVAL(a2, let_env);
orig_ast = a2;
env = let_env;
break;
case "do":
eval_ast(ast.slice(1, ast.size()-1), env);
orig_ast = ast[ast.size()-1];
Expand Down
7 changes: 5 additions & 2 deletions cs/step7_quote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,14 @@ static MalVal EVAL(MalVal orig_ast, Env env) {
val = ((MalList)a1)[i+1];
let_env.set(key.getName(), EVAL(val, let_env));
}
return EVAL(a2, let_env);
orig_ast = a2;
env = let_env;
break;
case "quote":
return ast[1];
case "quasiquote":
return EVAL(quasiquote(ast[1]), env);
orig_ast = quasiquote(ast[1]);
break;
case "do":
eval_ast(ast.slice(1, ast.size()-1), env);
orig_ast = ast[ast.size()-1];
Expand Down
7 changes: 5 additions & 2 deletions cs/step8_macros.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,14 @@ static MalVal EVAL(MalVal orig_ast, Env env) {
val = ((MalList)a1)[i+1];
let_env.set(key.getName(), EVAL(val, let_env));
}
return EVAL(a2, let_env);
orig_ast = a2;
env = let_env;
break;
case "quote":
return ast[1];
case "quasiquote":
return EVAL(quasiquote(ast[1]), env);
orig_ast = quasiquote(ast[1]);
break;
case "defmacro!":
a1 = ast[1];
a2 = ast[2];
Expand Down
Loading

0 comments on commit 6301e0b

Please sign in to comment.