1 readline
= require
'./node_readline'
2 {id
, map
, each
} = require
'prelude-ls'
3 {read_str
} = require
'./reader'
4 {pr_str
} = require
'./printer'
5 {Env
} = require
'./env'
7 repl_env
= new Env null
, do
10 value
: (a
, b
) -> {type
: \int
, value
: a.value + b.value
}
13 value
: (a
, b
) -> {type
: \int
, value
: a.value
- b.value
}
16 value
: (a
, b
) -> {type
: \int
, value
: a.value
* b.value
}
19 value
: (a
, b
) -> {type
: \int
, value
: parseInt
(a.value
/ b.value
)}
22 is
-symbol
= ({type
, value
}: ast
, name
) ->
23 type
== \symbol and value
== name
26 list
-to
-pairs
= (list
) ->
27 [0 to
(list.length
- 2) by
2] \
28 |
> map
(idx
) -> [list
[idx
], list
[idx+
1]]
31 eval_simple
= (env
, {type
, value
}: ast
) ->
33 | \symbol
=> env.get value
34 | \list
, \vector
=> do
36 value
: value |
> map eval_ast env
40 eval_ast
= (env
, {type
, value
}: ast
) -->
41 if type
!= \list then eval_simple env
, ast
42 else if value.length
== 0 then ast
43 else if value
[0].type
== \symbol
46 |
'def!' => eval_def env, params
47 |
'let*' => eval_let env, params
48 | otherwise
=> eval_apply env
, value
53 check_params
= (name
, params
, expected
) ->
54 if params.length
!= expected
55 throw new
Error "#
{name
} expected #
{expected
} parameters
,
59 eval_def
= (env
, params
) ->
60 check_params
'def!', params, 2
62 #
Name is in the first parameter
, and is not evaluated.
64 if name.type
!= \symbol
65 throw new
Error "expected a symbol for the first parameter
66 of def
!, got a #
{name.type
}"
68 #
Evaluate the second parameter and store
69 # it under name in the env.
70 env.set name.value
, (eval_ast env
, params
[1])
73 eval_let
= (env
, params
) ->
74 check_params
'let*', params, 2
76 binding_list
= params
[0]
77 if binding_list.type not in
[\list \vector
]
78 throw new
Error "expected
1st parameter of let
* to
79 be a binding list
(or vector
),
80 got a #
{binding_list.type
}"
81 else if binding_list.value.length %
2 != 0
82 throw new
Error "binding list of let
* must have an even
85 # Make a new environment with the
86 # current environment as outer.
89 #
Evaluate all binding values in the
93 |
> each
([binding_name
, binding_value
]) ->
94 if binding_name.type
!= \symbol
95 throw new
Error "expected a symbol as binding name
,
96 got a #
{binding_name.type
}"
98 let_env.set binding_name.value
, (eval_ast let_env
, binding_value
)
100 #
Evaluate the
'body' of let* with the new environment.
101 eval_ast let_env
, params
[1]
104 eval_apply
= (env
, list
) ->
105 [fn
, ...args
] = list |
> map eval_ast env
106 if fn.type
!= \function
107 throw new
Error fn.value
, ' is not a function'
108 fn.value.apply env
, args
119 line
= readline.readline
'user> '
120 break if not line? or line
== ''
125 then console.error error.message
126 else console.error "
Error:"
, pr_str error
, print_readably
=true