Commit | Line | Data |
---|---|---|
a15f76bd JM |
1 | <html> |
2 | <head> | |
3 | <style> | |
4 | h2 { | |
5 | text-align: center; | |
6 | } | |
7 | table { | |
8 | font-size: 11px; | |
9 | border-width: 0px; | |
10 | border-collapse: collapse; | |
11 | } | |
12 | table tr { | |
13 | border: none; | |
14 | } | |
15 | table td,th { | |
16 | border-left: solid 1px #008; | |
17 | } | |
18 | table td:first-child, th:first-child { | |
19 | border-left: none; | |
20 | } | |
21 | ||
22 | table td { | |
23 | vertical-align: top; | |
24 | padding: 2px; | |
25 | } | |
26 | pre { | |
27 | background: #FCFCF9; | |
28 | padding: 3px; | |
29 | border-width: 1px; | |
30 | border-style: solid; | |
31 | border-color: lightgrey; | |
32 | } | |
33 | ||
34 | .file { | |
35 | font-weight: 700; | |
36 | color: #338833; | |
37 | } | |
38 | .var { | |
39 | font-weight: 700; | |
40 | color: #BB8855; | |
41 | } | |
42 | .function { | |
43 | font-weight: 700; | |
44 | color: #887744; | |
45 | } | |
46 | .object { | |
47 | font-weight: 700; | |
48 | color: #DD7744; | |
49 | } | |
50 | .malsym { | |
51 | font-weight: 600; | |
52 | color: #883333; | |
53 | } | |
54 | .string { | |
55 | font-weight: 400; | |
56 | color: #994444; | |
57 | } | |
58 | </style> | |
59 | </head> | |
60 | <body> | |
61 | <h2>Make-A-Lisp Cheatsheet</h2> | |
62 | <table align=left> | |
63 | <tr> | |
64 | <th>Step 1</th> <th>Step 6</th> | |
65 | <tr> | |
66 | <td width=50%> | |
67 | <!-- | |
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>)) | |
73 | ||
74 | ||
75 | ||
76 | ||
77 | </code></pre> | |
78 | --> | |
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>)) | |
92 | </code></pre> | |
93 | </td> | |
94 | <td width=50%> | |
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] | |
104 | ||
105 | ||
106 | ||
107 | ||
108 | </code></pre> | |
109 | </td> | |
110 | <tr> | |
111 | <th> </th> <th> </th> | |
112 | <tr> | |
113 | <th>Step 2</th> <th>Step 7</th> | |
114 | <tr> | |
115 | <td width=50%> | |
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>, ...})) | |
124 | ||
125 | ||
126 | ||
127 | </code></pre> | |
128 | </td> | |
129 | <td width=50%> | |
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 | |
141 | </code></pre> | |
142 | </td> | |
143 | <tr> | |
144 | <th> </th> <th> </th> | |
145 | <tr> | |
146 | <th>Step 3</th> <th>Step 8</th> | |
147 | <tr> | |
148 | <td width=50%> | |
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> | |
160 | </code></pre> | |
161 | </td> | |
162 | <td width=50%> | |
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>) | |
172 | ||
173 | ||
174 | </code></pre> | |
175 | </td> | |
176 | <tr> | |
177 | <th> </th> <th> </th> | |
178 | <tr> | |
179 | <th>Step 4</th> <th>Step 9</th> | |
180 | <tr> | |
181 | <td width=50%> | |
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>() | |
198 | </code></pre> | |
199 | </td> | |
200 | <td width=50%> | |
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>) | |
214 | ||
215 | ||
216 | ||
217 | </code></pre> | |
218 | </td> | |
219 | <tr> | |
220 | <th> </th> <th> </th> | |
221 | <tr> | |
222 | <th>Step 5</th> <th>Step A</th> | |
223 | <tr> | |
224 | <td width=50%> | |
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>)) | |
237 | ||
238 | </code></pre> | |
239 | </td> | |
240 | <td width=50%> | |
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 | |
a15f76bd JM |
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>) |
251 | </code></pre> | |
252 | </td> | |
253 | <tr> | |
254 | <th> </th> <th> </th> | |
255 | </table> | |
256 | </body> | |
257 | </html> |