if (!ast || ast->type != MAL_LIST) { return 0; }
MalVal *a0 = _nth(ast, 0);
return (a0->type & MAL_SYMBOL) &&
- env_find(env, a0->val.string) &&
- env_get(env, a0->val.string)->ismacro;
+ env_find(env, a0) &&
+ env_get(env, a0)->ismacro;
}
MalVal *macroexpand(MalVal *ast, Env *env) {
if (!ast || mal_error) return NULL;
while (is_macro_call(ast, env)) {
MalVal *a0 = _nth(ast, 0);
- MalVal *mac = env_get(env, a0->val.string);
+ MalVal *mac = env_get(env, a0);
// TODO: this is weird and limits it to 20. FIXME
ast = _apply(mac, _rest(ast));
}
if (!ast || mal_error) return NULL;
if (ast->type == MAL_SYMBOL) {
//g_print("EVAL symbol: %s\n", ast->val.string);
- return env_get(env, ast->val.string);
+ return env_get(env, ast);
} else if ((ast->type == MAL_LIST) || (ast->type == MAL_VECTOR)) {
//g_print("EVAL sequential: %s\n", _pr_str(ast,1));
MalVal *el = _map2((MalVal *(*)(void*, void*))EVAL, ast, env);
MalVal *a1 = _nth(ast, 1),
*a2 = _nth(ast, 2);
MalVal *res = EVAL(a2, env);
- env_set(env, a1->val.string, res);
+ if (mal_error) return NULL;
+ env_set(env, a1, res);
return res;
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("let*", a0->val.string) == 0) {
key = g_array_index(a1->val.array, MalVal*, i);
val = g_array_index(a1->val.array, MalVal*, i+1);
assert_type(key, MAL_SYMBOL, "let* bind to non-symbol");
- env_set(let_env, key->val.string, EVAL(val, let_env));
+ env_set(let_env, key, EVAL(val, let_env));
}
ast = a2;
env = let_env;
MalVal *a1 = _nth(ast, 1),
*a2 = _nth(ast, 2);
MalVal *res = EVAL(a2, env);
+ if (mal_error) return NULL;
res->ismacro = TRUE;
- env_set(env, a1->val.string, res);
+ env_set(env, a1, res);
return res;
} else if ((a0->type & MAL_SYMBOL) &&
strcmp("macroexpand", a0->val.string) == 0) {
if (!cond || mal_error) return NULL;
if (cond->type & (MAL_FALSE|MAL_NIL)) {
// eval false slot form
- ast = _nth(ast, 3);
- if (!ast) {
+ if (ast->val.array->len > 3) {
+ ast = _nth(ast, 3);
+ } else {
return &mal_nil;
}
} else {
// core.c: defined using C
int i;
for(i=0; i < (sizeof(core_ns) / sizeof(core_ns[0])); i++) {
- env_set(repl_env, core_ns[i].name,
+ env_set(repl_env,
+ malval_new_symbol(core_ns[i].name),
malval_new_function(core_ns[i].func, core_ns[i].arg_cnt));
}
MalVal *do_eval(MalVal *ast) { return EVAL(ast, repl_env); }
- env_set(repl_env, "eval",
+ env_set(repl_env,
+ malval_new_symbol("eval"),
malval_new_function((void*(*)(void *))do_eval, 1));
MalVal *_argv = _listX(0);
MalVal *arg = malval_new_string(argv[i]);
g_array_append_val(_argv->val.array, arg);
}
- env_set(repl_env, "*ARGV*", _argv);
+ env_set(repl_env, malval_new_symbol("*ARGV*"), _argv);
// core.mal: defined using the language itself
- RE(repl_env, "", "(def! *host-language* \"c\")");
RE(repl_env, "", "(def! not (fn* (a) (if a false true)))");
RE(repl_env, "",
"(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))");
}
// repl loop
- RE(repl_env, "", "(println (str \"Mal [\" *host-language* \"]\"))");
for(;;) {
exp = RE(repl_env, prompt, NULL);
if (mal_error && strcmp("EOF", mal_error->val.string) == 0) {