diff options
| author | Joel Martin <github@martintribe.org> | 2014-12-18 20:33:49 -0600 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-01-09 16:16:50 -0600 |
| commit | b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c (patch) | |
| tree | f4d977ed220e9a3f665cfbf4f68770a81e4c2095 /c | |
| parent | aaba249304b184e12e2445ab22d66df1f39a51a5 (diff) | |
| download | mal-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.c | 22 | ||||
| -rw-r--r-- | c/core.h | 2 | ||||
| -rw-r--r-- | c/env.c | 18 | ||||
| -rw-r--r-- | c/printer.c | 21 | ||||
| -rw-r--r-- | c/reader.c | 7 | ||||
| -rw-r--r-- | c/step3_env.c | 14 | ||||
| -rw-r--r-- | c/step4_if_fn_do.c | 17 | ||||
| -rw-r--r-- | c/step5_tco.c | 15 | ||||
| -rw-r--r-- | c/step6_file.c | 20 | ||||
| -rw-r--r-- | c/step7_quote.c | 20 | ||||
| -rw-r--r-- | c/step8_macros.c | 29 | ||||
| -rw-r--r-- | c/step9_try.c | 31 | ||||
| -rw-r--r-- | c/stepA_interop.c | 29 | ||||
| -rw-r--r-- | c/types.c | 8 | ||||
| -rw-r--r-- | c/types.h | 7 |
15 files changed, 162 insertions, 98 deletions
@@ -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}, @@ -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 @@ -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); @@ -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\")"); @@ -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); } @@ -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); |
