├── .gitignore
├── interp.pdf
├── README.md
├── interp.bib
├── Makefile
├── LICENSE
├── interp.tex
└── interp.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.ss~
2 | *.ss#*
3 | .#*.ss
4 |
5 | *.scm~
6 | *.scm#*
7 | .#*.scm
8 |
--------------------------------------------------------------------------------
/interp.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webyrd/relational-interpreter-book-and-course/HEAD/interp.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # relational-interpreter-book-and-course
2 | Book and code and pointers to videos for my relational interpreter course
3 |
--------------------------------------------------------------------------------
/interp.bib:
--------------------------------------------------------------------------------
1 | @inproceedings{Byrd:2012:MLU:2661103.2661105,
2 | author = {Byrd, William E. and Holk, Eric and Friedman, Daniel P.},
3 | title = {{miniKanren}, Live and Untagged: {Quine} Generation via Relational Interpreters (Programming Pearl)},
4 | booktitle = {Proceedings of the 2012 Annual Workshop on Scheme and Functional Programming},
5 | series = {Scheme '12},
6 | year = {2012},
7 | OPTisbn = {978-1-4503-1895-2},
8 | location = {Copenhagen, Denmark},
9 | pages = {8--29},
10 | numpages = {22},
11 | OPTurl = {http://doi.acm.org/10.1145/2661103.2661105},
12 | doi = {10.1145/2661103.2661105},
13 | acmid = {2661105},
14 | publisher = {ACM},
15 | address = {New York, NY, USA},
16 | keywords = {interpreters, logic programming, miniKanren, quines, relational programming, scheme, tagging},
17 | }
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | INTERP = interp
2 | SRC = $(wildcard *.tex *.bib chapters/*.tex)
3 | FIG = $(wildcard images/*.pdf images/*.png images/*.jpg images/*.eps)
4 |
5 | all: ${INTERP}.pdf ${INTERP}.md
6 |
7 | ${INTERP}.pdf: $(SRC) $(FIGS) ${INTERP}.tex
8 | latexmk -pdflatex=xelatex -pdf -latexoption=-halt-on-error -latexoption=-interaction=nonstopmode ${INTERP}.tex
9 |
10 | ${INTERP}.md: $(SRC) $(FIGS) ${INTERP}.tex
11 | pandoc -s -o ${INTERP}.md ${INTERP}.tex
12 |
13 | clean:
14 | rm -f ${INTERP}.aux
15 | rm -f ${INTERP}.bbl
16 | rm -f ${INTERP}.bcf
17 | rm -f ${INTERP}.blg
18 | rm -f *.cpt
19 | rm -f ${INTERP}.fdb_latexmk
20 | rm -f ${INTERP}.fls
21 | rm -f ${INTERP}.idx
22 | rm -f ${INTERP}.ilg
23 | rm -f ${INTERP}.ind
24 | rm -f ${INTERP}.log
25 | rm -f ${INTERP}.mw
26 | rm -f ${INTERP}.out
27 | rm -f ${INTERP}.run.xml
28 | rm -f ${INTERP}.toc
29 | touch ${INTERP}.tex
30 |
31 | squeaky: clean
32 | rm -f ${INTERP}.pdf
33 | rm -f ${INTERP}.md
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 William E. Byrd
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/interp.tex:
--------------------------------------------------------------------------------
1 | \documentclass{book}
2 |
3 | \usepackage{alltt}
4 | \usepackage{calc}
5 | \usepackage{ccicons} % Creative Commons icons
6 | \usepackage[colorlinks,linktocpage]{hyperref}
7 | \usepackage{url}
8 |
9 | \newlength{\negspacelength}
10 | \setlength{\negspacelength}{\bigskipamount+\medskipamount}
11 |
12 | \newcommand{\negspace}{\vspace{-\negspacelength}}
13 |
14 | \def\whalfspace{\vspace*{0.335\baselineskip}}
15 | \def\wspace{\vspace*{0.67\baselineskip}}
16 | \def\nspace{\vspace*{-.7\baselineskip}}
17 | \def\nspacemargin{\vspace*{-1\baselineskip}}
18 |
19 | \begin{document}
20 |
21 | \frontmatter
22 |
23 | \date{\today}
24 |
25 | \title{Relational Interpreters in miniKanren \\ \ \\ (WORKING ROUGH DRAFT --- DRAFT 0)}
26 |
27 | \author{William E. Byrd}
28 |
29 | \maketitle
30 |
31 | {
32 | \fontsize{12}{12}
33 | \mbox{}
34 | \vfill
35 |
36 | % \hrule
37 |
38 | \noindent
39 | \textcopyright~2024 William E. Byrd
40 |
41 |
42 | \noindent
43 | \huge
44 | \ccLogo
45 | \ccAttribution
46 | \large
47 |
48 |
49 | \noindent
50 | This work is licensed under a Creative Commons Attribution 4.0 International License.
51 | (CC BY 4.0) \\
52 | \url{http://creativecommons.org/licenses/by/4.0/}
53 | }
54 |
55 | \newpage
56 |
57 | {
58 | \ \\
59 |
60 | \ \\
61 |
62 | \noindent
63 | \huge
64 | To Dan Friedman
65 | }
66 |
67 | \newpage
68 |
69 | \tableofcontents
70 |
71 | \chapter{Preface}
72 |
73 | The intent of this book is to share the techniques, knowledge, pitfalls, open problems, promising-looking future work/techniques, and literature of writing interpreters as relations in miniKanren.
74 | %
75 | Someone who reads this book actively should be ready to understand, implement, modify, and improve interpreters wtitten as miniKanren relations, read the related literature, and perform original research on the topic.
76 |
77 | \section{What this book is about}
78 |
79 | This book is about writing interpreters for programming languages, especially for subsets of Scheme.
80 | While there are many books on writing interpreters, this book is unusual in that it explores
81 | how to write interpreters as \emph{relations} in the miniKanren relational programming language.
82 | By writing interpreters as relations, and by using the implicit constraint solving and search in the \texttt{faster-miniKanren} implementation, we can use the flexibility of relational programming to allow us to experiment with programs in the language being interpreted. For example, a relational interpreter can interpret a program with missing subexpressions\footnote{Such programs are often called \emph{program sketches} [TODO cite].}, or \emph{holes}, attempting to fill in the missing subexpressions with values that result in valid programs in the language being interpreted. Or we can give both a program containing holes and the value we expect the program to produce when interpreted, and let \texttt{faster-miniKanren} try to fill in the holes in a way to produce the expected output. We can even write an interpreter that explicitly handles errors, and ask \texttt{faster-miniKanren} to find inputs to the program that trigger these errors.\footnote{This is known in the literature as ``angelic execution''.}
83 |
84 | \section{What you need to know to read this book}
85 |
86 | This book assumes you are familiar with the basics of Scheme or Racket, and are comfortable with the ideas of functionals programming. The book also assumes you understand the notions of evaluation order of expressions, lexical scope, environments, environment-passing interpreters.
87 |
88 | [TODO add topics that the reader should know, including Scheme, miniKanren, lexical scope, environment-passing interpreters, etc]
89 |
90 | [TODO add pointers to resources]
91 |
92 | \section{Running the code in this book}
93 |
94 | The code in this book was tested with Chez Scheme and Racket. It should be possible to run most code in other Scheme implementations, with few or no changes, with the exception of code that makes extensive use of Chez-specific or Racket-specific features, which I will point out in those chapters, as appropriate.
95 |
96 | \subsection{Getting \texttt{pmatch} from GitHub}
97 |
98 | \subsection{Getting \texttt{faster-miniKanren} from GitHub}
99 |
100 | \url{https://github.com/michaelballantyne/faster-miniKanren}
101 |
102 | \begin{alltt}
103 | git clone git@github.com:michaelballantyne/faster-minikanren.git
104 | \end{alltt}
105 |
106 | Alternatively, you can click on \verb|<> Code| button and select \verb|Download ZIP| to download and uncompress the \texttt{.zip} file containing the entire \texttt{faster-miniKanren} directory.
107 |
108 |
109 | \subsection{Using this book with Chez Scheme}
110 |
111 | \subsubsection{Installing Chez Scheme}
112 |
113 | \subsubsection{Starting a Chez Scheme REPL}
114 |
115 | \subsubsection{Loading a file in Chez Scheme}
116 |
117 | \subsubsection{Loading \texttt{faster-miniKanren} in Chez Scheme}
118 |
119 |
120 | \subsection{Using this book with Racket}
121 |
122 | \subsubsection{Installing Racket}
123 |
124 | \url{https://racket-lang.org/}
125 |
126 | \url{https://download.racket-lang.org/}
127 |
128 | \subsubsection{Important differences between Chez Scheme and Racket}
129 |
130 | representation of quoted values
131 |
132 | evaluation order
133 |
134 | language levels
135 |
136 | macros
137 |
138 | \subsubsection{The DrRacket IDE and the Racket REPL}
139 |
140 | \subsubsection{Starting and configuring DrRacket}
141 |
142 | changing default language
143 |
144 | changing default memory limit
145 |
146 | \subsubsection{Starting a Racket REPL}
147 |
148 | \subsubsection{Requiring a module in Racket}
149 |
150 | \subsubsection{Requiring the \texttt{faster-miniKanren} module in Racket}
151 |
152 | \section{Acknowledgements}
153 |
154 | Dan Friedman and Michael Ballantyne both encouraged me to continue working on this book, and independently encouraged me to break down one giant book into more than one book, each book being more manageable.
155 | %
156 | Both Dan and Michael encouraged me to avoid getting bogged down with a lot of introductory material, which had caused me to abandon previous writing efforts.
157 | %
158 | Michael also encouraged me to continue working on the book in the open.
159 |
160 | Darius Bacon wrote me a very helpful email about how using two separate lists to represent a lexical environment, rather than a single association list, can result in better performance and divergence behavior. I had played around with this representation in the past, but had abandoned it before I understood its advantages. Thank you, Darius.
161 |
162 | My mother has continually encouraged me to work on this book, and most importantly, to finish it!
163 |
164 | [TODO add other acknowledgements]
165 |
166 | [TODO add acks for typesetting tech, such as the fonts; also can add colophon if I'm so inclined]
167 |
168 | \mainmatter
169 |
170 | \chapter{A simple environment-passing Scheme interpreter in Scheme}% simple Scheme-in-Scheme %%%%%%%%%%
171 |
172 | call-by-value (CBV) $\lambda$-calculus (variable reference, single-argument $lambda$, and procedure application), plus \verb|quote| and \verb|list|
173 |
174 | association-list representation of the environment
175 |
176 | empty initial environment
177 |
178 | \verb|list| is implemented as if it were a special form rather than as a variable bound, in a non-empty initial environment, to a procedure. As a result, although \verb|list| can be shadowed, \verb|(list list)| results in an error that there is an attempt to reference an unbound variable \verb|list|.
179 |
180 | tagged list to represent closure
181 |
182 | grammar for the language we are interpreting
183 |
184 | \begin{alltt}
185 | (load "pmatch.scm")
186 | \end{alltt}
187 |
188 | [TODO make sure I explain MIT vs Indiana syntax for \verb|define|]
189 |
190 | \begin{alltt}
191 | (define (eval expr)
192 | (eval-expr expr '()))
193 | \end{alltt}
194 |
195 | \begin{alltt}
196 | (define (eval-expr expr env)
197 | (pmatch expr
198 | ((quote ,v)
199 | (guard (not-in-env? 'quote env))
200 | v)
201 | ((list . ,e*)
202 | (guard (not-in-env? 'list env))
203 | (eval-list e* env))
204 | (,x
205 | (guard (symbolo? x))
206 | (lookup x env))
207 | ((,rator ,rand)
208 | (let ((a (eval-expr rand env)))
209 | (pmatch (eval-expr rator env)
210 | ((closure ,x ,body ,env^)
211 | (guard (symbol? x))
212 | (eval-expr body `((,x . ,a) . ,env^))))))
213 | ((lambda (,x) ,body)
214 | (guard (and (symbol? x)
215 | (not-in-env? 'lambda env)))
216 | `(closure ,x ,body ,env))))
217 | \end{alltt}
218 |
219 | \begin{alltt}
220 | (define (not-in-env? x env)
221 | (pmatch env
222 | (((,y . ,v) . ,env^)
223 | (if (equal? y x) ;; TODO eq? vs eqv? vs equal?, with equal? being semantically closest to ==
224 | #f
225 | (not-in-env? x env^)))
226 | (() #t))) ;; TODO empty env clause comes second; Dijkstra guard, and all that
227 | \end{alltt}
228 |
229 | \begin{alltt}
230 | (define (eval-list expr env)
231 | (pmatch expr
232 | (() '())
233 | ((,a . ,d)
234 | (let ((t-a (eval-expr a env))
235 | (t-d (eval-list d env)))
236 | `(,t-a . ,t-d)))))
237 | \end{alltt}
238 |
239 | \begin{alltt}
240 | (define (lookup x env)
241 | (pmatch env
242 | (() (error 'lookup "unbound variable")) ;; TODO make sure error is introduced, and make error message nicer
243 | (((,y . ,v) . ,env^)
244 | (if (equal? y x)
245 | v
246 | (lookup x env^)))))
247 | \end{alltt}
248 |
249 | \chapter{Rewriting the simple environment-passing Scheme interpreter in miniKanren}% simple Scheme-in-miniKanren %%%%%%%%%%
250 |
251 | In this chapter we will translate the evaluator for the simple environment-passing interpreter from the previous chapter from a Scheme function to a miniKanren relation.
252 |
253 | [TODO cite the code from the Quines interp in faster-miniKanren, and point to the 2012 SW paper on Quines]
254 |
255 | [TODO this interp uses defrel---do I want to stick with defrel, or use define + lambda? Or maybe the book shows both (probably needs to show both at some point)]
256 |
257 | \begin{alltt}
258 | (load "mk-vicare.scm")
259 | (load "mk.scm")
260 | \end{alltt}
261 |
262 | \begin{alltt}
263 | (defrel (evalo expr val)
264 | (eval-expro expr '() val))
265 | \end{alltt}
266 |
267 | \begin{alltt}
268 | (defrel (eval-expro expr env val)
269 | (conde
270 | ((fresh (v)
271 | (== `(quote ,v) expr)
272 | (not-in-envo 'quote env)
273 | (absento 'closure v) ;; TODO discuss the tradeoffs of moving this absento to evalo
274 | (== v val)))
275 | ((fresh (e*)
276 | (== `(list . ,e*) expr)
277 | (not-in-envo 'list env)
278 | (absento 'closure e*) ;; TODO is this absento really needed, if we have absento for quote?
279 | (eval-listo e* env val)))
280 | ((symbolo expr) (lookupo expr env val))
281 | ((fresh (rator rand x body env^ a)
282 | (== `(,rator ,rand) expr)
283 | (eval-expro rator env `(closure ,x ,body ,env^))
284 | (eval-expro rand env a)
285 | (eval-expro body `((,x . ,a) . ,env^) val)))
286 | ((fresh (x body)
287 | (== `(lambda (,x) ,body) expr)
288 | (symbolo x)
289 | (not-in-envo 'lambda env)
290 | (== `(closure ,x ,body ,env) val)))))
291 | \end{alltt}
292 |
293 | \begin{alltt}
294 | (defrel (not-in-envo x env)
295 | (conde
296 | ((fresh (y v env^)
297 | (== `((,y . ,v) . ,env^) env)
298 | (=/= y x)
299 | (not-in-envo x env^)))
300 | ((== '() env))))
301 | \end{alltt}
302 |
303 | \begin{alltt}
304 | (defrel (eval-listo expr env val)
305 | (conde
306 | ((== '() expr)
307 | (== '() val))
308 | ((fresh (a d t-a t-d)
309 | (== `(,a . ,d) expr)
310 | (== `(,t-a . ,t-d) val)
311 | (eval-expro a env t-a)
312 | (eval-listo d env t-d)))))
313 | \end{alltt}
314 |
315 | \begin{alltt}
316 | (defrel (lookupo x env t)
317 | (fresh (y v env^)
318 | (== `((,y . ,v) . ,env^) env)
319 | (conde
320 | ((== y x) (== v t))
321 | ((=/= y x) (lookupo x env^ t)))))
322 | \end{alltt}
323 |
324 |
325 |
326 | \chapter{Quine time}% Quine time %%%%%%%%%%%%%%%%%%%%%%
327 |
328 | McCarthy challenge given in `A Micromanual for LISP'
329 |
330 | \begin{alltt}
331 | (run 1 (e) (evalo e e))
332 | \end{alltt}
333 | \verb|=>|
334 | \begin{alltt}
335 | ((((lambda (_.0) (list _.0 (list 'quote _.0)))
336 | '(lambda (_.0) (list _.0 (list 'quote _.0))))
337 | (=/= ((_.0 closure)) ((_.0 list)) ((_.0 quote)))
338 | (sym _.0)))
339 | \end{alltt}
340 |
341 | \begin{alltt}
342 | > ((lambda (_.0) (list _.0 (list 'quote _.0)))
343 | '(lambda (_.0) (list _.0 (list 'quote _.0))))
344 | ((lambda (_.0) (list _.0 (list 'quote _.0)))
345 | '(lambda (_.0) (list _.0 (list 'quote _.0))))
346 | \end{alltt}
347 |
348 | We replace \verb|_.0| with the arbitrary free variable name \verb|x| to produce the canonical LISP/Scheme Quine:
349 |
350 | \begin{alltt}
351 | ((lambda (x) (list x (list 'quote x)))
352 | '(lambda (x) (list x (list 'quote x))))
353 | \end{alltt}
354 |
355 | \begin{alltt}
356 | > ((lambda (x) (list x (list 'quote x)))
357 | '(lambda (x) (list x (list 'quote x))))
358 | ((lambda (x) (list x (list 'quote x)))
359 | '(lambda (x) (list x (list 'quote x))))
360 | \end{alltt}
361 |
362 | Twines
363 |
364 | every Quine is trivially a Twine; we can add a disequality constraint to ensure \verb|p| and \verb|q| are distinct terms
365 |
366 | \begin{alltt}
367 | > (run 1 (p q)
368 | (=/= p q)
369 | (evalo p q)
370 | (evalo q p))
371 | [TODO add the answer]
372 | \end{alltt}
373 |
374 | \footnote{I thank Larry Moss and the Indiana University Logic Symposium [TODO check the name of the symposium] for inviting me to give a talk where I demonstrated Quine generation, and where Larry suggested I tried generating Twines.}
375 |
376 | Thrines
377 |
378 | \begin{alltt}
379 | > (run 1 (p q r)
380 | (=/= p q)
381 | (=/= p r)
382 | (=/= q r)
383 | (evalo p q)
384 | (evalo q r)
385 | (evalo r p))
386 | [TODO add the answer]
387 | \end{alltt}
388 |
389 |
390 | Structurally boring Quines, Twines, and Thrines
391 |
392 | just moving quotes around
393 |
394 | \verb|absento| trick to generate more interesting Quines, Twines, and Thrines
395 |
396 | \begin{alltt}
397 | > (run 1 (p q)
398 | (absento p q)
399 | (absento q p)
400 | (evalo p q)
401 | (evalo q p))
402 | [TODO add the answer]
403 | \end{alltt}
404 |
405 | [similarly for Thrines]
406 |
407 | Revisiting our original Quine query with the \verb|absento| trick
408 |
409 | \begin{alltt}
410 | (run 1 (p)
411 | (fresh (expr1 expr2)
412 | (absento expr1 expr2)
413 | (== `(,expr1 . ,expr2) p)
414 | (evalo p p)))
415 | \end{alltt}
416 | \verb|=>|
417 | \begin{alltt}
418 | ((((lambda (_.0)
419 | (list (list 'lambda '(_.0) _.0) (list 'quote _.0)))
420 | '(list (list 'lambda '(_.0) _.0) (list 'quote _.0)))
421 | (=/= ((_.0 closure)) ((_.0 list)) ((_.0 quote)))
422 | (sym _.0)))
423 | \end{alltt}
424 |
425 |
426 | Gary P. Thompson II's Quine page (\url{http://www.nyx.net/~gthompso/quine.htm}) also describes \emph{Quine Generating Programs} (\url{http://www.nyx.net/~gthompso/self_gener.txt}):
427 |
428 | \begin{quote}
429 | It is possible (and actually in some cases easier) to write a program which outputs another program which is itself a quine.
430 | \end{quote}
431 |
432 | using \verb|q.scm| from faster-miniKanren:
433 |
434 | \begin{alltt}
435 | (run 1 (nq q)
436 | (=/= q nq)
437 | (evalo nq q)
438 | (evalo q q))
439 | =>
440 | ((('((lambda (_.0) (list _.0 (list 'quote _.0)))
441 | '(lambda (_.0) (list _.0 (list 'quote _.0))))
442 | ((lambda (_.0) (list _.0 (list 'quote _.0)))
443 | '(lambda (_.0) (list _.0 (list 'quote _.0)))))
444 | (=/= ((_.0 closure)) ((_.0 list)) ((_.0 quote)))
445 | (sym _.0)))
446 | \end{alltt}
447 |
448 | \begin{alltt}
449 | (run 1 (nq q)
450 | (absento q nq)
451 | (evalo nq q)
452 | (evalo q q))
453 | =>
454 | ((((list
455 | '(lambda (_.0) (list _.0 (list 'quote _.0)))
456 | ''(lambda (_.0) (list _.0 (list 'quote _.0))))
457 | ((lambda (_.0) (list _.0 (list 'quote _.0)))
458 | '(lambda (_.0) (list _.0 (list 'quote _.0)))))
459 | (=/= ((_.0 closure)) ((_.0 list)) ((_.0 quote)))
460 | (sym _.0)))
461 | \end{alltt}
462 |
463 |
464 | [TODO: challenge to myself: generate a Kimian self-rep (\url{http://www.nyx.net/~gthompso/self_kim.txt})
465 |
466 | \begin{quote}
467 | Kimian self-rep, like quines, got it's name from Godel Escher Bach. A
468 | Kimian 'program' is actually the error produced by the system when it
469 | encounters the code. Kimian self reps are therefore very system-specific,
470 | and even implementation specific.
471 | \end{quote}
472 |
473 | I want to add errors to the interp, any way. Once I've added errors, I should in theory be able to synthesize Kimian self-reps. Try it! And then move this description and code to the chapter that adds errors to the interp.
474 |
475 | Update: I've been able to generate Kimian self-rep, as can be seen in \verb|daily-mK/2025_01_21|:
476 |
477 | \begin{alltt}
478 | > (load "q-error.scm")
479 | > (run 1 (e) (evalo e e ))
480 | ((error (unbound-variable error)))
481 | \end{alltt}
482 |
483 | Need to clean up the interpreter code, which effectively uses the Maybe monad. I also need to check that the standard Quine still works with the updated interpreter, and try reorderings of the conjuncts, etc., to both avoid duplicate errors and to make the interp efficient enough to generate our standard Quine.
484 | ]
485 |
486 |
487 | [TODO: play with the ideas in this other Quines page \url{http://www.madore.org/~david/computers/quine.html} (thanks to Nada Amin for the pointer to this page, which I had forgotten about)]
488 |
489 |
490 | \chapter{Using a two-list representation of the environment}% split environment representation
491 |
492 | association-list representation of an environment where \verb|x| is mapped to the list \verb|(cat dog)| and \verb|y| is mapped to \verb|5|:
493 | \begin{alltt}
494 | ((x . (cat dog))
495 | (y . 5))
496 | \end{alltt}
497 |
498 | ``split'' two-list representation of the same environment:
499 | \begin{alltt}
500 | (x y) ; variables
501 |
502 | ((cat dog) 6) ; values
503 | \end{alltt}
504 |
505 | ;; a-list env
506 | ;; ((x . (cat dog))
507 | ;; (y . 5))
508 |
509 | ;; split env
510 | ;; (x y)
511 | ;; ((cat dog) 6)
512 |
513 | \verb|absento| trick for lazy \verb|not-in-envo|
514 |
515 | ;; (absento 'closure expr)
516 |
517 | ;; (absento t1 t2)
518 |
519 | ;; (not-in-envo 'lambda env)
520 | ;; (absento 'lambda '(x y))
521 |
522 | \begin{alltt}
523 | (defrel (evalo expr val)
524 | (eval-expro expr '(() . ()) val))
525 | \end{alltt}
526 |
527 | \begin{alltt}
528 | (defrel (eval-expro expr env val)
529 | (conde
530 | ;; quote, list, and variable reference/lookup clauses elided
531 | ((fresh (rator rand body env^ a x x* v*)
532 | (== `(,rator ,rand) expr)
533 | (== `(,x* . ,v*) env^)
534 | (eval-expro rator env `(closure ,x ,body ,env^))
535 | (eval-expro rand env a)
536 | (eval-expro body
537 | `((,x . x*) . (,a . v*))
538 | val)))
539 | ;; lambda clause elided
540 | ))
541 | \end{alltt}
542 |
543 | \begin{alltt}
544 | (defrel (not-in-envo x env)
545 | (fresh (x* v*)
546 | (== `(,x* . ,v*) env)
547 | (absento x x*)))
548 | \end{alltt}
549 |
550 | [TODO discuss tradeoffs between asserting (symbolo x) in these helper relations---how stand-alone do we want them?]
551 |
552 | \begin{alltt}
553 | (defrel (lookupo x env t)
554 | (fresh (y x* v v*)
555 | (== `((,y . ,x*) . (,v . ,v*)) env)
556 | (conde
557 | ((== y x) (== v t))
558 | ((=/= y x) (lookupo x `(,x* . ,v*) t)))))
559 | \end{alltt}
560 |
561 |
562 |
563 | \chapter{Extending the interpreter to handle \texttt{append}}% extended append interpreter
564 |
565 | add \verb|cons|, \verb|car|, \verb|cdr|, \verb|null?|, and \verb|if|
566 |
567 | extend \verb|lambda| and application to handle multiple arguments and variadic
568 |
569 |
570 | \chapter{Using a non-empty initial environment}% non-empty initial env
571 |
572 | So far our \verb|evalo| driver relation has used an empty initial environment. The \verb|eval-expro| relations treats application of \verb|cons| explicitly, as if it were a special form; as a result, while it is possible to shadow \verb|cons|:
573 |
574 | [TODO actually, given that cons is the only built-in function, and we don't support multi-arg or variadic application, I'm not sure I can really show off shadoing:]
575 |
576 | \begin{alltt}
577 | ((lambda (cons) (cons 'cat 'dog)) (lambda (x))
578 | \end{alltt}
579 |
580 | \noindent
581 | it is not possible to treat the built-in \verb|cons| as a first-class procedure value:
582 |
583 | \begin{alltt}
584 | (cons cons cons)
585 | =>
586 | [TODO what is the behavior? unbound variable cons as an error?]
587 | \end{alltt}
588 |
589 | \begin{alltt}
590 | ((lambda (x) x) cons)
591 | =>
592 | [TODO what is the behavior? unbound variable cons as an error?]
593 | \end{alltt}
594 |
595 |
596 | new case to handle prim app rather than user-defined closure app
597 |
598 | use either \verb|cons| or \verb|list|; have to implement \verb|eval-listo|, anyway, for application of primitives and varidic application---probably best to implement both \verb|list| and \verb|cons|
599 |
600 | \verb|eval-listo| to evaluate the arguments of the \verb|rand|
601 |
602 | move code to handle those primitive cases to \verb|eval-primo|, without the \verb|not-in-envo| calls
603 |
604 | \verb|cons|, \verb|car|, \verb|cdr|, and \verb|null?| bound in the initial env to prims
605 |
606 | \verb|list| bound in the initial env to the closure that results from evaluating the variadic \verb|(lambda x x)|
607 |
608 |
609 | Experimental: try adding quote and lambda to the intial env as well, as in my experiments starting with \verb|daily-mK/2025_01_22|
610 |
611 |
612 | \chapter{Adding explicit errors}% explicit errors
613 |
614 | So far our interpreters handle Scheme errors implicitly by failing to produce a result, rather than producing an explicit error. This implicit representation of errors has advantages, in both keeping the implementation code simple and in performance/fail-fast behavior.
615 |
616 | [TODO see the code and comments in \verb|daily-mK/2025_01_19| --- this code needs to be updated to use non-empty initial environment, to avoid unbound variable errors for built-ins, such as \verb|(error (unbound variable lambda))|]
617 |
618 | [TODO discuss disadvantage of threading through values monadically instead of lexically, esp. regarding losing fail-fast behavior, breaking the wires, and losing flexibility in reordering conjuncts]
619 |
620 | [TODO hmm in my experiments, if I have an explicit error for unbound variables, I seem to need to ``guard'' the application (and prim app, if I have non-empty initial environments) by ensuring that the rator is either not any of the keywords (quote, lambda, etc.), or that the rator is a keyword, and lookup produces a value rather an error. See \verb|daily-mK/2025_01_21|. Hmm, can I just use this guarding instead of having to go to a non-empty initial env, if all I want is an explicit error for unbound variable lookup?]
621 |
622 | \chapter{Angelic execution}% angelic execution
623 |
624 | [TODO look at my code from PolyConf 2015, which includes an interpreter for an imperative language, along with angelic execution; cite PL course slides for example]
625 |
626 |
627 | \chapter{Adding mutation}% mutation
628 |
629 | [TODO look at my code from PolyConf 2015, which includes an interpreter for an imperative language, along with angelic execution]
630 |
631 | support \verb|set!| (can we get away with supporting \verb|set!| without adding a store?)
632 |
633 | support mutiple pairs and have an explicit store
634 |
635 |
636 | \chapter{Adding delimited control operators}%
637 |
638 | delimited continuations and/or effect handlers---can we do so in such a way that avoids ``breaking the wires''?
639 |
640 | talk about the problem with \verb|call/cc| and breaking the wires
641 |
642 |
643 |
644 | \chapter{Writing a parser as a relation}% relational parser
645 |
646 | [TODO I'm not saying this right. For a program skeleton plus N input/output examples, N+1 instances of Chez Scheme are launced as separate processes: one per example, which, if it fails fast, will result in the overall synthesis task being stopped. The other processes the sketch plus all the input/output examples, all in a conjunction. All N+1 processes run the parser before trying to run evalo, as a separate run expression, in an attempt to generate a cleaner error messages if the user makes a syntactic mistake, while stopping the entire set of N+1 computations if the individual discrete tests faol]
647 |
648 | Barliman uses a `run` query to try to parse the user's code; if the parse query fails, the entire synthesis task is halted, with an error message.
649 |
650 | [TODO get the details straight, including the OS processes that are launched for each test and for the main synthesis tasks; also, the GUI behavior]
651 |
652 |
653 | \chapter{Writing a type inferencer as a relation}% relational type inferencer
654 |
655 |
656 | \chapter{Build your own Barliman}% build your own Barliman
657 |
658 |
659 | \chapter{Speeding up the interpreter}% speeding up the interpreter
660 |
661 | [restrict to interpreter changes that don't require hacking faster-miniKanren or in-depth knowledge of the implementation]
662 |
663 | dynamic reordering of conjuncts, especially for application
664 |
665 | fast environment lookup for environments that are sufficiently ground
666 |
667 |
668 | \chapter{Open problems}% open problems
669 |
670 |
671 | \appendix
672 |
673 |
674 | \end{document}
675 |
--------------------------------------------------------------------------------
/interp.md:
--------------------------------------------------------------------------------
1 | ---
2 | author:
3 | - William E. Byrd
4 | date: 2025-01-24
5 | title: |
6 | Relational Interpreters in miniKanren\
7 | \
8 | (WORKING ROUGH DRAFT --- DRAFT 0)
9 | ---
10 |
11 | 2024 William E. Byrd
12 |
13 | This work is licensed under a Creative Commons Attribution 4.0
14 | International License. (CC BY 4.0)\
15 |
16 |
17 | \
18 | \
19 | To Dan Friedman
20 |
21 | # Preface
22 |
23 | The intent of this book is to share the techniques, knowledge, pitfalls,
24 | open problems, promising-looking future work/techniques, and literature
25 | of writing interpreters as relations in miniKanren. Someone who reads
26 | this book actively should be ready to understand, implement, modify, and
27 | improve interpreters wtitten as miniKanren relations, read the related
28 | literature, and perform original research on the topic.
29 |
30 | ## What this book is about
31 |
32 | This book is about writing interpreters for programming languages,
33 | especially for subsets of Scheme. While there are many books on writing
34 | interpreters, this book is unusual in that it explores how to write
35 | interpreters as *relations* in the miniKanren relational programming
36 | language. By writing interpreters as relations, and by using the
37 | implicit constraint solving and search in the `faster-miniKanren`
38 | implementation, we can use the flexibility of relational programming to
39 | allow us to experiment with programs in the language being interpreted.
40 | For example, a relational interpreter can interpret a program with
41 | missing subexpressions[^1], or *holes*, attempting to fill in the
42 | missing subexpressions with values that result in valid programs in the
43 | language being interpreted. Or we can give both a program containing
44 | holes and the value we expect the program to produce when interpreted,
45 | and let `faster-miniKanren` try to fill in the holes in a way to produce
46 | the expected output. We can even write an interpreter that explicitly
47 | handles errors, and ask `faster-miniKanren` to find inputs to the
48 | program that trigger these errors.[^2]
49 |
50 | ## What you need to know to read this book
51 |
52 | This book assumes you are familiar with the basics of Scheme or Racket,
53 | and are comfortable with the ideas of functionals programming. The book
54 | also assumes you understand the notions of evaluation order of
55 | expressions, lexical scope, environments, environment-passing
56 | interpreters.
57 |
58 | \[TODO add topics that the reader should know, including Scheme,
59 | miniKanren, lexical scope, environment-passing interpreters, etc\]
60 |
61 | \[TODO add pointers to resources\]
62 |
63 | ## Running the code in this book
64 |
65 | The code in this book was tested with Chez Scheme and Racket. It should
66 | be possible to run most code in other Scheme implementations, with few
67 | or no changes, with the exception of code that makes extensive use of
68 | Chez-specific or Racket-specific features, which I will point out in
69 | those chapters, as appropriate.
70 |
71 | ### Getting `pmatch` from GitHub
72 |
73 | ### Getting `faster-miniKanren` from GitHub
74 |
75 |
76 |
77 | `git``\ `{=latex}`clone``\ `{=latex}`git@github.com:michaelballantyne/faster-minikanren.git`
78 |
79 | Alternatively, you can click on `<> Code` button and select
80 | `Download ZIP` to download and uncompress the `.zip` file containing the
81 | entire `faster-miniKanren` directory.
82 |
83 | ### Using this book with Chez Scheme
84 |
85 | #### Installing Chez Scheme
86 |
87 | #### Starting a Chez Scheme REPL
88 |
89 | #### Loading a file in Chez Scheme
90 |
91 | #### Loading `faster-miniKanren` in Chez Scheme
92 |
93 | ### Using this book with Racket
94 |
95 | #### Installing Racket
96 |
97 |
98 |
99 |
100 |
101 | #### Important differences between Chez Scheme and Racket
102 |
103 | representation of quoted values
104 |
105 | evaluation order
106 |
107 | language levels
108 |
109 | macros
110 |
111 | #### The DrRacket IDE and the Racket REPL
112 |
113 | #### Starting and configuring DrRacket
114 |
115 | changing default language
116 |
117 | changing default memory limit
118 |
119 | #### Starting a Racket REPL
120 |
121 | #### Requiring a module in Racket
122 |
123 | #### Requiring the `faster-miniKanren` module in Racket
124 |
125 | ## Acknowledgements
126 |
127 | Dan Friedman and Michael Ballantyne both encouraged me to continue
128 | working on this book, and independently encouraged me to break down one
129 | giant book into more than one book, each book being more manageable.
130 | Both Dan and Michael encouraged me to avoid getting bogged down with a
131 | lot of introductory material, which had caused me to abandon previous
132 | writing efforts. Michael also encouraged me to continue working on the
133 | book in the open.
134 |
135 | Darius Bacon wrote me a very helpful email about how using two separate
136 | lists to represent a lexical environment, rather than a single
137 | association list, can result in better performance and divergence
138 | behavior. I had played around with this representation in the past, but
139 | had abandoned it before I understood its advantages. Thank you, Darius.
140 |
141 | My mother has continually encouraged me to work on this book, and most
142 | importantly, to finish it!
143 |
144 | \[TODO add other acknowledgements\]
145 |
146 | \[TODO add acks for typesetting tech, such as the fonts; also can add
147 | colophon if I'm so inclined\]
148 |
149 | # A simple environment-passing Scheme interpreter in Scheme
150 |
151 | call-by-value (CBV) $\lambda$-calculus (variable reference,
152 | single-argument $lambda$, and procedure application), plus `quote` and
153 | `list`
154 |
155 | association-list representation of the environment
156 |
157 | empty initial environment
158 |
159 | `list` is implemented as if it were a special form rather than as a
160 | variable bound, in a non-empty initial environment, to a procedure. As a
161 | result, although `list` can be shadowed, `(list list)` results in an
162 | error that there is an attempt to reference an unbound variable `list`.
163 |
164 | tagged list to represent closure
165 |
166 | grammar for the language we are interpreting
167 |
168 | `(load``\ `{=latex}`"pmatch.scm")`
169 |
170 | \[TODO make sure I explain MIT vs Indiana syntax for `define`\]
171 |
172 | `(define``\ `{=latex}`(eval``\ `{=latex}`expr)`\
173 | `(eval-expr``\ `{=latex}`expr``\ `{=latex}`’()))`
174 |
175 | `(define``\ `{=latex}`(eval-expr``\ `{=latex}`expr``\ `{=latex}`env)`\
176 | `(pmatch``\ `{=latex}`expr`\
177 | `((quote``\ `{=latex}`,v)`\
178 | `(guard``\ `{=latex}`(not-in-env?``\ `{=latex}`’quote``\ `{=latex}`env))`\
179 | `v)`\
180 | `((list``\ `{=latex}`.``\ `{=latex}`,e*)`\
181 | `(guard``\ `{=latex}`(not-in-env?``\ `{=latex}`’list``\ `{=latex}`env))`\
182 | `(eval-list``\ `{=latex}`e*``\ `{=latex}`env))`\
183 | `(,x`\
184 | `(guard``\ `{=latex}`(symbolo?``\ `{=latex}`x))`\
185 | `(lookup``\ `{=latex}`x``\ `{=latex}`env))`\
186 | `((,rator``\ `{=latex}`,rand)`\
187 | `(let``\ `{=latex}`((a``\ `{=latex}`(eval-expr``\ `{=latex}`rand``\ `{=latex}`env)))`\
188 | `(pmatch``\ `{=latex}`(eval-expr``\ `{=latex}`rator``\ `{=latex}`env)`\
189 | `((closure``\ `{=latex}`,x``\ `{=latex}`,body``\ `{=latex}`,env^)`\
190 | `(guard``\ `{=latex}`(symbol?``\ `{=latex}`x))`\
191 | `(eval-expr``\ `{=latex}`body``\ `{=latex}`‘((,x``\ `{=latex}`.``\ `{=latex}`,a)``\ `{=latex}`.``\ `{=latex}`,env^))))))`\
192 | `((lambda``\ `{=latex}`(,x)``\ `{=latex}`,body)`\
193 | `(guard``\ `{=latex}`(and``\ `{=latex}`(symbol?``\ `{=latex}`x)`\
194 | `(not-in-env?``\ `{=latex}`’lambda``\ `{=latex}`env)))`\
195 | `‘(closure``\ `{=latex}`,x``\ `{=latex}`,body``\ `{=latex}`,env))))`
196 |
197 | `(define``\ `{=latex}`(not-in-env?``\ `{=latex}`x``\ `{=latex}`env)`\
198 | `(pmatch``\ `{=latex}`env`\
199 | `(((,y``\ `{=latex}`.``\ `{=latex}`,v)``\ `{=latex}`.``\ `{=latex}`,env^)`\
200 | `(if``\ `{=latex}`(equal?``\ `{=latex}`y``\ `{=latex}`x)``\ `{=latex}`;;``\ `{=latex}`TODO``\ `{=latex}`eq?``\ `{=latex}`vs``\ `{=latex}`eqv?``\ `{=latex}`vs``\ `{=latex}`equal?,``\ `{=latex}`with``\ `{=latex}`equal?``\ `{=latex}`being``\ `{=latex}`semantically``\ `{=latex}`closest``\ `{=latex}`to``\ `{=latex}`==`\
201 | `#f`\
202 | `(not-in-env?``\ `{=latex}`x``\ `{=latex}`env^)))`\
203 | `(()``\ `{=latex}`#t)))``\ `{=latex}`;;``\ `{=latex}`TODO``\ `{=latex}`empty``\ `{=latex}`env``\ `{=latex}`clause``\ `{=latex}`comes``\ `{=latex}`second;``\ `{=latex}`Dijkstra``\ `{=latex}`guard,``\ `{=latex}`and``\ `{=latex}`all``\ `{=latex}`that`
204 |
205 | `(define``\ `{=latex}`(eval-list``\ `{=latex}`expr``\ `{=latex}`env)`\
206 | `(pmatch``\ `{=latex}`expr`\
207 | `(()``\ `{=latex}`’())`\
208 | `((,a``\ `{=latex}`.``\ `{=latex}`,d)`\
209 | `(let``\ `{=latex}`((t-a``\ `{=latex}`(eval-expr``\ `{=latex}`a``\ `{=latex}`env))`\
210 | `(t-d``\ `{=latex}`(eval-list``\ `{=latex}`d``\ `{=latex}`env)))`\
211 | `‘(,t-a``\ `{=latex}`.``\ `{=latex}`,t-d)))))`
212 |
213 | `(define``\ `{=latex}`(lookup``\ `{=latex}`x``\ `{=latex}`env)`\
214 | `(pmatch``\ `{=latex}`env`\
215 | `(()``\ `{=latex}`(error``\ `{=latex}`’lookup``\ `{=latex}`"unbound``\ `{=latex}`variable"))``\ `{=latex}`;;``\ `{=latex}`TODO``\ `{=latex}`make``\ `{=latex}`sure``\ `{=latex}`error``\ `{=latex}`is``\ `{=latex}`introduced,``\ `{=latex}`and``\ `{=latex}`make``\ `{=latex}`error``\ `{=latex}`message``\ `{=latex}`nicer`\
216 | `(((,y``\ `{=latex}`.``\ `{=latex}`,v)``\ `{=latex}`.``\ `{=latex}`,env^)`\
217 | `(if``\ `{=latex}`(equal?``\ `{=latex}`y``\ `{=latex}`x)`\
218 | `v`\
219 | `(lookup``\ `{=latex}`x``\ `{=latex}`env^)))))`
220 |
221 | # Rewriting the simple environment-passing Scheme interpreter in miniKanren
222 |
223 | In this chapter we will translate the evaluator for the simple
224 | environment-passing interpreter from the previous chapter from a Scheme
225 | function to a miniKanren relation.
226 |
227 | \[TODO cite the code from the Quines interp in faster-miniKanren, and
228 | point to the 2012 SW paper on Quines\]
229 |
230 | \[TODO this interp uses defrel---do I want to stick with defrel, or use
231 | define + lambda? Or maybe the book shows both (probably needs to show
232 | both at some point)\]
233 |
234 | `(load``\ `{=latex}`"mk-vicare.scm")`\
235 | `(load``\ `{=latex}`"mk.scm")`
236 |
237 | `(defrel``\ `{=latex}`(evalo``\ `{=latex}`expr``\ `{=latex}`val)`\
238 | `(eval-expro``\ `{=latex}`expr``\ `{=latex}`’()``\ `{=latex}`val))`
239 |
240 | `(defrel``\ `{=latex}`(eval-expro``\ `{=latex}`expr``\ `{=latex}`env``\ `{=latex}`val)`\
241 | `(conde`\
242 | `((fresh``\ `{=latex}`(v)`\
243 | `(==``\ `{=latex}`‘(quote``\ `{=latex}`,v)``\ `{=latex}`expr)`\
244 | `(not-in-envo``\ `{=latex}`’quote``\ `{=latex}`env)`\
245 | `(absento``\ `{=latex}`’closure``\ `{=latex}`v)``\ `{=latex}`;;``\ `{=latex}`TODO``\ `{=latex}`discuss``\ `{=latex}`the``\ `{=latex}`tradeoffs``\ `{=latex}`of``\ `{=latex}`moving``\ `{=latex}`this``\ `{=latex}`absento``\ `{=latex}`to``\ `{=latex}`evalo`\
246 | `(==``\ `{=latex}`v``\ `{=latex}`val)))`\
247 | `((fresh``\ `{=latex}`(e*)`\
248 | `(==``\ `{=latex}`‘(list``\ `{=latex}`.``\ `{=latex}`,e*)``\ `{=latex}`expr)`\
249 | `(not-in-envo``\ `{=latex}`’list``\ `{=latex}`env)`\
250 | `(absento``\ `{=latex}`’closure``\ `{=latex}`e*)``\ `{=latex}`;;``\ `{=latex}`TODO``\ `{=latex}`is``\ `{=latex}`this``\ `{=latex}`absento``\ `{=latex}`really``\ `{=latex}`needed,``\ `{=latex}`if``\ `{=latex}`we``\ `{=latex}`have``\ `{=latex}`absento``\ `{=latex}`for``\ `{=latex}`quote?`\
251 | `(eval-listo``\ `{=latex}`e*``\ `{=latex}`env``\ `{=latex}`val)))`\
252 | `((symbolo``\ `{=latex}`expr)``\ `{=latex}`(lookupo``\ `{=latex}`expr``\ `{=latex}`env``\ `{=latex}`val))`\
253 | `((fresh``\ `{=latex}`(rator``\ `{=latex}`rand``\ `{=latex}`x``\ `{=latex}`body``\ `{=latex}`env^``\ `{=latex}`a)`\
254 | `(==``\ `{=latex}`‘(,rator``\ `{=latex}`,rand)``\ `{=latex}`expr)`\
255 | `(eval-expro``\ `{=latex}`rator``\ `{=latex}`env``\ `{=latex}`‘(closure``\ `{=latex}`,x``\ `{=latex}`,body``\ `{=latex}`,env^))`\
256 | `(eval-expro``\ `{=latex}`rand``\ `{=latex}`env``\ `{=latex}`a)`\
257 | `(eval-expro``\ `{=latex}`body``\ `{=latex}`‘((,x``\ `{=latex}`.``\ `{=latex}`,a)``\ `{=latex}`.``\ `{=latex}`,env^)``\ `{=latex}`val)))`\
258 | `((fresh``\ `{=latex}`(x``\ `{=latex}`body)`\
259 | `(==``\ `{=latex}`‘(lambda``\ `{=latex}`(,x)``\ `{=latex}`,body)``\ `{=latex}`expr)`\
260 | `(symbolo``\ `{=latex}`x)`\
261 | `(not-in-envo``\ `{=latex}`’lambda``\ `{=latex}`env)`\
262 | `(==``\ `{=latex}`‘(closure``\ `{=latex}`,x``\ `{=latex}`,body``\ `{=latex}`,env)``\ `{=latex}`val)))))`
263 |
264 | `(defrel``\ `{=latex}`(not-in-envo``\ `{=latex}`x``\ `{=latex}`env)`\
265 | `(conde`\
266 | `((fresh``\ `{=latex}`(y``\ `{=latex}`v``\ `{=latex}`env^)`\
267 | `(==``\ `{=latex}'`((,y``\ `{=latex}`.``\ `{=latex}`,v)``\ `{=latex}`.``\ `{=latex}`,env^)``\ `{=latex}`env)`\
268 | `(=/=``\ `{=latex}`y``\ `{=latex}`x)`\
269 | `(not-in-envo``\ `{=latex}`x``\ `{=latex}`env^)))`\
270 | `((==``\ `{=latex}'`()``\ `{=latex}`env))))`
271 |
272 | `(defrel``\ `{=latex}`(eval-listo``\ `{=latex}`expr``\ `{=latex}`env``\ `{=latex}`val)`\
273 | `(conde`\
274 | `((==``\ `{=latex}`’()``\ `{=latex}`expr)`\
275 | `(==``\ `{=latex}`’()``\ `{=latex}`val))`\
276 | `((fresh``\ `{=latex}`(a``\ `{=latex}`d``\ `{=latex}`t-a``\ `{=latex}`t-d)`\
277 | `(==``\ `{=latex}`‘(,a``\ `{=latex}`.``\ `{=latex}`,d)``\ `{=latex}`expr)`\
278 | `(==``\ `{=latex}`‘(,t-a``\ `{=latex}`.``\ `{=latex}`,t-d)``\ `{=latex}`val)`\
279 | `(eval-expro``\ `{=latex}`a``\ `{=latex}`env``\ `{=latex}`t-a)`\
280 | `(eval-listo``\ `{=latex}`d``\ `{=latex}`env``\ `{=latex}`t-d)))))`
281 |
282 | `(defrel``\ `{=latex}`(lookupo``\ `{=latex}`x``\ `{=latex}`env``\ `{=latex}`t)`\
283 | `(fresh``\ `{=latex}`(y``\ `{=latex}`v``\ `{=latex}`env^)`\
284 | `(==``\ `{=latex}`‘((,y``\ `{=latex}`.``\ `{=latex}`,v)``\ `{=latex}`.``\ `{=latex}`,env^)``\ `{=latex}`env)`\
285 | `(conde`\
286 | `((==``\ `{=latex}`y``\ `{=latex}`x)``\ `{=latex}`(==``\ `{=latex}`v``\ `{=latex}`t))`\
287 | `((=/=``\ `{=latex}`y``\ `{=latex}`x)``\ `{=latex}`(lookupo``\ `{=latex}`x``\ `{=latex}`env^``\ `{=latex}`t)))))`
288 |
289 | # Quine time
290 |
291 | McCarthy challenge given in 'A Micromanual for LISP'
292 |
293 | `(run``\ `{=latex}`1``\ `{=latex}`(e)``\ `{=latex}`(evalo``\ `{=latex}`e``\ `{=latex}`e))`
294 |
295 | `=>`
296 |
297 | `((((lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
298 | `’(lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0))))`\
299 | `(=/=``\ `{=latex}`((_.0``\ `{=latex}`closure))``\ `{=latex}`((_.0``\ `{=latex}`list))``\ `{=latex}`((_.0``\ `{=latex}`quote)))`\
300 | `(sym``\ `{=latex}`_.0)))`
301 |
302 | `>``\ `{=latex}`((lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
303 | `’(lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0))))`\
304 | `((lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
305 | `’(lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0))))`
306 |
307 | We replace `_.0` with the arbitrary free variable name `x` to produce
308 | the canonical LISP/Scheme Quine:
309 |
310 | `((lambda``\ `{=latex}`(x)``\ `{=latex}`(list``\ `{=latex}`x``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`x)))`\
311 | `’(lambda``\ `{=latex}`(x)``\ `{=latex}`(list``\ `{=latex}`x``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`x))))`
312 |
313 | `>``\ `{=latex}`((lambda``\ `{=latex}`(x)``\ `{=latex}`(list``\ `{=latex}`x``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`x)))`\
314 | `’(lambda``\ `{=latex}`(x)``\ `{=latex}`(list``\ `{=latex}`x``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`x))))`\
315 | `((lambda``\ `{=latex}`(x)``\ `{=latex}`(list``\ `{=latex}`x``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`x)))`\
316 | `’(lambda``\ `{=latex}`(x)``\ `{=latex}`(list``\ `{=latex}`x``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`x))))`
317 |
318 | Twines
319 |
320 | every Quine is trivially a Twine; we can add a disequality constraint to
321 | ensure `p` and `q` are distinct terms
322 |
323 | `>``\ `{=latex}`(run``\ `{=latex}`1``\ `{=latex}`(p``\ `{=latex}`q)`\
324 | `(=/=``\ `{=latex}`p``\ `{=latex}`q)`\
325 | `(evalo``\ `{=latex}`p``\ `{=latex}`q)`\
326 | `(evalo``\ `{=latex}`q``\ `{=latex}`p))`\
327 | `[TODO``\ `{=latex}`add``\ `{=latex}`the``\ `{=latex}`answer]`
328 |
329 | [^3]
330 |
331 | Thrines
332 |
333 | `>``\ `{=latex}`(run``\ `{=latex}`1``\ `{=latex}`(p``\ `{=latex}`q``\ `{=latex}`r)`\
334 | `(=/=``\ `{=latex}`p``\ `{=latex}`q)`\
335 | `(=/=``\ `{=latex}`p``\ `{=latex}`r)`\
336 | `(=/=``\ `{=latex}`q``\ `{=latex}`r)`\
337 | `(evalo``\ `{=latex}`p``\ `{=latex}`q)`\
338 | `(evalo``\ `{=latex}`q``\ `{=latex}`r)`\
339 | `(evalo``\ `{=latex}`r``\ `{=latex}`p))`\
340 | `[TODO``\ `{=latex}`add``\ `{=latex}`the``\ `{=latex}`answer]`
341 |
342 | Structurally boring Quines, Twines, and Thrines
343 |
344 | just moving quotes around
345 |
346 | `absento` trick to generate more interesting Quines, Twines, and Thrines
347 |
348 | `>``\ `{=latex}`(run``\ `{=latex}`1``\ `{=latex}`(p``\ `{=latex}`q)`\
349 | `(absento``\ `{=latex}`p``\ `{=latex}`q)`\
350 | `(absento``\ `{=latex}`q``\ `{=latex}`p)`\
351 | `(evalo``\ `{=latex}`p``\ `{=latex}`q)`\
352 | `(evalo``\ `{=latex}`q``\ `{=latex}`p))`\
353 | `[TODO``\ `{=latex}`add``\ `{=latex}`the``\ `{=latex}`answer]`
354 |
355 | \[similarly for Thrines\]
356 |
357 | Revisiting our original Quine query with the `absento` trick
358 |
359 | `(run``\ `{=latex}`1``\ `{=latex}`(p)`\
360 | `(fresh``\ `{=latex}`(expr1``\ `{=latex}`expr2)`\
361 | `(absento``\ `{=latex}`expr1``\ `{=latex}`expr2)`\
362 | `(==``\ `{=latex}`‘(,expr1``\ `{=latex}`.``\ `{=latex}`,expr2)``\ `{=latex}`p)`\
363 | `(evalo``\ `{=latex}`p``\ `{=latex}`p)))`
364 |
365 | `=>`
366 |
367 | `((((lambda``\ `{=latex}`(_.0)`\
368 | `(list``\ `{=latex}`(list``\ `{=latex}`’lambda``\ `{=latex}`’(_.0)``\ `{=latex}`_.0)``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
369 | `’(list``\ `{=latex}`(list``\ `{=latex}`’lambda``\ `{=latex}`’(_.0)``\ `{=latex}`_.0)``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
370 | `(=/=``\ `{=latex}`((_.0``\ `{=latex}`closure))``\ `{=latex}`((_.0``\ `{=latex}`list))``\ `{=latex}`((_.0``\ `{=latex}`quote)))`\
371 | `(sym``\ `{=latex}`_.0)))`
372 |
373 | Gary P. Thompson II's Quine page
374 | () also describes *Quine
375 | Generating Programs* ():
376 |
377 | > It is possible (and actually in some cases easier) to write a program
378 | > which outputs another program which is itself a quine.
379 |
380 | using `q.scm` from faster-miniKanren:
381 |
382 | `(run``\ `{=latex}`1``\ `{=latex}`(nq``\ `{=latex}`q)`\
383 | `(=/=``\ `{=latex}`q``\ `{=latex}`nq)`\
384 | `(evalo``\ `{=latex}`nq``\ `{=latex}`q)`\
385 | `(evalo``\ `{=latex}`q``\ `{=latex}`q))`\
386 | `=>`\
387 | `(((’((lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
388 | `’(lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0))))`\
389 | `((lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
390 | `’(lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))))`\
391 | `(=/=``\ `{=latex}`((_.0``\ `{=latex}`closure))``\ `{=latex}`((_.0``\ `{=latex}`list))``\ `{=latex}`((_.0``\ `{=latex}`quote)))`\
392 | `(sym``\ `{=latex}`_.0)))`
393 |
394 | `(run``\ `{=latex}`1``\ `{=latex}`(nq``\ `{=latex}`q)`\
395 | `(absento``\ `{=latex}`q``\ `{=latex}`nq)`\
396 | `(evalo``\ `{=latex}`nq``\ `{=latex}`q)`\
397 | `(evalo``\ `{=latex}`q``\ `{=latex}`q))`\
398 | `=>`\
399 | `((((list`\
400 | `’(lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
401 | `”(lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0))))`\
402 | `((lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))`\
403 | `’(lambda``\ `{=latex}`(_.0)``\ `{=latex}`(list``\ `{=latex}`_.0``\ `{=latex}`(list``\ `{=latex}`’quote``\ `{=latex}`_.0)))))`\
404 | `(=/=``\ `{=latex}`((_.0``\ `{=latex}`closure))``\ `{=latex}`((_.0``\ `{=latex}`list))``\ `{=latex}`((_.0``\ `{=latex}`quote)))`\
405 | `(sym``\ `{=latex}`_.0)))`
406 |
407 | \[TODO: challenge to myself: generate a Kimian self-rep
408 | ()
409 |
410 | > Kimian self-rep, like quines, got it's name from Godel Escher Bach. A
411 | > Kimian 'program' is actually the error produced by the system when it
412 | > encounters the code. Kimian self reps are therefore very
413 | > system-specific, and even implementation specific.
414 |
415 | I want to add errors to the interp, any way. Once I've added errors, I
416 | should in theory be able to synthesize Kimian self-reps. Try it! And
417 | then move this description and code to the chapter that adds errors to
418 | the interp.
419 |
420 | Update: I've been able to generate Kimian self-rep, as can be seen in
421 | `daily-mK/2025_01_21`:
422 |
423 | `>``\ `{=latex}`(load``\ `{=latex}`"q-error.scm")`\
424 | `>``\ `{=latex}`(run``\ `{=latex}`1``\ `{=latex}`(e)``\ `{=latex}`(evalo``\ `{=latex}`e``\ `{=latex}`e``\ `{=latex}`))`\
425 | `((error``\ `{=latex}`(unbound-variable``\ `{=latex}`error)))`
426 |
427 | Need to clean up the interpreter code, which effectively uses the Maybe
428 | monad. I also need to check that the standard Quine still works with the
429 | updated interpreter, and try reorderings of the conjuncts, etc., to both
430 | avoid duplicate errors and to make the interp efficient enough to
431 | generate our standard Quine. \]
432 |
433 | \[TODO: play with the ideas in this other Quines page
434 | (thanks to Nada Amin
435 | for the pointer to this page, which I had forgotten about)\]
436 |
437 | # Using a two-list representation of the environment
438 |
439 | association-list representation of an environment where `x` is mapped to
440 | the list `(cat dog)` and `y` is mapped to `5`:
441 |
442 | `((x``\ `{=latex}`.``\ `{=latex}`(cat``\ `{=latex}`dog))`\
443 | `(y``\ `{=latex}`.``\ `{=latex}`5))`
444 |
445 | "split" two-list representation of the same environment:
446 |
447 | `(x``\ `{=latex}`y)``\ `{=latex}`;``\ `{=latex}`variables`
448 |
449 | `((cat``\ `{=latex}`dog)``\ `{=latex}`6)``\ `{=latex}`;``\ `{=latex}`values`
450 |
451 | ;; a-list env ;; ((x . (cat dog)) ;; (y . 5))
452 |
453 | ;; split env ;; (x y) ;; ((cat dog) 6)
454 |
455 | `absento` trick for lazy `not-in-envo`
456 |
457 | ;; (absento 'closure expr)
458 |
459 | ;; (absento t1 t2)
460 |
461 | ;; (not-in-envo 'lambda env) ;; (absento 'lambda '(x y))
462 |
463 | `(defrel``\ `{=latex}`(evalo``\ `{=latex}`expr``\ `{=latex}`val)`\
464 | `(eval-expro``\ `{=latex}`expr``\ `{=latex}`’(()``\ `{=latex}`.``\ `{=latex}`())``\ `{=latex}`val))`
465 |
466 | `(defrel``\ `{=latex}`(eval-expro``\ `{=latex}`expr``\ `{=latex}`env``\ `{=latex}`val)`\
467 | `(conde`\
468 | `;;``\ `{=latex}`quote,``\ `{=latex}`list,``\ `{=latex}`and``\ `{=latex}`variable``\ `{=latex}`reference/lookup``\ `{=latex}`clauses``\ `{=latex}`elided`\
469 | `((fresh``\ `{=latex}`(rator``\ `{=latex}`rand``\ `{=latex}`body``\ `{=latex}`env^``\ `{=latex}`a``\ `{=latex}`x``\ `{=latex}`x*``\ `{=latex}`v*)`\
470 | `(==``\ `{=latex}`‘(,rator``\ `{=latex}`,rand)``\ `{=latex}`expr)`\
471 | `(==``\ `{=latex}`‘(,x*``\ `{=latex}`.``\ `{=latex}`,v*)``\ `{=latex}`env^)`\
472 | `(eval-expro``\ `{=latex}`rator``\ `{=latex}`env``\ `{=latex}`‘(closure``\ `{=latex}`,x``\ `{=latex}`,body``\ `{=latex}`,env^))`\
473 | `(eval-expro``\ `{=latex}`rand``\ `{=latex}`env``\ `{=latex}`a)`\
474 | `(eval-expro``\ `{=latex}`body`\
475 | `‘((,x``\ `{=latex}`.``\ `{=latex}`x*)``\ `{=latex}`.``\ `{=latex}`(,a``\ `{=latex}`.``\ `{=latex}`v*))`\
476 | `val)))`\
477 | `;;``\ `{=latex}`lambda``\ `{=latex}`clause``\ `{=latex}`elided`\
478 | `))`
479 |
480 | `(defrel``\ `{=latex}`(not-in-envo``\ `{=latex}`x``\ `{=latex}`env)`\
481 | `(fresh``\ `{=latex}`(x*``\ `{=latex}`v*)`\
482 | `(==``\ `{=latex}`‘(,x*``\ `{=latex}`.``\ `{=latex}`,v*)``\ `{=latex}`env)`\
483 | `(absento``\ `{=latex}`x``\ `{=latex}`x*)))`
484 |
485 | \[TODO discuss tradeoffs between asserting (symbolo x) in these helper
486 | relations---how stand-alone do we want them?\]
487 |
488 | `(defrel``\ `{=latex}`(lookupo``\ `{=latex}`x``\ `{=latex}`env``\ `{=latex}`t)`\
489 | `(fresh``\ `{=latex}`(y``\ `{=latex}`x*``\ `{=latex}`v``\ `{=latex}`v*)`\
490 | `(==``\ `{=latex}`‘((,y``\ `{=latex}`.``\ `{=latex}`,x*)``\ `{=latex}`.``\ `{=latex}`(,v``\ `{=latex}`.``\ `{=latex}`,v*))``\ `{=latex}`env)`\
491 | `(conde`\
492 | `((==``\ `{=latex}`y``\ `{=latex}`x)``\ `{=latex}`(==``\ `{=latex}`v``\ `{=latex}`t))`\
493 | `((=/=``\ `{=latex}`y``\ `{=latex}`x)``\ `{=latex}`(lookupo``\ `{=latex}`x``\ `{=latex}`‘(,x*``\ `{=latex}`.``\ `{=latex}`,v*)``\ `{=latex}`t)))))`
494 |
495 | # Extending the interpreter to handle `append`
496 |
497 | add `cons`, `car`, `cdr`, `null?`, and `if`
498 |
499 | extend `lambda` and application to handle multiple arguments and
500 | variadic
501 |
502 | # Using a non-empty initial environment
503 |
504 | So far our `evalo` driver relation has used an empty initial
505 | environment. The `eval-expro` relations treats application of `cons`
506 | explicitly, as if it were a special form; as a result, while it is
507 | possible to shadow `cons`:
508 |
509 | \[TODO actually, given that cons is the only built-in function, and we
510 | don't support multi-arg or variadic application, I'm not sure I can
511 | really show off shadoing:\]
512 |
513 | `((lambda``\ `{=latex}`(cons)``\ `{=latex}`(cons``\ `{=latex}`’cat``\ `{=latex}`’dog))``\ `{=latex}`(lambda``\ `{=latex}`(x))`
514 |
515 | it is not possible to treat the built-in `cons` as a first-class
516 | procedure value:
517 |
518 | `(cons``\ `{=latex}`cons``\ `{=latex}`cons)`\
519 | `=>`\
520 | `[TODO``\ `{=latex}`what``\ `{=latex}`is``\ `{=latex}`the``\ `{=latex}`behavior?``\ `{=latex}`unbound``\ `{=latex}`variable``\ `{=latex}`cons``\ `{=latex}`as``\ `{=latex}`an``\ `{=latex}`error?]`
521 |
522 | `((lambda``\ `{=latex}`(x)``\ `{=latex}`x)``\ `{=latex}`cons)`\
523 | `=>`\
524 | `[TODO``\ `{=latex}`what``\ `{=latex}`is``\ `{=latex}`the``\ `{=latex}`behavior?``\ `{=latex}`unbound``\ `{=latex}`variable``\ `{=latex}`cons``\ `{=latex}`as``\ `{=latex}`an``\ `{=latex}`error?]`
525 |
526 | new case to handle prim app rather than user-defined closure app
527 |
528 | use either `cons` or `list`; have to implement `eval-listo`, anyway, for
529 | application of primitives and varidic application---probably best to
530 | implement both `list` and `cons`
531 |
532 | `eval-listo` to evaluate the arguments of the `rand`
533 |
534 | move code to handle those primitive cases to `eval-primo`, without the
535 | `not-in-envo` calls
536 |
537 | `cons`, `car`, `cdr`, and `null?` bound in the initial env to prims
538 |
539 | `list` bound in the initial env to the closure that results from
540 | evaluating the variadic `(lambda x x)`
541 |
542 | Experimental: try adding quote and lambda to the intial env as well, as
543 | in my experiments starting with `daily-mK/2025_01_22`
544 |
545 | # Adding explicit errors
546 |
547 | So far our interpreters handle Scheme errors implicitly by failing to
548 | produce a result, rather than producing an explicit error. This implicit
549 | representation of errors has advantages, in both keeping the
550 | implementation code simple and in performance/fail-fast behavior.
551 |
552 | \[TODO see the code and comments in `daily-mK/2025_01_19` --- this code
553 | needs to be updated to use non-empty initial environment, to avoid
554 | unbound variable errors for built-ins, such as
555 | `(error (unbound variable lambda))`\]
556 |
557 | \[TODO discuss disadvantage of threading through values monadically
558 | instead of lexically, esp. regarding losing fail-fast behavior, breaking
559 | the wires, and losing flexibility in reordering conjuncts\]
560 |
561 | \[TODO hmm in my experiments, if I have an explicit error for unbound
562 | variables, I seem to need to "guard" the application (and prim app, if I
563 | have non-empty initial environments) by ensuring that the rator is
564 | either not any of the keywords (quote, lambda, etc.), or that the rator
565 | is a keyword, and lookup produces a value rather an error. See
566 | `daily-mK/2025_01_21`. Hmm, can I just use this guarding instead of
567 | having to go to a non-empty initial env, if all I want is an explicit
568 | error for unbound variable lookup?\]
569 |
570 | # Angelic execution
571 |
572 | \[TODO look at my code from PolyConf 2015, which includes an interpreter
573 | for an imperative language, along with angelic execution; cite PL course
574 | slides for example\]
575 |
576 | # Adding mutation
577 |
578 | \[TODO look at my code from PolyConf 2015, which includes an interpreter
579 | for an imperative language, along with angelic execution\]
580 |
581 | support `set!` (can we get away with supporting `set!` without adding a
582 | store?)
583 |
584 | support mutiple pairs and have an explicit store
585 |
586 | # Adding delimited control operators
587 |
588 | delimited continuations and/or effect handlers---can we do so in such a
589 | way that avoids "breaking the wires"?
590 |
591 | talk about the problem with `call/cc` and breaking the wires
592 |
593 | # Writing a parser as a relation
594 |
595 | \[TODO I'm not saying this right. For a program skeleton plus N
596 | input/output examples, N+1 instances of Chez Scheme are launced as
597 | separate processes: one per example, which, if it fails fast, will
598 | result in the overall synthesis task being stopped. The other processes
599 | the sketch plus all the input/output examples, all in a conjunction. All
600 | N+1 processes run the parser before trying to run evalo, as a separate
601 | run expression, in an attempt to generate a cleaner error messages if
602 | the user makes a syntactic mistake, while stopping the entire set of N+1
603 | computations if the individual discrete tests faol\]
604 |
605 | Barliman uses a 'run' query to try to parse the user's code; if the
606 | parse query fails, the entire synthesis task is halted, with an error
607 | message.
608 |
609 | \[TODO get the details straight, including the OS processes that are
610 | launched for each test and for the main synthesis tasks; also, the GUI
611 | behavior\]
612 |
613 | # Writing a type inferencer as a relation
614 |
615 | # Build your own Barliman
616 |
617 | # Speeding up the interpreter
618 |
619 | \[restrict to interpreter changes that don't require hacking
620 | faster-miniKanren or in-depth knowledge of the implementation\]
621 |
622 | dynamic reordering of conjuncts, especially for application
623 |
624 | fast environment lookup for environments that are sufficiently ground
625 |
626 | # Open problems
627 |
628 | [^1]: Such programs are often called *program sketches* \[TODO cite\].
629 |
630 | [^2]: This is known in the literature as "angelic execution".
631 |
632 | [^3]: I thank Larry Moss and the Indiana University Logic Symposium
633 | \[TODO check the name of the symposium\] for inviting me to give a
634 | talk where I demonstrated Quine generation, and where Larry
635 | suggested I tried generating Twines.
636 |
--------------------------------------------------------------------------------