mirror of
https://github.com/kanaka/mal.git
synced 2024-09-21 10:37:58 +03:00
54 lines
1.4 KiB
Plaintext
54 lines
1.4 KiB
Plaintext
readline = require './node_readline'
|
|
{id, map, Obj} = require 'prelude-ls'
|
|
{read_str} = require './reader'
|
|
{pr_str} = require './printer'
|
|
|
|
repl_env = do
|
|
'+':
|
|
type: \function
|
|
value: (a, b) -> {type: \int, value: a.value + b.value}
|
|
'-':
|
|
type: \function
|
|
value: (a, b) -> {type: \int, value: a.value - b.value}
|
|
'*':
|
|
type: \function
|
|
value: (a, b) -> {type: \int, value: a.value * b.value}
|
|
'/':
|
|
type: \function
|
|
value: (a, b) -> {type: \int, value: parseInt(a.value / b.value)}
|
|
|
|
eval_ast = (repl_env, {type, value}: ast) -->
|
|
switch type
|
|
| \symbol =>
|
|
result = repl_env[value]
|
|
if not result? then throw new Error 'symbol not found: ', value
|
|
result
|
|
| \list, \vector =>
|
|
result = value |> map eval_ast repl_env
|
|
if type == \list and result.length != 0
|
|
fn = result[0]
|
|
if fn.type != \function
|
|
throw new Error fn.value, ' is not a function'
|
|
fn.value.apply repl_env, result.slice 1
|
|
else
|
|
{type: type, value: result}
|
|
| \map =>
|
|
{type: \map, value: value |> Obj.map eval_ast repl_env}
|
|
| otherwise =>
|
|
ast
|
|
|
|
|
|
rep = (line) ->
|
|
line
|
|
|> read_str
|
|
|> eval_ast repl_env
|
|
|> pr_str
|
|
|
|
loop
|
|
line = readline.readline 'user> '
|
|
break if not line? or line == ''
|
|
try
|
|
console.log rep line
|
|
catch {message}
|
|
console.error message
|