Commit | Line | Data |
---|---|---|
cb86911f | 1 | readline = require './node_readline' |
2ff2d84b | 2 | {id, map, Obj} = require 'prelude-ls' |
cb86911f JB |
3 | {read_str} = require './reader' |
4 | {pr_str} = require './printer' | |
5 | ||
6 | repl_env = do | |
7 | '+': | |
8 | type: \function | |
9 | value: (a, b) -> {type: \int, value: a.value + b.value} | |
10 | '-': | |
11 | type: \function | |
12 | value: (a, b) -> {type: \int, value: a.value - b.value} | |
13 | '*': | |
14 | type: \function | |
15 | value: (a, b) -> {type: \int, value: a.value * b.value} | |
16 | '/': | |
17 | type: \function | |
18 | value: (a, b) -> {type: \int, value: parseInt(a.value / b.value)} | |
19 | ||
20 | eval_ast = (repl_env, {type, value}: ast) --> | |
21 | switch type | |
22 | | \symbol => | |
23 | result = repl_env[value] | |
24 | if not result? then throw new Error 'symbol not found: ', value | |
25 | result | |
26 | | \list, \vector => | |
27 | result = value |> map eval_ast repl_env | |
28 | if type == \list and result.length != 0 | |
29 | fn = result[0] | |
30 | if fn.type != \function | |
31 | throw new Error fn.value, ' is not a function' | |
32 | fn.value.apply repl_env, result.slice 1 | |
33 | else | |
34 | {type: type, value: result} | |
2ff2d84b JB |
35 | | \map => |
36 | {type: \map, value: value |> Obj.map eval_ast repl_env} | |
cb86911f JB |
37 | | otherwise => |
38 | ast | |
39 | ||
40 | ||
41 | rep = (line) -> | |
42 | line | |
43 | |> read_str | |
44 | |> eval_ast repl_env | |
45 | |> pr_str | |
46 | ||
47 | loop | |
48 | line = readline.readline 'user> ' | |
49 | break if not line? or line == '' | |
50 | try | |
51 | console.log rep line | |
52 | catch {message} | |
53 | console.error message |