Merge branch 'master' into issue_166_string_ops
[jackhill/mal.git] / es6 / step2_eval.js
CommitLineData
4f8c7db9
JM
1import { readline } from './node_readline'
2import { _symbol, _symbol_Q, _list_Q, _vector, _vector_Q,
3 _hash_map_Q } from './types'
4import { BlankException, read_str } from './reader'
5import { pr_str } from './printer'
732f2170
JM
6
7// read
4f8c7db9 8const READ = (str) => read_str(str)
732f2170
JM
9
10// eval
11const eval_ast = (ast, env) => {
4f8c7db9
JM
12 if (_symbol_Q(ast)) {
13 if (ast in env) {
732f2170
JM
14 return env[ast]
15 } else {
4f8c7db9 16 throw Error(`'${Symbol.keyFor(ast)}' not found`)
732f2170
JM
17 }
18 } else if (_list_Q(ast)) {
4f8c7db9 19 return ast.map((x) => EVAL(x, env))
afa79313 20 } else if (_vector_Q(ast)) {
4f8c7db9 21 return _vector(...ast.map((x) => EVAL(x, env)))
afa79313 22 } else if (_hash_map_Q(ast)) {
4f8c7db9 23 let new_hm = new Map()
afa79313 24 for (let [k, v] of ast) {
4f8c7db9 25 new_hm.set(EVAL(k, env), EVAL(v, env))
afa79313 26 }
4f8c7db9 27 return new_hm
732f2170 28 } else {
4f8c7db9 29 return ast
732f2170
JM
30 }
31}
32
33const EVAL = (ast, env) => {
34 if (!_list_Q(ast)) { return eval_ast(ast, env) }
35
4f8c7db9
JM
36 const [f, ...args] = eval_ast(ast, env)
37 return f(...args)
732f2170
JM
38}
39
40// print
4f8c7db9 41const PRINT = (exp) => pr_str(exp, true)
732f2170
JM
42
43// repl
4f8c7db9
JM
44var repl_env = {[_symbol('+')]: (a,b) => a+b,
45 [_symbol('-')]: (a,b) => a-b,
46 [_symbol('*')]: (a,b) => a*b,
47 [_symbol('/')]: (a,b) => a/b}
48const REP = (str) => PRINT(EVAL(READ(str), repl_env))
732f2170
JM
49
50while (true) {
4f8c7db9
JM
51 let line = readline('user> ')
52 if (line == null) break
732f2170
JM
53 try {
54 if (line) { console.log(REP(line)); }
55 } catch (exc) {
56 if (exc instanceof BlankException) { continue; }
57 if (exc.stack) { console.log(exc.stack); }
4f8c7db9 58 else { console.log(`Error: ${exc}`); }
732f2170
JM
59 }
60}