Commit | Line | Data |
---|---|---|
e10ceff5 JM |
1 | import rl from './node_readline.js' |
2 | const readline = rl.readline | |
a05c086f | 3 | import { _list_Q } from './types' |
4f8c7db9 JM |
4 | import { BlankException, read_str } from './reader' |
5 | import { pr_str } from './printer' | |
6 | import { new_env, env_set, env_get } from './env' | |
732f2170 JM |
7 | |
8 | // read | |
a05c086f | 9 | const READ = str => read_str(str) |
732f2170 JM |
10 | |
11 | // eval | |
12 | const eval_ast = (ast, env) => { | |
a05c086f | 13 | if (typeof ast === 'symbol') { |
5024b694 | 14 | return env_get(env, ast) |
a05c086f JM |
15 | } else if (ast instanceof Array) { |
16 | return ast.map(x => EVAL(x, env)) | |
17 | } else if (ast instanceof Map) { | |
4f8c7db9 | 18 | let new_hm = new Map() |
a05c086f | 19 | ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env))) |
4f8c7db9 | 20 | return new_hm |
732f2170 | 21 | } else { |
4f8c7db9 | 22 | return ast |
732f2170 JM |
23 | } |
24 | } | |
25 | ||
26 | const EVAL = (ast, env) => { | |
4f8c7db9 | 27 | //console.log('EVAL:', pr_str(ast, true)) |
732f2170 | 28 | if (!_list_Q(ast)) { return eval_ast(ast, env) } |
f8665761 | 29 | if (ast.length === 0) { return ast } |
732f2170 | 30 | |
4f8c7db9 | 31 | const [a0, a1, a2, a3] = ast |
a05c086f JM |
32 | switch (typeof a0 === 'symbol' ? Symbol.keyFor(a0) : Symbol(':default')) { |
33 | case 'def!': | |
4f8c7db9 | 34 | return env_set(env, a1, EVAL(a2, env)) |
732f2170 | 35 | case 'let*': |
4f8c7db9 | 36 | let let_env = new_env(env) |
732f2170 | 37 | for (let i=0; i < a1.length; i+=2) { |
4f8c7db9 | 38 | env_set(let_env, a1[i], EVAL(a1[i+1], let_env)) |
732f2170 | 39 | } |
4f8c7db9 | 40 | return EVAL(a2, let_env) |
732f2170 | 41 | default: |
4f8c7db9 JM |
42 | let [f, ...args] = eval_ast(ast, env) |
43 | return f(...args) | |
732f2170 JM |
44 | } |
45 | } | |
46 | ||
47 | ||
a05c086f | 48 | const PRINT = exp => pr_str(exp, true) |
732f2170 JM |
49 | |
50 | // repl | |
4f8c7db9 | 51 | let repl_env = new_env() |
a05c086f JM |
52 | env_set(repl_env, Symbol.for('+'), (a,b) => a+b) |
53 | env_set(repl_env, Symbol.for('-'), (a,b) => a-b) | |
54 | env_set(repl_env, Symbol.for('*'), (a,b) => a*b) | |
55 | env_set(repl_env, Symbol.for('/'), (a,b) => a/b) | |
56 | const REP = str => PRINT(EVAL(READ(str), repl_env)) | |
732f2170 JM |
57 | |
58 | while (true) { | |
4f8c7db9 JM |
59 | let line = readline('user> ') |
60 | if (line == null) break | |
732f2170 | 61 | try { |
a05c086f | 62 | if (line) { console.log(REP(line)) } |
732f2170 | 63 | } catch (exc) { |
a05c086f JM |
64 | if (exc instanceof BlankException) { continue } |
65 | if (exc.stack) { console.log(exc.stack) } | |
66 | else { console.log(`Error: ${exc}`) } | |
732f2170 JM |
67 | } |
68 | } |