├── .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 | --------------------------------------------------------------------------------