11 MalVal
*EVAL(MalVal
*ast
, GHashTable
*env
);
14 MalVal
*READ(char prompt
[], char *str
) {
20 line
= _readline(prompt
);
27 if (!str
) { MAL_GC_FREE(line
); }
32 MalVal
*eval_ast(MalVal
*ast
, GHashTable
*env
) {
33 if (!ast
|| mal_error
) return NULL
;
34 if (ast
->type
== MAL_SYMBOL
) {
35 //g_print("EVAL symbol: %s\n", ast->val.string);
36 // TODO: check if not found
37 MalVal
*res
= g_hash_table_lookup(env
, ast
->val
.string
);
38 assert(res
, "'%s' not found", ast
->val
.string
);
40 } else if ((ast
->type
== MAL_LIST
) || (ast
->type
== MAL_VECTOR
)) {
41 //g_print("EVAL sequential: %s\n", _pr_str(ast,1));
42 MalVal
*el
= _map2((MalVal
*(*)(void*, void*))EVAL
, ast
, env
);
43 if (!el
|| mal_error
) return NULL
;
46 } else if (ast
->type
== MAL_HASH_MAP
) {
47 //g_print("EVAL hash_map: %s\n", _pr_str(ast,1));
50 MalVal
*seq
= malval_new_list(MAL_LIST
,
51 g_array_sized_new(TRUE
, TRUE
, sizeof(MalVal
*),
53 g_hash_table_iter_init (&iter
, ast
->val
.hash_table
);
54 while (g_hash_table_iter_next (&iter
, &key
, &value
)) {
55 MalVal
*kname
= malval_new_string((char *)key
);
56 g_array_append_val(seq
->val
.array
, kname
);
57 MalVal
*new_val
= EVAL((MalVal
*)value
, env
);
58 g_array_append_val(seq
->val
.array
, new_val
);
60 return _hash_map(seq
);
62 //g_print("EVAL scalar: %s\n", _pr_str(ast,1));
67 MalVal
*EVAL(MalVal
*ast
, GHashTable
*env
) {
68 if (!ast
|| mal_error
) return NULL
;
69 //g_print("EVAL: %s\n", _pr_str(ast,1));
70 if (ast
->type
!= MAL_LIST
) {
71 return eval_ast(ast
, env
);
73 if (!ast
|| mal_error
) return NULL
;
76 //g_print("EVAL apply list: %s\n", _pr_str(ast,1));
77 if (_count(ast
) == 0) { return ast
; }
78 MalVal
*a0
= _nth(ast
, 0);
79 assert_type(a0
, MAL_SYMBOL
, "Cannot invoke %s", _pr_str(a0
,1));
80 MalVal
*el
= eval_ast(ast
, env
);
81 if (!el
|| mal_error
) { return NULL
; }
82 MalVal
*(*f
)(void *, void*) = (MalVal
*(*)(void*, void*))_first(el
);
83 //g_print("eval_invoke el: %s\n", _pr_str(el,1));
84 return f(_nth(el
, 1), _nth(el
, 2));
88 char *PRINT(MalVal
*exp
) {
92 return _pr_str(exp
,1);
98 MalVal
*RE(GHashTable
*env
, char *prompt
, char *str
) {
100 ast
= READ(prompt
, str
);
101 if (!ast
|| mal_error
) return NULL
;
102 exp
= EVAL(ast
, env
);
104 malval_free(ast
); // Free input structure
109 // Setup the initial REPL environment
110 GHashTable
*repl_env
;
112 WRAP_INTEGER_OP(plus
,+)
113 WRAP_INTEGER_OP(minus
,-)
114 WRAP_INTEGER_OP(multiply
,*)
115 WRAP_INTEGER_OP(divide
,/)
117 void init_repl_env() {
118 repl_env
= g_hash_table_new(g_str_hash
, g_str_equal
);
120 g_hash_table_insert(repl_env
, "+", int_plus
);
121 g_hash_table_insert(repl_env
, "-", int_minus
);
122 g_hash_table_insert(repl_env
, "*", int_multiply
);
123 g_hash_table_insert(repl_env
, "/", int_divide
);
134 // Set the initial prompt and environment
135 snprintf(prompt
, sizeof(prompt
), "user> ");
140 exp
= RE(repl_env
, prompt
, NULL
);
141 if (mal_error
&& strcmp("EOF", mal_error
->val
.string
) == 0) {
147 fprintf(stderr
, "Error: %s\n", _pr_str(mal_error
,1));
148 malval_free(mal_error
);
152 MAL_GC_FREE(output
); // Free output string
155 //malval_free(exp); // Free evaluated expression