10 border-collapse: collapse;
16 border-left: solid
1px #
008;
18 table td:first-child, th:first-child {
31 border-color: lightgrey;
61 <h2>Make-A-Lisp Cheatsheet
</h2>
64 <th>Step
1</th> <th>Step
6</th>
68 <pre><code><span class=file>step0_repl.EXT</span>:
69 <span class=function>READ</span></span>(<span class=var>ast</span>): passthrough <span class=var>ast</span>
70 <span class=function>EVAL</span>(<span class=var>ast</span>, <span class=var>env</span>): passthrough <span class=var>ast</span>
71 <span class=function>PRINT</span>(<span class=var>ast</span>): passthrough <span class=var>ast</span>
72 <span class=function>main</span>(<span class=var>args</span>): loop: <span class=function>writeline</span> <span class=function>PRINT</span>(<span class=function>EVAL</span>(<span class=function>READ</span>(<span class=function>readline</span>()), <span class=string>""</span>))
79 <pre><code><span class=file
>reader.EXT
</span>:
80 <span class=object
>Reader
</span>(
<span class=var
>tokens
</span>) object:
<span class=var
>position
</span>,
<span class=function
>next
</span>(),
<span class=function
>peek
</span>()
81 <span class=function
>tokenize
</span>:
<span class=string
>/[\s,]*(~@|[\[\]{}()'`~^@]|
"(?:\\.|[^\\"])*
"|;.*|[^\s\[\]{}('"`,;)]*)/
</span>
82 <span class=function
>read_atom
</span>: int, float, string (escaped), keyword, nil, true, false, symbol
83 <span class=function
>read_list
</span>: repeatedly
<span class=function
>read_form
</span> until end token (
<span class=object
>EOF
</span> is error)
84 <span class=function
>read_form
</span>: expand reader macros,
<span class=function
>read_list
</span> (vector/maps too), or
<span class=function
>read_atom
</span>
85 <span class=function
>read_str
</span>:
<span class=function
>tokenize
</span>, error if no tokens, call
<span class=function
>read_form
</span>(
<span class=object
>Reader
</span>(
<span class=var
>tokens
</span>))
86 <span class=file
>printer.EXT
</span>:
87 <span class=function
>pr_str
</span>(
<span class=var
>ast
</span>,
<span class=var
>print_readably
</span>):
88 - map
<span class=function
>pr_str
</span> across collections
89 - unescape strings if
<span class=var
>print_readably
</span>
90 <span class=file
>step1_read_print.EXT
</span>:
91 <span class=function
>main
</span>(
<span class=var
>args
</span>): loop:
<span class=function
>writeline
</span> <span class=function
>PRINT
</span>(
<span class=function
>EVAL
</span>(
<span class=function
>READ
</span>(
<span class=function
>readline
</span>()),
<span class=string
>""</span>))
95 <pre><code><span class=file
>core.EXT
</span>:
96 <span class=function
>read-string
</span>: call
<span class=function
>reader.read_str
</span>
97 <span class=function
>slurp
</span>: return file content as a string
98 <span class=function
>atom
</span>,
<span class=function
>atom?
</span>,
<span class=function
>deref
</span>,
<span class=function
>reset!
</span>,
<span class=function
>swap!
</span>: atom functions
99 <span class=file
>step6_file.EXT
</span>:
100 <span class=function
>main
</span>(
<span class=var
>args
</span>):
101 - add
<span class=malsym
>eval
</span> and
<span class=malsym
>*ARGV*
</span> to
<span class=var
>repl_env
</span>
102 - define
<span class=malsym
>load-file
</span> using
<span class=function
>rep
</span>
103 - if
<span class=var
>args
</span>, set
<span class=malsym
>*ARGV*
</span> to rest(
<span class=var
>args
</span>) and call
<span class=malsym
>load-file
</span> with
<span class=var
>arg
</span>s[
0]
111 <th> </th> <th> </th>
113 <th>Step
2</th> <th>Step
7</th>
116 <pre><code><span class=file
>step2_eval.EXT
</span>:
117 <span class=function
>eval_ast
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>): lookup symbols in
<span class=var
>env
</span>, map
<span class=function
>EVAL
</span> across collections
118 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
119 - if not list?(
<span class=var
>ast
</span>), return
<span class=function
>eval_ast
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>)
120 - otherwise apply (
<span class=var
>ast
</span> is a list):
121 <span class=var
>el
</span> =
<span class=function
>eval_ast
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>)
122 return
<span class=var
>el
</span>[
0](rest(
<span class=var
>el
</span>))
123 <span class=function
>main
</span>(
<span class=var
>args
</span>): loop:
<span class=function
>writeline
</span> <span class=function
>PRINT
</span>(
<span class=function
>EVAL
</span>(
<span class=function
>READ
</span>(
<span class=function
>readline
</span>()), {
<span class=malsym
>+
</span>:
<span class=function
>add
</span>, ...}))
130 <pre><code><span class=file
>core.EXT
</span>:
131 <span class=function
>cons
</span>,
<span class=function
>concat
</span>: sequence functions
132 <span class=file
>step7_quote.EXT
</span>:
133 <span class=function
>quasiquote
</span>(ast):
134 -
<span class=var
>ast
</span> is empty or not a list -
> (
<span class=malsym
>quote
</span> <span class=var
>ast
</span>)
135 - (
<span class=malsym
>unquote
</span> FOO) -
> FOO
136 - ((
<span class=malsym
>splice-unquote
</span> FOO) BAR..) -
> (
<span class=malsym
>concat
</span> FOO
<span class=function
>quasiquote
</span>(BAR...))
</span>
137 - (FOO BAR...) -
> (
<span class=malsym
>cons
</span> FOO
<span class=function
>quasiquote
</span>(BAR...))
</span>
138 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
139 -
<span class=malsym
>quote
</span> -
> return
<span class=var
>ast
</span>[
1]
140 -
<span class=malsym
>quasiquote
</span> -
> set
<span class=var
>ast
</span> to
<span class=function
>quasiquote
</span>(
<span class=var
>ast
</span>[
1]), loop
144 <th> </th> <th> </th>
146 <th>Step
3</th> <th>Step
8</th>
149 <pre><code><span class=file
>env.EXT
</span>:
150 <span class=object
>Env
</span>(
<span class=var
>outer
</span>) object:
<span class=var
>data
</span>,
<span class=function
>set
</span>(
<span class=var
>k
</span>,
<span class=var
>v
</span>),
<span class=function
>find
</span>(
<span class=var
>k
</span>),
<span class=function
>get
</span>(
<span class=var
>k
</span>)
151 <span class=file
>step3_env.EXT
</span>:
152 <span class=function
>eval_ast
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>): switch to
<span class=var
>env
</span>.
<span class=function
>get
</span> for symbol lookup
153 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
154 -
<span class=malsym
>def!
</span> -
> return
<span class=var
>env
</span>.
<span class=function
>set
</span>(
<span class=var
>ast
</span>[
1],
<span class=function
>EVAL
</span>(
<span class=var
>ast
</span>[
2],
<span class=var
>env
</span>))
155 -
<span class=malsym
>let*
</span> -
> create new env
<span class=var
>let_env
</span>
156 for each ODD/EVEN pair in
<span class=var
>ast[
1]
</span>:
157 <span class=var
>let_env
</span>.
<span class=function
>set
</span>(ODD,
<span class=function
>EVAL
</span>(EVEN,
<span class=var
>let_env
</span>))
158 return
<span class=function
>EVAL
</span>(
<span class=var
>ast
</span>[
2],
<span class=var
>let_env
</span>)
159 <span class=function
>main
</span>(
<span class=var
>args
</span>): populate
<span class=var
>repl_env
</span> with numeric functions using
<span class=var
>repl_env
</span>.
<span class=function
>set
</span>
163 <pre><code><span class=file
>core.EXT
</span>:
164 <span class=function
>nth
</span>,
<span class=function
>first
</span>,
<span class=function
>rest
</span>: sequence functions
165 <span class=file
>step8_macros.EXT
</span>:
166 <span class=function
>macroexpand
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
167 - while
<span class=var
>env
</span>.
<span class=function
>get
</span>(
<span class=var
>ast
</span>[
0]) is a macro:
<span class=var
>ast
</span> =
<span class=var
>env
</span>.
<span class=function
>get
</span>(
<span class=var
>ast
</span>[
0])(rest(
<span class=var
>ast
</span>))
168 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
169 - before apply section, add
<span class=var
>ast
</span> =
<span class=function
>macroexpand
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>)
170 -
<span class=malsym
>defmacro!
</span> -
> same as
<span class=malsym
>def!
</span>, but set mal function macro flag
171 -
<span class=malsym
>macroexpand
</span> -
> return
<span class=function
>macroexpand
</span>(
<span class=var
>ast
</span>[
1],
<span class=var
>env
</span>)
177 <th> </th> <th> </th>
179 <th>Step
4</th> <th>Step
9</th>
182 <pre><code><span class=file
>env.EXT
</span>:
183 <span class=object
>Env
</span>(
<span class=var
>outer
</span>,
<span class=var
>binds
</span>,
<span class=var
>exprs
</span>) object: map
<span class=var
>binds
</span> to
<span class=var
>exprs
</span>, handle
<span class=string
>"&"</span> as variadic
184 <span class=file
>core.EXT
</span>:
185 <span class=function
>=
</span>: recursive compare of collections
186 <span class=function
>pr-str
</span>,
<span class=function
>str
</span>: return
<span class=function
>pr_str
</span>(
<span class=function
>arg
</span>, true) join
<span class=string
>" "</span>,
<span class=function
>pr_str
</span>(
<span class=function
>arg
</span>, false) join
<span class=string
>""</span>
187 <span class=function
>prn
</span>,
<span class=function
>println
</span>: print
<span class=function
>pr_str
</span>(
<span class=function
>arg
</span>, true) join
<span class=string
>""</span>,
<span class=function
>pr_str
</span>(
<span class=function
>arg
</span>, false) join
<span class=string
>""</span>
188 <span class=function
><
</span>,
<span class=function
><=
</span>,
<span class=function
>></span>,
<span class=function
>>=
</span>,
<span class=function
>+
</span>,
<span class=function
>-
</span>,
<span class=function
>*
</span>,
<span class=function
>/
</span>: numeric comparison and numeric operations
189 <span class=function
>list
</span>,
<span class=function
>list?
</span>,
<span class=function
>empty?
</span>,
<span class=function
>count
</span>: sequence functions
190 <span class=file
>step4_do_if_fn.EXT
</span>:
191 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
192 -
<span class=malsym
>do
</span> -
> return last element of
<span class=function
>eval_ast
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>)
193 -
<span class=malsym
>if
</span> -
> if
<span class=function
>EVAL
</span>(
<span class=var
>ast[
1]
</span>,
<span class=var
>env
</span>): return
<span class=function
>EVAL
</span>(
<span class=var
>ast[
2]
</span>,
<span class=var
>env
</span>)
194 else : return
<span class=function
>EVAL
</span>(
<span class=var
>ast[
3]
</span>,
<span class=var
>env
</span>)
195 -
<span class=malsym
>fn*
</span> -
> return closure:
196 (
<span class=var
>args
</span>) -
> <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>[
2], new
<span class=object
>Env
</span>(
<span class=var
>env
</span>,
<span class=var
>ast
</span>[
1],
<span class=var
>args
</span>))
197 <span class=function
>main
</span>(
<span class=var
>args
</span>): populate
<span class=var
>repl_env
</span> with core functions, define not using
<span class=function
>rep
</span>()
201 <pre><code><span class=file
>core.EXT
</span>:
202 <span class=function
>throw
</span>: raise mal value as exception (maybe wrap in native exception)
203 <span class=function
>vector
</span>,
<span class=function
>vector?
</span>: sequence functions
204 <span class=function
>hash-map
</span>,
<span class=function
>get
</span>,
<span class=function
>contains?
</span>,
<span class=function
>keys
</span>,
<span class=function
>vals
</span>: hash-map functions
205 <span class=function
>assoc
</span>,
<span class=function
>dissoc
</span>: immutable hash-map transform functions
206 <span class=function
>apply
</span>(
<span class=var
>f
</span>,
<span class=var
>args...
</span>,
<span class=var
>last
</span>): return
<span class=function
>f
</span>(
<span class=function
>concat
</span>(
<span class=var
>args
</span>,
<span class=var
>last
</span>))
207 <span class=function
>map
</span>(
<span class=var
>f
</span>,
<span class=var
>args
</span>): return list of mapping
<span class=function
>f
</span> on each
<span class=var
>args
</span>
208 <span class=file
>step9_try.EXT
</span>:
209 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
210 -
<span class=malsym
>try*
</span> -
> try
<span class=function
>EVAL
</span>(
<span class=var
>ast
</span>[
1],
<span class=var
>env
</span>)
211 catch exception
<span class=var
>exc
</span> (unwrap if necessary):
212 new
<span class=var
>err_env
</span> with
<span class=var
>ast
</span>[
2][
1] symbol bound to
<span class=var
>exc
</span>
213 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>[
2][
2],
<span class=var
>err_env
</span>)
220 <th> </th> <th> </th>
222 <th>Step
5</th> <th>Step A
</th>
225 <pre><code><span class=file
>step5_tco.EXT
</span>:
226 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
227 - top level loop in
<span class=function
>EVAL
</span>
228 -
<span class=malsym
>let*
</span> -
> set
<span class=var
>env
</span> to
<span class=var
>let_env
</span>, set
<span class=var
>ast
</span> to
<span class=var
>ast
</span>[
2], loop
229 -
<span class=malsym
>do
</span> -
> <span class=function
>eval_ast
</span> of middle elements, sets
<span class=var
>ast
</span> to last element, loop
230 -
<span class=malsym
>if
</span> -
> set
<span class=var
>ast
</span> to
<span class=var
>ast
</span>[
2] or
<span class=var
>ast
</span>[
3] (or
<span class=malsym
>nil
</span>) depending condition, loop
231 -
<span class=malsym
>fn*
</span> -
> return new mal function type
<span class=var
>f
</span> with:
232 <span class=var
>f
</span>.
<span class=var
>ast
</span>=
<span class=var
>ast
</span>[
2],
<span class=var
>f
</span>.
<span class=var
>params
</span>=
<span class=var
>ast
</span>[
1],
<span class=var
>f
</span>.
<span class=var
>env
</span>=
<span class=var
>env
</span>
233 - apply -
> <span class=var
>el
</span> =
<span class=function
>eval_ast
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>)
234 <span class=var
>f
</span> =
<span class=var
>el
</span>[
0]
235 if
<span class=var
>f
</span> is a mal function:
<span class=var
>ast
</span> =
<span class=var
>f
</span>.
<span class=var
>ast
</span> and
<span class=var
>env
</span> =
<span class=var
>f
</span>.
<span class=var
>env
</span>, loop
236 else : return
<span class=var
>el
</span>[
0](rest(
<span class=var
>el
</span>))
241 <pre><code><span class=file
>core.EXT
</span>:
242 <span class=function
>string?
</span>: true if string
243 <span class=function
>readline
</span>: prompt and read a line of input (synchronous)
244 <span class=function
>time-ms
</span>: return milliseconds since epoch (
1970-
1-
1)
245 <span class=function
>conj
</span>,
<span class=function
>seq
</span>: type specific sequence functions
246 <span class=function
>meta
</span>,
<span class=function
>with-meta
</span>: metadata functions
247 <span class=file
>step9_try.EXT
</span>:
248 <span class=function
>EVAL
</span>(
<span class=var
>ast
</span>,
<span class=var
>env
</span>):
249 - set
<span class=malsym
>*host-language*
</span> in
<span class=var
>repl_env
</span> to host language name
250 <span class=function
>main
</span>(
<span class=var
>args
</span>):
<span class=function
>rep
</span>(
<span class=string
>"(println (str \"Mal [\
" <span class=malsym>*host-language*</span> \"]\
"))"</span>)
254 <th> </th> <th> </th>