aboutsummaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-12-18 20:33:49 -0600
committerJoel Martin <github@martintribe.org>2015-01-09 16:16:50 -0600
commitb8ee29b22fbaa7a01f2754b4d6dd9af52e02017c (patch)
treef4d977ed220e9a3f665cfbf4f68770a81e4c2095 /c
parentaaba249304b184e12e2445ab22d66df1f39a51a5 (diff)
downloadmal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.tar.gz
mal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.zip
All: add keywords.
Also, fix nth and count to match cloure.
Diffstat (limited to 'c')
-rw-r--r--c/core.c22
-rw-r--r--c/core.h2
-rw-r--r--c/env.c18
-rw-r--r--c/printer.c21
-rw-r--r--c/reader.c7
-rw-r--r--c/step3_env.c14
-rw-r--r--c/step4_if_fn_do.c17
-rw-r--r--c/step5_tco.c15
-rw-r--r--c/step6_file.c20
-rw-r--r--c/step7_quote.c20
-rw-r--r--c/step8_macros.c29
-rw-r--r--c/step9_try.c31
-rw-r--r--c/stepA_interop.c29
-rw-r--r--c/types.c8
-rw-r--r--c/types.h7
15 files changed, 162 insertions, 98 deletions
diff --git a/c/core.c b/c/core.c
index 10c9fc9..8e420e9 100644
--- a/c/core.c
+++ b/c/core.c
@@ -40,7 +40,23 @@ MalVal *symbol(MalVal *args) {
return args;
}
-MalVal *symbol_Q(MalVal *seq) { return seq->type & MAL_SYMBOL ? &mal_true : &mal_false; }
+MalVal *symbol_Q(MalVal *seq) {
+ return seq->type & MAL_SYMBOL ? &mal_true : &mal_false; }
+
+
+// Keyword functions
+
+MalVal *keyword(MalVal *args) {
+ assert_type(args, MAL_STRING,
+ "keyword called with non-string value");
+ return malval_new_keyword(args->val.string);
+}
+
+MalVal *keyword_Q(MalVal *seq) {
+ return seq->type & MAL_STRING && seq->val.string[0] == '\x7f'
+ ? &mal_true
+ : &mal_false;
+}
// String functions
@@ -431,7 +447,7 @@ MalVal *swap_BANG(MalVal *args) {
-core_ns_entry core_ns[54] = {
+core_ns_entry core_ns[56] = {
{"=", (void*(*)(void*))equal_Q, 2},
{"throw", (void*(*)(void*))throw, 1},
{"nil?", (void*(*)(void*))nil_Q, 1},
@@ -439,6 +455,8 @@ core_ns_entry core_ns[54] = {
{"false?", (void*(*)(void*))false_Q, 1},
{"symbol", (void*(*)(void*))symbol, 1},
{"symbol?", (void*(*)(void*))symbol_Q, 1},
+ {"keyword", (void*(*)(void*))keyword, 1},
+ {"keyword?", (void*(*)(void*))keyword_Q, 1},
{"pr-str", (void*(*)(void*))pr_str, -1},
{"str", (void*(*)(void*))str, -1},
diff --git a/c/core.h b/c/core.h
index 49f8bee..82070ff 100644
--- a/c/core.h
+++ b/c/core.h
@@ -10,6 +10,6 @@ typedef struct {
int arg_cnt;
} core_ns_entry;
-extern core_ns_entry core_ns[54];
+extern core_ns_entry core_ns[56];
#endif
diff --git a/c/env.c b/c/env.c
index d4b8f32..0114d1e 100644
--- a/c/env.c
+++ b/c/env.c
@@ -25,10 +25,10 @@ Env *new_env(Env *outer, MalVal* binds, MalVal *exprs) {
if (i > exprs_len) { break; }
if (_nth(binds, i)->val.string[0] == '&') {
varargs = 1;
- env_set(e, _nth(binds, i+1)->val.string, _slice(exprs, i, _count(exprs)));
+ env_set(e, _nth(binds, i+1), _slice(exprs, i, _count(exprs)));
break;
} else {
- env_set(e, _nth(binds, i)->val.string, _nth(exprs, i));
+ env_set(e, _nth(binds, i), _nth(exprs, i));
}
}
assert(varargs || (binds_len == exprs_len),
@@ -39,8 +39,8 @@ Env *new_env(Env *outer, MalVal* binds, MalVal *exprs) {
return e;
}
-Env *env_find(Env *env, char *key) {
- void *val = g_hash_table_lookup(env->table, key);
+Env *env_find(Env *env, MalVal *key) {
+ void *val = g_hash_table_lookup(env->table, key->val.string);
if (val) {
return env;
} else if (env->outer) {
@@ -50,13 +50,13 @@ Env *env_find(Env *env, char *key) {
}
}
-MalVal *env_get(Env *env, char *key) {
+MalVal *env_get(Env *env, MalVal *key) {
Env *e = env_find(env, key);
- assert(e, "'%s' not found", key);
- return g_hash_table_lookup(e->table, key);
+ assert(e, "'%s' not found", key->val.string);
+ return g_hash_table_lookup(e->table, key->val.string);
}
-Env *env_set(Env *env, char *key, MalVal *val) {
- g_hash_table_insert(env->table, key, val);
+Env *env_set(Env *env, MalVal *key, MalVal *val) {
+ g_hash_table_insert(env->table, key->val.string, val);
return env;
}
diff --git a/c/printer.c b/c/printer.c
index 0669cf6..786d89e 100644
--- a/c/printer.c
+++ b/c/printer.c
@@ -5,7 +5,8 @@
char *_pr_str_hash_map(MalVal *obj, int print_readably) {
int start = 1;
- char *repr = NULL, *repr_tmp1 = NULL, *repr_tmp2 = NULL;
+ char *repr = NULL, *repr_tmp1 = NULL, *repr_tmp2 = NULL,
+ *key2 = NULL;
GHashTableIter iter;
gpointer key, value;
@@ -14,14 +15,20 @@ char *_pr_str_hash_map(MalVal *obj, int print_readably) {
g_hash_table_iter_init (&iter, obj->val.hash_table);
while (g_hash_table_iter_next (&iter, &key, &value)) {
//g_print ("%s/%p ", (const char *) key, (void *) value);
+ if (((char*)key)[0] == '\x7f') {
+ key2 = g_strdup_printf("%s", (char*)key);
+ key2[0] = ':';
+ } else {
+ key2 = g_strdup_printf("\"%s\"", (char*)key);
+ }
repr_tmp1 = _pr_str((MalVal*)value, print_readably);
if (start) {
start = 0;
- repr = g_strdup_printf("{\"%s\" %s", (char *)key, repr_tmp1);
+ repr = g_strdup_printf("{%s %s", (char*)key2, repr_tmp1);
} else {
repr_tmp2 = repr;
- repr = g_strdup_printf("%s \"%s\" %s", repr_tmp2, (char *)key, repr_tmp1);
+ repr = g_strdup_printf("%s %s %s", repr_tmp2, (char*)key2, repr_tmp1);
free(repr_tmp2);
}
free(repr_tmp1);
@@ -70,7 +77,11 @@ char *_pr_str(MalVal *obj, int print_readably) {
repr = g_strdup_printf("false");
break;
case MAL_STRING:
- if (print_readably) {
+ if (obj->val.string[0] == '\x7f') {
+ // Keyword
+ repr = g_strdup_printf("%s", obj->val.string);
+ repr[0] = ':';
+ } else if (print_readably) {
char *repr_tmp = g_strescape(obj->val.string, "");
repr = g_strdup_printf("\"%s\"", repr_tmp);
free(repr_tmp);
@@ -121,7 +132,7 @@ char *_pr_str_args(MalVal *args, char *sep, int print_readably) {
assert_type(args, MAL_LIST|MAL_VECTOR,
"_pr_str called with non-sequential args");
int i;
- char *repr = g_strdup_printf(""),
+ char *repr = g_strdup_printf("%s", ""),
*repr2 = NULL;
for (i=0; i<_count(args); i++) {
MalVal *obj = g_array_index(args->val.array, MalVal*, i);
diff --git a/c/reader.c b/c/reader.c
index d9b75b7..ae16321 100644
--- a/c/reader.c
+++ b/c/reader.c
@@ -122,7 +122,7 @@ MalVal *read_atom(Reader *reader) {
token = reader_next(reader);
//g_print("read_atom token: %s\n", token);
- regex = g_regex_new ("(^-?[0-9]+$)|(^-?[0-9][0-9.]*$)|(^nil$)|(^true$)|(^false$)|^\"(.*)\"$|(^[^\"]*$)", 0, 0, &err);
+ regex = g_regex_new ("(^-?[0-9]+$)|(^-?[0-9][0-9.]*$)|(^nil$)|(^true$)|(^false$)|^\"(.*)\"$|:(.*)|(^[^\"]*$)", 0, 0, &err);
g_regex_match (regex, token, 0, &matchInfo);
if (g_match_info_fetch_pos(matchInfo, 1, &pos, NULL) && pos != -1) {
@@ -145,8 +145,11 @@ MalVal *read_atom(Reader *reader) {
char *str_tmp = replace_str(g_match_info_fetch(matchInfo, 6), "\\\"", "\"");
atom = malval_new_string(str_tmp);
} else if (g_match_info_fetch_pos(matchInfo, 7, &pos, NULL) && pos != -1) {
+ //g_print("read_atom keyword\n");
+ atom = malval_new_keyword(g_match_info_fetch(matchInfo, 7));
+ } else if (g_match_info_fetch_pos(matchInfo, 8, &pos, NULL) && pos != -1) {
//g_print("read_atom symbol\n");
- atom = malval_new_symbol(g_match_info_fetch(matchInfo, 7));
+ atom = malval_new_symbol(g_match_info_fetch(matchInfo, 8));
} else {
malval_free(atom);
atom = NULL;
diff --git a/c/step3_env.c b/c/step3_env.c
index 2f41bc0..cacf9d7 100644
--- a/c/step3_env.c
+++ b/c/step3_env.c
@@ -32,7 +32,7 @@ MalVal *eval_ast(MalVal *ast, Env *env) {
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);
@@ -79,7 +79,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
MalVal *a1 = _nth(ast, 1),
*a2 = _nth(ast, 2);
MalVal *res = EVAL(a2, env);
- env_set(env, a1->val.string, res);
+ env_set(env, a1, res);
return res;
} else if (strcmp("let*", a0->val.string) == 0) {
//g_print("eval apply let*\n");
@@ -95,7 +95,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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));
}
return EVAL(a2, let_env);
} else {
@@ -143,10 +143,10 @@ void init_repl_env() {
WRAP_INTEGER_OP(multiply,*)
WRAP_INTEGER_OP(divide,/)
- env_set(repl_env, "+", (MalVal *)int_plus);
- env_set(repl_env, "-", (MalVal *)int_minus);
- env_set(repl_env, "*", (MalVal *)int_multiply);
- env_set(repl_env, "/", (MalVal *)int_divide);
+ env_set(repl_env, malval_new_symbol("+"), (MalVal *)int_plus);
+ env_set(repl_env, malval_new_symbol("-"), (MalVal *)int_minus);
+ env_set(repl_env, malval_new_symbol("*"), (MalVal *)int_multiply);
+ env_set(repl_env, malval_new_symbol("/"), (MalVal *)int_divide);
}
int main()
diff --git a/c/step4_if_fn_do.c b/c/step4_if_fn_do.c
index 84fb760..413bcd6 100644
--- a/c/step4_if_fn_do.c
+++ b/c/step4_if_fn_do.c
@@ -33,7 +33,7 @@ MalVal *eval_ast(MalVal *ast, Env *env) {
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);
@@ -80,7 +80,8 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -97,7 +98,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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));
}
return EVAL(a2, let_env);
} else if ((a0->type & MAL_SYMBOL) &&
@@ -110,12 +111,11 @@ MalVal *EVAL(MalVal *ast, Env *env) {
//g_print("eval apply if\n");
MalVal *a1 = _nth(ast, 1);
MalVal *cond = EVAL(a1, env);
- if (!ast || mal_error) return NULL;
+ if (!cond || mal_error) return NULL;
if (cond->type & (MAL_FALSE|MAL_NIL)) {
// eval false slot form
- MalVal *a3 = _nth(ast, 3);
- if (a3) {
- return EVAL(a3, env);
+ if (ast->val.array->len > 3) {
+ return EVAL(_nth(ast, 3), env);
} else {
return &mal_nil;
}
@@ -179,7 +179,8 @@ void init_repl_env() {
// 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));
}
diff --git a/c/step5_tco.c b/c/step5_tco.c
index edca21b..a1762c8 100644
--- a/c/step5_tco.c
+++ b/c/step5_tco.c
@@ -33,7 +33,7 @@ MalVal *eval_ast(MalVal *ast, Env *env) {
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);
@@ -82,7 +82,8 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -99,7 +100,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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;
@@ -118,8 +119,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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 {
@@ -190,7 +192,8 @@ void init_repl_env() {
// 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));
}
diff --git a/c/step6_file.c b/c/step6_file.c
index 9ff62a9..409e221 100644
--- a/c/step6_file.c
+++ b/c/step6_file.c
@@ -33,7 +33,7 @@ MalVal *eval_ast(MalVal *ast, Env *env) {
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);
@@ -82,7 +82,8 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -99,7 +100,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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;
@@ -118,8 +119,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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 {
@@ -190,11 +192,13 @@ void init_repl_env(int argc, char *argv[]) {
// 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);
@@ -202,7 +206,7 @@ void init_repl_env(int argc, char *argv[]) {
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! not (fn* (a) (if a false true)))");
diff --git a/c/step7_quote.c b/c/step7_quote.c
index d0d1d3d..73250e3 100644
--- a/c/step7_quote.c
+++ b/c/step7_quote.c
@@ -60,7 +60,7 @@ MalVal *eval_ast(MalVal *ast, Env *env) {
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);
@@ -109,7 +109,8 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -126,7 +127,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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;
@@ -155,8 +156,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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 {
@@ -227,11 +229,13 @@ void init_repl_env(int argc, char *argv[]) {
// 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);
@@ -239,7 +243,7 @@ void init_repl_env(int argc, char *argv[]) {
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! not (fn* (a) (if a false true)))");
diff --git a/c/step8_macros.c b/c/step8_macros.c
index 3558caf..55c6988 100644
--- a/c/step8_macros.c
+++ b/c/step8_macros.c
@@ -61,15 +61,15 @@ int is_macro_call(MalVal *ast, Env *env) {
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));
}
@@ -80,7 +80,7 @@ MalVal *eval_ast(MalVal *ast, Env *env) {
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);
@@ -133,7 +133,8 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -150,7 +151,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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;
@@ -171,8 +172,9 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -193,8 +195,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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 {
@@ -266,11 +269,13 @@ void init_repl_env(int argc, char *argv[]) {
// 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);
@@ -278,7 +283,7 @@ void init_repl_env(int argc, char *argv[]) {
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! not (fn* (a) (if a false true)))");
diff --git a/c/step9_try.c b/c/step9_try.c
index 395a7f0..ffba2f9 100644
--- a/c/step9_try.c
+++ b/c/step9_try.c
@@ -62,15 +62,15 @@ int is_macro_call(MalVal *ast, Env *env) {
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));
}
@@ -81,7 +81,7 @@ MalVal *eval_ast(MalVal *ast, Env *env) {
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);
@@ -134,7 +134,8 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -151,7 +152,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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;
@@ -172,8 +173,9 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -215,8 +217,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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 {
@@ -288,11 +291,13 @@ void init_repl_env(int argc, char *argv[]) {
// 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);
@@ -300,10 +305,9 @@ void init_repl_env(int argc, char *argv[]) {
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) \")\")))))");
@@ -328,7 +332,6 @@ int main(int argc, char *argv[])
}
// 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) {
diff --git a/c/stepA_interop.c b/c/stepA_interop.c
index b4b7431..05e9f65 100644
--- a/c/stepA_interop.c
+++ b/c/stepA_interop.c
@@ -62,15 +62,15 @@ int is_macro_call(MalVal *ast, Env *env) {
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));
}
@@ -81,7 +81,7 @@ MalVal *eval_ast(MalVal *ast, Env *env) {
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);
@@ -134,7 +134,8 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -151,7 +152,7 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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;
@@ -172,8 +173,9 @@ MalVal *EVAL(MalVal *ast, Env *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) {
@@ -220,8 +222,9 @@ MalVal *EVAL(MalVal *ast, Env *env) {
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 {
@@ -293,11 +296,13 @@ void init_repl_env(int argc, char *argv[]) {
// 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);
@@ -305,7 +310,7 @@ void init_repl_env(int argc, char *argv[]) {
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\")");
diff --git a/c/types.c b/c/types.c
index 3f1771b..a6c8492 100644
--- a/c/types.c
+++ b/c/types.c
@@ -105,6 +105,12 @@ MalVal *malval_new_symbol(char *val) {
return mv;
}
+MalVal *malval_new_keyword(char *val) {
+ MalVal *mv = malval_new(MAL_STRING, NULL);
+ mv->val.string = g_strdup_printf("\x7f%s", val);
+ return mv;
+}
+
MalVal *malval_new_list(MalType type, GArray *val) {
MalVal *mv = malval_new(type, NULL);
mv->val.array = val;
@@ -422,7 +428,7 @@ MalVal *_nth(MalVal *seq, int idx) {
assert_type(seq, MAL_LIST|MAL_VECTOR,
"_nth called with non-sequential");
if (idx >= _count(seq)) {
- return &mal_nil;
+ abort("nth: index out of range");
}
return g_array_index(seq->val.array, MalVal*, idx);
}
diff --git a/c/types.h b/c/types.h
index aa6c5e3..80a40ac 100644
--- a/c/types.h
+++ b/c/types.h
@@ -15,9 +15,9 @@ typedef struct Env {
} Env;
Env *new_env(Env *outer, struct MalVal* binds, struct MalVal *exprs);
-Env *env_find(Env *env, char *key);
-struct MalVal *env_get(Env *env, char *key);
-Env *env_set(Env *env, char *key, struct MalVal *val);
+Env *env_find(Env *env, struct MalVal *key);
+struct MalVal *env_get(Env *env, struct MalVal *key);
+Env *env_set(Env *env, struct MalVal *key, struct MalVal *val);
// Utility functiosn
@@ -130,6 +130,7 @@ MalVal *malval_new_integer(gint64 val);
MalVal *malval_new_float(gdouble val);
MalVal *malval_new_string(char *val);
MalVal *malval_new_symbol(char *val);
+MalVal *malval_new_keyword(char *val);
MalVal *malval_new_list(MalType type, GArray *val);
MalVal *malval_new_hash_map(GHashTable *val);
MalVal *malval_new_atom(MalVal *val);