Commit | Line | Data |
---|---|---|
21986733 DM |
1 | set_path, get_env("YORICK_MAL_PATH") + ":" + get_path() |
2 | require, "reader.i" | |
3 | require, "printer.i" | |
4 | require, "core.i" | |
5 | ||
6 | func READ(str) | |
7 | { | |
8 | return read_str(str) | |
9 | } | |
10 | ||
11 | func eval_ast(ast, env) | |
12 | { | |
13 | type = structof(ast) | |
14 | if (type == MalSymbol) { | |
15 | val = h_get(env, ast.val) | |
16 | if (is_void(val)) return MalError(message=("'" + ast.val + "' not found")) | |
17 | return val | |
18 | } else if (type == MalList) { | |
19 | seq = *(ast.val) | |
20 | res = array(pointer, numberof(seq)) | |
21 | for (i = 1; i <= numberof(seq); ++i) { | |
22 | e = EVAL(*seq(i), env) | |
23 | if (structof(e) == MalError) return e | |
24 | res(i) = &e | |
25 | } | |
26 | return MalList(val=&res) | |
27 | } else if (type == MalVector) { | |
28 | seq = *(ast.val) | |
29 | res = array(pointer, numberof(seq)) | |
30 | for (i = 1; i <= numberof(seq); ++i) { | |
31 | e = EVAL(*seq(i), env) | |
32 | if (structof(e) == MalError) return e | |
33 | res(i) = &e | |
34 | } | |
35 | return MalVector(val=&res) | |
36 | } else if (type == MalHashmap) { | |
37 | h = *(ast.val) | |
38 | if (numberof(*h.keys) == 0) return ast | |
39 | res = hash_new() | |
40 | for (i = 1; i <= numberof(*h.keys); ++i) { | |
41 | new_key = EVAL(hashmap_key_to_obj((*h.keys)(i)), env) | |
42 | if (structof(new_key) == MalError) return new_key | |
43 | new_val = EVAL(*((*h.vals)(i)), env) | |
44 | if (structof(new_val) == MalError) return new_val | |
45 | hash_set, res, hashmap_obj_to_key(new_key), new_val | |
46 | } | |
47 | return MalHashmap(val=&res) | |
48 | } else return ast | |
49 | } | |
50 | ||
51 | func EVAL(ast, env) | |
52 | { | |
53 | if (structof(ast) == MalError) return ast | |
54 | if (structof(ast) != MalList) return eval_ast(ast, env) | |
55 | if (numberof(*ast.val) == 0) return ast | |
56 | el = eval_ast(ast, env) | |
57 | if (structof(el) == MalError) return el | |
58 | seq = *el.val | |
59 | args = (numberof(seq) > 1) ? seq(2:) : [] | |
60 | return call_core_fn(seq(1)->val, args) | |
61 | } | |
62 | ||
63 | func PRINT(exp) | |
64 | { | |
65 | if (structof(exp) == MalError) return exp | |
66 | return pr_str(exp, 1) | |
67 | } | |
68 | ||
69 | func REP(str, env) | |
70 | { | |
71 | return PRINT(EVAL(READ(str), env)) | |
72 | } | |
73 | ||
74 | func main(void) | |
75 | { | |
76 | repl_env = h_new() | |
77 | h_set, repl_env, "+", MalNativeFunction(val="+") | |
78 | h_set, repl_env, "-", MalNativeFunction(val="-") | |
79 | h_set, repl_env, "*", MalNativeFunction(val="*") | |
80 | h_set, repl_env, "/", MalNativeFunction(val="/") | |
81 | ||
82 | stdin_file = open("/dev/stdin", "r") | |
83 | while (1) { | |
84 | write, format="%s", "user> " | |
85 | line = rdline(stdin_file, prompt="") | |
86 | if (!line) break | |
87 | if (strlen(line) > 0) { | |
88 | result = REP(line, repl_env) | |
89 | if (structof(result) == MalError) write, format="Error: %s\n", result.message | |
90 | else write, format="%s\n", result | |
91 | } | |
92 | } | |
93 | write, "" | |
94 | } | |
95 | ||
96 | main; |