Merge pull request #400 from asarhaddon/improve-mal-impl-macro-no-meta
[jackhill/mal.git] / yorick / step3_env.i
CommitLineData
21986733
DM
1set_path, get_env("YORICK_MAL_PATH") + ":" + get_path()
2require, "reader.i"
3require, "printer.i"
4require, "core.i"
5require, "env.i"
6
7func READ(str)
8{
9 return read_str(str)
10}
11
12func eval_ast(ast, env)
13{
14 type = structof(ast)
15 if (type == MalSymbol) {
16 return env_get(env, ast.val)
17 } else if (type == MalList) {
18 seq = *(ast.val)
19 res = array(pointer, numberof(seq))
20 for (i = 1; i <= numberof(seq); ++i) {
21 e = EVAL(*seq(i), env)
22 if (structof(e) == MalError) return e
23 res(i) = &e
24 }
25 return MalList(val=&res)
26 } else if (type == MalVector) {
27 seq = *(ast.val)
28 res = array(pointer, numberof(seq))
29 for (i = 1; i <= numberof(seq); ++i) {
30 e = EVAL(*seq(i), env)
31 if (structof(e) == MalError) return e
32 res(i) = &e
33 }
34 return MalVector(val=&res)
35 } else if (type == MalHashmap) {
36 h = *(ast.val)
37 if (numberof(*h.keys) == 0) return ast
38 res = hash_new()
39 for (i = 1; i <= numberof(*h.keys); ++i) {
40 new_key = EVAL(hashmap_key_to_obj((*h.keys)(i)), env)
41 if (structof(new_key) == MalError) return new_key
42 new_val = EVAL(*((*h.vals)(i)), env)
43 if (structof(new_val) == MalError) return new_val
44 hash_set, res, hashmap_obj_to_key(new_key), new_val
45 }
46 return MalHashmap(val=&res)
47 } else return ast
48}
49
50func EVAL(ast, env)
51{
52 if (structof(ast) == MalError) return ast
53 if (structof(ast) != MalList) return eval_ast(ast, env)
54 lst = *ast.val
55 if (numberof(lst) == 0) return ast
56 a1 = lst(1)->val
57 if (a1 == "def!") {
58 new_value = EVAL(*lst(3), env)
59 if (structof(new_value) == MalError) return new_value
60 return env_set(env, lst(2)->val, new_value)
61 } else if (a1 == "let*") {
62 let_env = env_new(&env)
63 args_lst = *(lst(2)->val)
64 for (i = 1; i <= numberof(args_lst); i += 2) {
65 var_name = args_lst(i)->val
66 var_value = EVAL(*args_lst(i + 1), let_env)
67 if (structof(var_value) == MalError) return var_value
68 env_set, let_env, var_name, var_value
69 }
70 return EVAL(*lst(3), let_env)
71 } else {
72 el = eval_ast(ast, env)
73 if (structof(el) == MalError) return el
74 seq = *el.val
75 args = (numberof(seq) > 1) ? seq(2:) : []
76 return call_core_fn(seq(1)->val, args)
77 }
78}
79
80func PRINT(exp)
81{
82 if (structof(exp) == MalError) return exp
83 return pr_str(exp, 1)
84}
85
86func REP(str, env)
87{
88 return PRINT(EVAL(READ(str), env))
89}
90
91func main(void)
92{
93 repl_env = env_new(pointer(0))
94 env_set, repl_env, "+", MalNativeFunction(val="+")
95 env_set, repl_env, "-", MalNativeFunction(val="-")
96 env_set, repl_env, "*", MalNativeFunction(val="*")
97 env_set, repl_env, "/", MalNativeFunction(val="/")
98
99 stdin_file = open("/dev/stdin", "r")
100 while (1) {
101 write, format="%s", "user> "
102 line = rdline(stdin_file, prompt="")
103 if (!line) break
104 if (strlen(line) > 0) {
105 result = REP(line, repl_env)
106 if (structof(result) == MalError) write, format="Error: %s\n", result.message
107 else write, format="%s\n", result
108 }
109 }
110 write, ""
111}
112
113main;