1 import { readline
} from './node_readline'
2 import { _list_Q
} from './types'
3 import { BlankException
, read_str
} from './reader'
4 import { pr_str
} from './printer'
5 import { new_env
, env_set
, env_get
} from './env'
6 import { core_ns
} from './core'
9 const READ
= str
=> read_str(str
)
12 const eval_ast
= (ast
, env
) => {
13 if (typeof ast
=== 'symbol') {
14 return env_get(env
, ast
)
15 } else if (ast
instanceof Array
) {
16 return ast
.map(x
=> EVAL(x
, env
))
17 } else if (ast
instanceof Map
) {
18 let new_hm
= new Map()
19 ast
.forEach((v
, k
) => new_hm
.set(EVAL(k
, env
), EVAL(v
, env
)))
26 const EVAL
= (ast
, env
) => {
27 //console.log('EVAL:', pr_str(ast, true))
28 if (!_list_Q(ast
)) { return eval_ast(ast
, env
) }
29 if (ast
.length
=== 0) { return ast
}
31 const [a0
, a1
, a2
, a3
] = ast
32 switch (typeof a0
=== 'symbol' ? Symbol
.keyFor(a0
) : Symbol(':default')) {
34 return env_set(env
, a1
, EVAL(a2
, env
))
36 let let_env
= new_env(env
)
37 for (let i
=0; i
< a1
.length
; i
+=2) {
38 env_set(let_env
, a1
[i
], EVAL(a1
[i
+1], let_env
))
40 return EVAL(a2
, let_env
)
42 return eval_ast(ast
.slice(1), env
)[ast
.length
-2]
44 let cond
= EVAL(a1
, env
)
45 if (cond
=== null || cond
=== false) {
46 return typeof a3
!== 'undefined' ? EVAL(a3
, env
) : null
51 return (...args
) => EVAL(a2
, new_env(env
, a1
, args
))
53 let [f
, ...args
] = eval_ast(ast
, env
)
59 const PRINT
= exp
=> pr_str(exp
, true)
62 let repl_env
= new_env()
63 const REP
= str
=> PRINT(EVAL(READ(str
), repl_env
))
65 // core.EXT: defined using ES6
66 for (let [k
, v
] of core_ns
) { env_set(repl_env
, Symbol
.for(k
), v
) }
68 // core.mal: defined using language itself
69 REP('(def! not (fn* (a) (if a false true)))')
72 let line
= readline('user> ')
73 if (line
== null) break
75 if (line
) { console
.log(REP(line
)) }
77 if (exc
instanceof BlankException
) { continue }
78 if (exc
.stack
) { console
.log(exc
.stack
) }
79 else { console
.log(`Error: ${exc}`) }