1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-17 16:47:22 +03:00
mal/impls/wren/step3_env.wren
Joel Martin 8a19f60386 Move implementations into impls/ dir
- Reorder README to have implementation list after "learning tool"
  bullet.

- This also moves tests/ and libs/ into impls. It would be preferrable
  to have these directories at the top level.  However, this causes
  difficulties with the wasm implementations which need pre-open
  directories and have trouble with paths starting with "../../". So
  in lieu of that, symlink those directories to the top-level.

- Move the run_argv_test.sh script into the tests directory for
  general hygiene.
2020-02-10 23:50:16 -06:00

79 lines
2.0 KiB
Plaintext

import "./env" for Env
import "./readline" for Readline
import "./reader" for MalReader
import "./printer" for Printer
import "./types" for MalSymbol, MalList, MalVector, MalMap
class Mal {
static read(str) {
return MalReader.read_str(str)
}
static eval_ast(ast, env) {
if (ast is MalSymbol) {
return env.get(ast.value)
} else if (ast is MalList) {
return MalList.new(ast.elements.map { |e| eval(e, env) }.toList)
} else if (ast is MalVector) {
return MalVector.new(ast.elements.map { |e| eval(e, env) }.toList)
} else if (ast is MalMap) {
var m = {}
for (e in ast.data) {
m[e.key] = eval(e.value, env)
}
return MalMap.new(m)
} else {
return ast
}
}
static eval(ast, env) {
if (!(ast is MalList)) return eval_ast(ast, env)
if (ast.isEmpty) return ast
if (ast[0] is MalSymbol) {
if (ast[0].value == "def!") {
return env.set(ast[1].value, eval(ast[2], env))
} else if (ast[0].value == "let*") {
var letEnv = Env.new(env)
var i = 0
while (i < ast[1].count) {
letEnv.set(ast[1][i].value, eval(ast[1][i + 1], letEnv))
i = i + 2
}
return eval(ast[2], letEnv)
}
}
var evaled_ast = eval_ast(ast, env)
var f = evaled_ast[0]
return f.call(evaled_ast[1..-1])
}
static print(ast) {
return Printer.pr_str(ast)
}
static rep(str) {
return print(eval(read(str), __repl_env))
}
static main() {
__repl_env = Env.new()
__repl_env.set("+", Fn.new { |a| a[0] + a[1] })
__repl_env.set("-", Fn.new { |a| a[0] - a[1] })
__repl_env.set("*", Fn.new { |a| a[0] * a[1] })
__repl_env.set("/", Fn.new { |a| a[0] / a[1] })
while (true) {
var line = Readline.readLine("user> ")
if (line == null) break
if (line != "") {
var fiber = Fiber.new { System.print(rep(line)) }
fiber.try()
if (fiber.error) System.print("Error: %(fiber.error)")
}
}
System.print()
}
}
Mal.main()