3 fun read(input: String?): MalType = read_str(input)
5 fun eval(ast: MalType, env: Map<String, MalType>): MalType =
7 val evaluated = eval_ast(ast, env) as ISeq
8 if (evaluated.first() !is MalFunction) throw MalException("cannot execute non-function")
9 (evaluated.first() as MalFunction).apply(evaluated.rest())
10 } else eval_ast(ast, env)
12 fun eval_ast(ast: MalType, env: Map<String, MalType>): MalType =
13 if (ast is MalSymbol) {
14 env.get(ast.value) ?: throw MalException("'${ast.value}' not found")
15 } else if (ast is MalList) {
16 ast.elements.fold(MalList(), { a, b -> a.conj_BANG(eval(b, env)); a })
17 } else if (ast is MalVector) {
18 ast.elements.fold(MalVector(), { a, b -> a.conj_BANG(eval(b, env)); a })
19 } else if (ast is MalHashMap) {
20 ast.elements.entries.fold(MalHashMap(), { a, b -> a.assoc_BANG(b.key, eval(b.value, env)); a })
23 fun print(result: MalType) = pr_str(result, print_readably = true)
25 fun main(args: Array<String>) {
27 Pair("+", MalFunction({ a: ISeq -> a.seq().reduce({ x, y -> x as MalInteger + y as MalInteger }) })),
28 Pair("-", MalFunction({ a: ISeq -> a.seq().reduce({ x, y -> x as MalInteger - y as MalInteger }) })),
29 Pair("*", MalFunction({ a: ISeq -> a.seq().reduce({ x, y -> x as MalInteger * y as MalInteger }) })),
30 Pair("/", MalFunction({ a: ISeq -> a.seq().reduce({ x, y -> x as MalInteger / y as MalInteger }) }))
34 val input = readline("user> ") ?: break
37 println(print(eval(read(input), env)))
38 } catch (e: MalContinue) {
39 } catch (e: MalException) {
40 println("Error: " + e.message)
41 } catch (t: Throwable) {
42 println("Uncaught " + t + ": " + t.message)