<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5145015724555605651</id><updated>2012-01-21T01:18:11.029-08:00</updated><category term='gc'/><category term='solver'/><category term='variants'/><category term='status'/><category term='parser'/><category term='inliner'/><category term='llvm jit bitcode'/><category term='vectors'/><title type='text'>The Alien Tongue</title><subtitle type='html'>News and Info for the Irken Community</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://alien.nightmare.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>65</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-2786248108808925229</id><published>2012-01-21T01:18:00.000-08:00</published><updated>2012-01-21T01:18:11.041-08:00</updated><title type='text'>Some notes on continuation-passing style</title><content type='html'>I've been going over the CPS transform lately, and wrote some notes on how to use the transform to compile to C, stackless style.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dark.nightmare.com/rushing/factcps/"&gt;dark.nightmare.com/rushing/factcps/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-2786248108808925229?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/2786248108808925229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2012/01/some-notes-on-continuation-passing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2786248108808925229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2786248108808925229'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2012/01/some-notes-on-continuation-passing.html' title='Some notes on continuation-passing style'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-4802641383924984944</id><published>2012-01-09T17:30:00.000-08:00</published><updated>2012-01-09T17:30:17.976-08:00</updated><title type='text'>thinking about an llvm backend, again</title><content type='html'>I've been very happy with my other project that uses LLVM as the backend for a compiler.&lt;br /&gt;I've also learned a lot about LLVM's IR design.&lt;br /&gt;&lt;br /&gt;I can't help but think that it might only take a week or two to write a back end for Irken.&lt;br /&gt;However, there are a few issues.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;My CPS output assumes that each insn has a result that is put into a register. &amp;nbsp;This doesn't fit LLVM's model, which assumes that arguments to insns can be &lt;i&gt;either&lt;/i&gt;&amp;nbsp;an immediate &lt;i&gt;or&lt;/i&gt;&amp;nbsp;a register. &amp;nbsp;In fact, they do not allow you to put an immediate into a register.&lt;/li&gt;&lt;li&gt;LLVM doesn't like gcc's goto-label feature. &amp;nbsp; I think they implemented it reluctantly, because it doesn't fit the SSA model very well. &amp;nbsp;The majority of funcalls by Irken are to known functions, which translate to a branch to a known label. &amp;nbsp;However, whenever higher-level functions are called, this leads to something like "&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;goto *r0;&lt;/span&gt;" in C, which turns into an indirectbr insn in LLVM. &amp;nbsp;It implements this using a gigantic phi/indirectbr table at the very end of the function. &amp;nbsp;Maybe this isn't really a problem - it just looks bad.&lt;/li&gt;&lt;li&gt;The extremely useful &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;%cexp&lt;/span&gt; primitive would go away! &amp;nbsp;There's something to be said for being able to refer to OS constants, OS functions, macros, etc... with such a simple mechanism. &amp;nbsp;I'd probably just have to let it go, and force users to write stubs.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;I think #1 can be dealt with by adding an extra pass that translates between the two representations. &amp;nbsp;(maybe I should revisit the CPS==SSA paper?)&lt;/div&gt;&lt;div&gt;Another approach might be to use an annoying alloca/store/load sequence and hope that mem2reg does a good job?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-4802641383924984944?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/4802641383924984944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2012/01/thinking-about-llvm-backend-again.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4802641383924984944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4802641383924984944'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2012/01/thinking-about-llvm-backend-again.html' title='thinking about an llvm backend, again'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-1046849896003607618</id><published>2012-01-02T00:15:00.000-08:00</published><updated>2012-01-02T00:15:26.126-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='llvm jit bitcode'/><title type='text'>Irken status, LLVM bitcode</title><content type='html'>This is just a quick note that the Irken project has &lt;i&gt;not&lt;/i&gt;&amp;nbsp;died, only gone into a temporary hibernation.&lt;br /&gt;When in the course of history it becomes necessary to earn a living...&lt;br /&gt;&lt;br /&gt;Anyway, I have some tangentially related comments about LLVM.&lt;br /&gt;My current employer is interested in maybe doing a little LLVM JIT work, wherein my experience with compilers may prove useful. &amp;nbsp;A nice side effect for me is that I &lt;i&gt;finally&lt;/i&gt;&amp;nbsp;get to play around a bit with LLVM, something which I carefully avoided while working on Irken.&lt;br /&gt;&lt;br /&gt;My first reaction was to pick up llvm-py, which looked like a fairly complete interface to the various libraries that make up the llvm system.&lt;br /&gt;&lt;br /&gt;Big Mistake. &amp;nbsp;It doesn't build any more. &amp;nbsp;It's only a little over a year old. &amp;nbsp;The last release of llvm-py was for LLVM 2.8rc2. &amp;nbsp;I am now running 3.0.&lt;br /&gt;&lt;br /&gt;Here's the problem: the LLVM API's are &lt;b&gt;constantly&lt;/b&gt;&lt;a href="http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-June/023190.html"&gt;&amp;nbsp;changing&lt;/a&gt;. &amp;nbsp;And that's a good thing, really. &amp;nbsp;But since those C++ API's are the only well-supported interface to the system, it's a moving target.&lt;br /&gt;&lt;br /&gt;There are &lt;a href="http://llvm.org/docs/FAQ.html#langirgen"&gt;three main options&lt;/a&gt; for a compiler writer who wants to target LLVM. &amp;nbsp;The first is to use the C++ API. &amp;nbsp;(or you could use the completely undocumented and incomplete C interface).&lt;br /&gt;&lt;br /&gt;The second option is to write llvm assembly. &amp;nbsp;This is not a bad option, but will be slower because of the need to parse the assembly.&lt;br /&gt;&lt;br /&gt;The third is to write llvm 'bitcode'. &amp;nbsp;I thought this was probably the right approach. &amp;nbsp;Bitcode is a binary representation of the LLVM IR language, it seems that it would be likely to change much more slowly than the library interfaces.&lt;br /&gt;&lt;br /&gt;The problem is that the person who designed the &lt;a href="http://llvm.org/docs/BitCodeFormat.html"&gt;bitcode file format&lt;/a&gt; was on meth at the time. &amp;nbsp;This has got to be one of the most evil formats I've ever seen. &amp;nbsp;I &lt;b&gt;think&lt;/b&gt;&amp;nbsp;they were trying to make the resulting file as small as possible, but at the expense of counting every bit. &amp;nbsp;(perhaps an early LLVM project flew on a space probe?) &amp;nbsp;Just to give you an idea, 3 and 4-bit integers (not aligned on any boundary) are a common field type. &amp;nbsp;And not just that, but some of the fields are variably sized, starting at 2 bits and going up. &amp;nbsp;Symbols are represented using 6-bit characters. &amp;nbsp;Also, the concept of 'bitstream' is taken very literally, the bits in a file are viewed as if it were one large integer, starting from the LSB. &amp;nbsp;This is actually an elegant approach, but it is &lt;i&gt;completely&lt;/i&gt;&amp;nbsp;different from every other file format or network protocol. &amp;nbsp;I had to continually resist using common parsing patterns with it. &amp;nbsp; There's also a compression-like method of 'abbreviating' common record types. &amp;nbsp;And after all that work to save bits, at the end of every block the bit stream is aligned to 32 bits!&lt;br /&gt;&lt;br /&gt;Ok, got that off my chest.&lt;br /&gt;&lt;br /&gt;My sense is that nobody uses the bitcode format because of this (the only other implementation I could find was in Haskell, and was also impenetrable because Everything Is A Monad, You Know). &amp;nbsp;Most people just succumb to the pressure to write against the C++ API, and will then spend the rest of their lives reading the llvm-dev list to keep track of the changes.&lt;br /&gt;&lt;br /&gt;I have &lt;a href="http://dark.nightmare.com/rushing/python/bc.py"&gt;mostly decoded the format&lt;/a&gt;, and I think I could actually output it for a compiler.&lt;br /&gt;But I think I'll split the difference and start out by outputting llvm assembly to start with. &amp;nbsp;If the day comes when I need to shave some of the 10MB off the resulting .so file, and maybe speed things up, I'll revisit the bitcode issue.&lt;br /&gt;&lt;br /&gt;In the meanwhile I've had a whack at using &lt;a href="http://dark.nightmare.com/rushing/misc/llvm.pyx.html"&gt;Cython's C++ support to make a minimal interface to LLVM&lt;/a&gt; where I can feed either llvm assembly or bitcode to the JIT and run it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-1046849896003607618?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/1046849896003607618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2012/01/irken-status-llvm-bitcode.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/1046849896003607618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/1046849896003607618'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2012/01/irken-status-llvm-bitcode.html' title='Irken status, LLVM bitcode'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-4568532663817840813</id><published>2011-05-23T17:15:00.000-07:00</published><updated>2011-05-23T17:15:47.584-07:00</updated><title type='text'>git, github, clang</title><content type='html'>I've imported my svn history into git, and published the whole thing on github:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/samrushing/irken-compiler/"&gt;https://github.com/samrushing/irken-compiler/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Still trying to grok git and github, there'll probably be a stall for a week or so.&lt;br /&gt;&lt;br /&gt;In the meanwhile, I have interesting news: &amp;nbsp;I was able to take out all the 'nested functions' which relied on a gcc extension. &amp;nbsp;I resisted this for a long time because early testing had shown that declaring the 'registers' as local register variables in the main function was a huge win.&lt;br /&gt;&lt;br /&gt;After a quick test the other day, I found that moving everything out to global variables has no visible impact on performance. &amp;nbsp;I don't know if this is because of improvements in gcc &amp;amp; llvm, or if I just wasn't trying a large enough program.&lt;br /&gt;&lt;br /&gt;That means I'm now able to compile the output with clang, rather than relying on llvm+dragonegg, which can be much more annoying to build, install, and use.&lt;br /&gt;&lt;br /&gt;The good news continues: although the performance of the generated code is identical (maybe a tiny bit faster), the compilation time has been cut quite significantly. &amp;nbsp;On my machine an LLVM -O2 compile dropped from 18m to 8m. &amp;nbsp;The -O0 compile time is even sweeter, about 3s, which is actually faster than Irken itself, which hovers right around 5s to self-compile. &amp;nbsp;So a roughly 10s edit-compile cycle will definitely speed the development of Irken up.&lt;br /&gt;&lt;br /&gt;Now the bad news. &amp;nbsp;The no-nested-funs version causes 'as' on snow leopard to take a lunch break. &amp;nbsp;It actually nails the CPU for 10 or 15 minutes before finally emerging as if nothing was wrong. &amp;nbsp;No problems on FreeBSD 7.3 with gcc-4.5.3, though. &amp;nbsp;This could be a significant annoyance, since I expect many people trying out Irken would prefer to do so with a stock compiler.&lt;br /&gt;&lt;br /&gt;More bad news: &amp;nbsp;clang-2.9 crashes when fed Irken's self-compiled output. &amp;nbsp;I was going to file a bug against it, but when I checked out the svn version and built it the problem was gone. &amp;nbsp;Sigh.&lt;br /&gt;&lt;br /&gt;This is why I'm trying to figure out how to make branches on github, since it'd be nice to maintain both versions for a while until these issues are ironed out. &amp;nbsp;I have made a local branch called 'no-nested-funs', I just haven't figured out how to publish it on github.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-4568532663817840813?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/4568532663817840813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/05/git-github-clang.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4568532663817840813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4568532663817840813'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/05/git-github-clang.html' title='git, github, clang'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-8730415127328411899</id><published>2011-05-15T15:59:00.000-07:00</published><updated>2011-05-15T15:59:43.184-07:00</updated><title type='text'>nested datatypes, 2-3 trees, numerical encoding</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"&gt;This &lt;a href="http://www.soi.city.ac.uk/~ross/papers/FingerTree.pdf"&gt;paper by Hinze &amp;amp; Paterson&lt;/a&gt;&amp;nbsp;discusses the use of 'nested datatypes' to implement 2-3 trees, but in a way that uses the type system to automatically handle the invariants. &amp;nbsp;A &lt;a href="http://scienceblogs.com/goodmath/2010/04/finger_trees_done_right_i_hope.php"&gt;blog post from Mark Chu-Carroll&lt;/a&gt;&amp;nbsp;is a bit easier to follow. &amp;nbsp;Here's his example of a sequence encoded as a 2-3 tree (in Haskell):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Arial, Verdana, Geneva, Helvetica, sans-serif; line-height: 16px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;data Tree t = Zero t | Succ (Tree (Node t))&lt;br /&gt;data Node s = Node2 s s | Node3 s s s&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;Each level of the tree contains sub-trees that are 'one less' via the numeric encoding scheme.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;This sent me back to Okasaki's book, where I'm finally starting to grok those last two chapters. &amp;nbsp;This &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.571"&gt;bizarre mingling of numerical encoding and data structures&lt;/a&gt; lights a fire in the parts of my brain dedicated to data structures. &amp;nbsp;If feel as if I could automatically see the relationship between red-black trees, 2-3 trees, and binary number representations.... if only I could double my IQ.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;I have this cool puzzle called the '&lt;a href="http://www.jaapsch.net/puzzles/spinout.htm"&gt;Spin-Out&lt;/a&gt;', which is actually a physical demonstration of the properties of &lt;a href="http://en.wikipedia.org/wiki/Gray_code"&gt;Gray Codes&lt;/a&gt;. &amp;nbsp;It seems to me that Gray Codes and balanced trees should be a natural fit.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;Unfortunately, I can't experiment with any of these ideas in Irken (or OCaml, or SML) because the nested datatypes require polymorphic recursion.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;Type inference with polymorphic recursion is undecidable. &amp;nbsp;Haskell allows it only if the user provides a manual type signature. &amp;nbsp;I'm guessing this is impossible (i.e., unsafe) with SML/OCaml because of the presence of assignment? &amp;nbsp;Could such a feature safely be used with functions that the compiler can verify are pure?&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;span class="Apple-style-span" style="white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-8730415127328411899?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/8730415127328411899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/05/nested-datatypes-2-3-trees-numerical.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8730415127328411899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8730415127328411899'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/05/nested-datatypes-2-3-trees-numerical.html' title='nested datatypes, 2-3 trees, numerical encoding'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-8549283194312840652</id><published>2011-04-27T00:36:00.000-07:00</published><updated>2011-04-27T00:36:26.695-07:00</updated><title type='text'>DOOM DOOM DOOM (a coro/thread kqueue-based scheduler)</title><content type='html'>I've created a new sub-project, code-named 'doom', for the coroutine-based cooperative threading system. &amp;nbsp;It uses kqueue(), of course. &amp;nbsp;Because it's better. &amp;nbsp;It wouldn't be too hard for someone from linux-land to make a version based on epoll.&lt;br /&gt;&lt;br /&gt;In the &lt;a href="http://dark.nightmare.com/rushing/irken/irken/doom/"&gt;doom directory&lt;/a&gt;, you'll find a &lt;a href="http://dark.nightmare.com/rushing/irken/irken/doom/fetch.scm.html"&gt;simple http demo&lt;/a&gt;, and the &lt;a href="http://dark.nightmare.com/rushing/irken/irken/doom/echo.scm.html"&gt;obligatory echo server&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Exception handling certainly makes the code look a lot nicer.&lt;br /&gt;&lt;br /&gt;I'm the best at space.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-8549283194312840652?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/8549283194312840652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/04/doom-doom-doom-corothread-kqueue-based.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8549283194312840652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8549283194312840652'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/04/doom-doom-doom-corothread-kqueue-based.html' title='DOOM DOOM DOOM (a coro/thread kqueue-based scheduler)'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-4722253415515245745</id><published>2011-04-22T15:55:00.000-07:00</published><updated>2011-04-22T21:58:52.333-07:00</updated><title type='text'>exception handling, take two</title><content type='html'>A bit tricky, but I found a way to implement &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;try/except&lt;/span&gt; almost completely with defmacro. &amp;nbsp;I needed to add some extra typechecking around &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;raise&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;try&lt;/span&gt; to ensure that all exception types are monomorphic. &amp;nbsp;I achieved this by having the compiler keep a global map of exception-name =&amp;gt; tvar. &amp;nbsp; Seems to work...&lt;br /&gt;&lt;br /&gt;While working on this I learned that the Scheme-style &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;call/cc&lt;/span&gt; is not really type safe, and I need to use the SML version. &amp;nbsp;The main difference is the protocol - SML's &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;callcc&lt;/span&gt; requires the use of a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;throw&lt;/span&gt; procedure since the continuation needs to carry type information:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(define (callcc p) : (((continuation 'a) -&amp;gt; 'a) -&amp;gt; 'a)&lt;br /&gt;&amp;nbsp; (p (getcc)))&lt;br /&gt;&lt;br /&gt;(define (throw k v)&lt;br /&gt;&amp;nbsp; (putcc k v))&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; -*- Mode: Irken -*-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;"lib/core.scm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;"lib/random.scm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; We use polymorphic variants for exceptions.&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; Since we're a whole-program compiler there's no need to declare&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; them - though I might could be convinced it's still a good idea.&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; Exception data must be monomorphic to preserve type safety.&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; &amp;lt;try&amp;gt; and &amp;lt;raise&amp;gt; are implemented as macros, with one extra hitch:&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  two special compiler primitives are used to check that exception&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  types are consistent: %exn-raise and %exn-handle&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;base-exception-handler&lt;/span&gt; &lt;span class="nv"&gt;exn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;:&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;rsum&lt;/span&gt; &lt;span class="ss"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="ss"&gt;'b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error1&lt;/span&gt; &lt;span class="s"&gt;"uncaught exception"&lt;/span&gt; &lt;span class="nv"&gt;exn&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt; &lt;span class="nv"&gt;base-exception-handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;raise&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="nv"&gt;exn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;*the-exception-handler*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;%exn-raise&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt; &lt;span class="nv"&gt;exn&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;try&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; done accumulating body parts, finish up.&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;except&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;exn-match&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;callcc&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;$exn-k0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;$old-hand&lt;/span&gt; &lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set!&lt;/span&gt;&lt;br /&gt;           &lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;$exn-val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt; &lt;span class="nv"&gt;$old-hand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;throw&lt;/span&gt; &lt;span class="nv"&gt;$exn-k0&lt;/span&gt;&lt;br /&gt;              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;%exn-handle&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt; &lt;span class="nv"&gt;$exn-val&lt;/span&gt;&lt;br /&gt;               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;$exn-val&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;br /&gt;                 &lt;span class="nv"&gt;exn-match&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;br /&gt;                 &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="nv"&gt;$exn-val&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;br /&gt;          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;$result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt; &lt;span class="nv"&gt;$old-hand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; accumulating body parts...&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="nv"&gt;body2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; begin to accumulate...&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                   &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level0&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level1&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="nv"&gt;except&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Level0&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:pair&lt;/span&gt; &lt;span class="s"&gt;"level 0"&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level1&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level2&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="nv"&gt;except&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Level1&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:pair&lt;/span&gt; &lt;span class="s"&gt;"level 1"&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level2&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level3&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="nv"&gt;except&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Level2&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:pair&lt;/span&gt; &lt;span class="s"&gt;"level 2"&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level3&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;br /&gt;     &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Level0&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;     &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Level1&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;     &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Level2&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;     &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Level3&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;     &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:pair&lt;/span&gt; &lt;span class="s"&gt;"no exception!"&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;     &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Bottom&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;     &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="nv"&gt;except&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:Level3&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:pair&lt;/span&gt; &lt;span class="s"&gt;"level 3"&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level0&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level0&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level0&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level0&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;level0&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-4722253415515245745?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/4722253415515245745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/04/exception-handling-take-two.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4722253415515245745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4722253415515245745'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/04/exception-handling-take-two.html' title='exception handling, take two'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-6403279454141380478</id><published>2011-04-06T17:15:00.000-07:00</published><updated>2011-04-06T17:15:32.593-07:00</updated><title type='text'>exception handling with defmacro</title><content type='html'>I've started work on a coroutine/thread scheduler, code named "Doom". &amp;nbsp;Doing some socket I/O has finally &amp;nbsp;snapped my 'missing feature' threshold - I really need exception handling to do it right.&lt;br /&gt;&lt;br /&gt;Here's my first attempt.  The basic syntax is &lt;code&gt;(try &amp;lt;body&amp;gt; except &amp;lt;exception-patterns&amp;gt;)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;If this works, it'll be a great example of the huge advantages of the lisp syntax and macros - no changes made to the compiler to support it!&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; -*- Mode: Irken -*-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;"lib/core.scm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;"lib/random.scm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; can we implement an exception system using the macro system?&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; XXX eventually we'll need to change call/cc to swap out exception&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  handlers, which probably means making a 'modern' call/cc with&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  dynamic-wind, etc.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;base-exception-handler&lt;/span&gt; &lt;span class="nv"&gt;exn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error1&lt;/span&gt; &lt;span class="s"&gt;"uncaught exception"&lt;/span&gt; &lt;span class="nv"&gt;exn&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt; &lt;span class="nv"&gt;base-exception-handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="nv"&gt;exn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;*the-exception-handler*&lt;/span&gt; &lt;span class="nv"&gt;exn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; what kind of values do we want for exceptions, and how they're caught/compared?&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; python: started with strings, went to objects of the Exception class.&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; scheme: SRFI-12 includes something that looks like property lists?&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; sml: string refs? (in sml/nj according to CwC)&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; ocaml: declared exception datatypes.&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; [alternate for ocaml: http://dutherenverseauborddelatable.wordpress.com/downloads/exception-monads-for-ocaml/&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  sounds a little like my 'fourth idea']&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; my first temptation is to just use symbols, and stay simple&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; second idea is to use a record, which theoretically gives you the&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   ability to attach other kinds of data, which could be very&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   convenient. Example: (raise BadFD) =&amp;gt; {exception='BadFD ...}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; third idea: hardcore - define a global exception type, force the user to&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   extend it.  [could be made easier by compiler hacks that allow you to&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   extend the type anywhere in the source?].  Code would have to wildcard&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   exceptions it doesn't know about?  [or is that the definition of handing&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   it upstream?]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; fourth idea: use records (or polymorphic variants) to define unique&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   exception names *and* types.  For example: (raise (BadFD&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   current-fd)) would type as {BadFD=int ...}  this would make it&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   more like the SRFI-12 property-list thing (unless I misunderstand&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   what SRFI-12 is all about).  Hmmm... maybe we could extend the&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   exception handler by extending the record?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; It'd be nice if the type system can tell us what exceptions are possible&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   at any given point in the code... is this maybe impossible due to the&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   dynamic (vs static/lexical) nature of exception handling?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; the more I think about the 'fourth idea' the less reason I see to&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  restrict the type of exceptions.  Syntax-wise, the following macro&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  does not enforce any restrictions.  It's possible though that only&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  the polymorphic-variant-scheme will survive type checking.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; this is the first time I've tried to 'accumulate' pieces in a macro.&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; it's possible that there's a better idiom that I just haven't discovered yet.&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; should really look to see how the scheme folks do this (or do they just avoid&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; it all by wrapping everything in verbose s-expressions).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;try&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; done accumulating body parts, finish up.&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;except&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;exn-match&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;$old-hand&lt;/span&gt; &lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set!&lt;/span&gt;&lt;br /&gt;        &lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;$exn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt; &lt;span class="nv"&gt;$old-hand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;$exn&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;br /&gt;            &lt;span class="nv"&gt;exn-match&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;br /&gt;            &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="nv"&gt;$exn&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;br /&gt;       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;$result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;*the-exception-handler*&lt;/span&gt; &lt;span class="nv"&gt;$old-hand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;         &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; accumulating body parts...&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="nv"&gt;body2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; begin to accumulate...&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="nv"&gt;body0&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                   &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="nv"&gt;body0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random-barf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;= &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logand&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:OtherException&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;      &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;thing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;try&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="nv"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;= &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:MyException&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;begin&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random-barf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;&lt;br /&gt;   &lt;span class="nv"&gt;except&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:MyException&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:OtherException&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;thing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Here's what the macro expansion looks like for &lt;code&gt;thing&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(define (thing)&lt;br /&gt;  (let (($old-hand *the-exception-handler*))&lt;br /&gt;    (begin&lt;br /&gt;      (set!&lt;br /&gt;       *the-exception-handler*&lt;br /&gt;       (lambda ($exn)&lt;br /&gt;         (begin&lt;br /&gt;           (set! *the-exception-handler* $old-hand)&lt;br /&gt;           (%fatbar&lt;br /&gt;            #f&lt;br /&gt;            (%nvcase&lt;br /&gt;             nil&lt;br /&gt;             $exn&lt;br /&gt;             (MyException OtherException)&lt;br /&gt;             (1 1)&lt;br /&gt;             ((let-splat&lt;br /&gt;               ((m9 (%nvget (:MyException 0 1) $exn)))&lt;br /&gt;               (let_subst (value m9) value))&lt;br /&gt;              9)&lt;br /&gt;             (%match-error #f))&lt;br /&gt;            (raise $exn)))))&lt;br /&gt;      (let (($result&lt;br /&gt;             (letrec&lt;br /&gt;                 ((loop&lt;br /&gt;                   (function loop (n) (if (= n 100) (raise (:MyException 12)) (loop (+ n 1))))))&lt;br /&gt;               (loop 0))))&lt;br /&gt;        (begin (set! *the-exception-handler* $old-hand) $result)))))&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-6403279454141380478?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/6403279454141380478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/04/exception-handling-with-defmacro.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6403279454141380478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6403279454141380478'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/04/exception-handling-with-defmacro.html' title='exception handling with defmacro'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-8113894031066248401</id><published>2011-03-23T17:55:00.000-07:00</published><updated>2011-03-23T17:55:46.701-07:00</updated><title type='text'>same-fringe demo</title><content type='html'>This demonstrates how to use generators to solve the same-fringe problem.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, I found a minimalist way of building binary-tree literals using defmacro.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; -*- Mode: Irken -*-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;lib/core.scm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;datatype&lt;/span&gt; &lt;span class="nv"&gt;btree&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:leaf&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;btree/make&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree:node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree:leaf&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;t0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;literal&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;)))))))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;literal&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;t2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;literal&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;btree/inorder&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree:leaf&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree:node&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/inorder&lt;/span&gt; &lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/inorder&lt;/span&gt; &lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;u&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make-generator&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;make-generator&lt;/span&gt;&lt;br /&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/inorder&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;consumer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;maybe:yes&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;      &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;forever&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;consumer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;maybe:no&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;same-fringe&lt;/span&gt; &lt;span class="nv"&gt;t0&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;=&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;g0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make-generator&lt;/span&gt; &lt;span class="nv"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;g1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;btree/make-generator&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="nv"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;m0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;g0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;m1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;g1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;m0&lt;/span&gt; &lt;span class="nv"&gt;m1&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;maybe:yes&lt;/span&gt; &lt;span class="nv"&gt;v0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;maybe:yes&lt;/span&gt; &lt;span class="nv"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;= &lt;/span&gt;&lt;span class="nv"&gt;v0&lt;/span&gt; &lt;span class="nv"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;g0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;g1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-string&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;NOT equal\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;maybe:no&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;maybe:no&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-string&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;equal\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-string&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;unequal size\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;same-fringe&lt;/span&gt; &lt;span class="nv"&gt;t0&lt;/span&gt; &lt;span class="nv"&gt;t1&lt;/span&gt; &lt;span class="nv"&gt;=&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;same-fringe&lt;/span&gt; &lt;span class="nv"&gt;t0&lt;/span&gt; &lt;span class="nv"&gt;t2&lt;/span&gt; &lt;span class="nv"&gt;=&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-8113894031066248401?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/8113894031066248401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/03/same-fringe-demo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8113894031066248401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8113894031066248401'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/03/same-fringe-demo.html' title='same-fringe demo'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3619605814531530595</id><published>2011-03-20T18:09:00.000-07:00</published><updated>2011-03-20T18:09:36.180-07:00</updated><title type='text'>win32 binary</title><content type='html'>I've tried to make the bootstrapping script work on win32, and I think for the most part I've succeeded. &amp;nbsp;There are issues with mac-specific flags making it into the bootstrap file that I still need to work out.&lt;br /&gt;&lt;br /&gt;I used mingw, but I suspect other gcc binaries will work, too. &amp;nbsp;A &lt;a href="http://dark.nightmare.com/rushing/irken/irken.110320.win32-exe.zip"&gt;32-bit executable is now available&lt;/a&gt;, which may ease the bootstrapping process for some.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3619605814531530595?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3619605814531530595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/03/win32-binary.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3619605814531530595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3619605814531530595'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/03/win32-binary.html' title='win32 binary'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-2526526835344439743</id><published>2011-03-17T18:58:00.000-07:00</published><updated>2011-03-17T18:58:48.762-07:00</updated><title type='text'>description of the compiler and runtime</title><content type='html'>I've started on a &lt;a href="http://dark.nightmare.com/rushing/irken/irken/self/HACKING.txt"&gt;'HACKING.txt'&lt;/a&gt; document describing the compiler and runtime.&lt;br /&gt;It should be enough to get folks started on understanding the source.&lt;br /&gt;Feedback appreciated!&lt;br /&gt;&lt;br /&gt;-Sam&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-2526526835344439743?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/2526526835344439743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/03/description-of-compiler-and-runtime.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2526526835344439743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2526526835344439743'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/03/description-of-compiler-and-runtime.html' title='description of the compiler and runtime'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-4795253876545342913</id><published>2011-03-17T16:15:00.000-07:00</published><updated>2011-03-17T16:15:16.650-07:00</updated><title type='text'>self-hosted distribution</title><content type='html'>I've finally put together a 'real' self-hosted &lt;a href="http://dark.nightmare.com/rushing/irken/irken.110317.tar.gz"&gt;distribution&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The tarball is a little bigger - even though I removed all the python code. &amp;nbsp;The reason is that I have to distribute a pre-compiled version of self/compile.c so that the compiler can be bootstrapped.&lt;br /&gt;&lt;br /&gt;Enjoy, and feedback appreciated.&lt;br /&gt;&lt;br /&gt;Here's the text of the README:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;This is the initial release of the self-hosted compiler.&lt;br /&gt;&lt;br /&gt;It's still in a very unpolished state, but you can use it to bootstrap itself.&lt;br /&gt;&lt;br /&gt;Just run the script "util/bootstrap.py":&lt;br /&gt;&lt;br /&gt;$ python util/bootstrap.py&lt;br /&gt;&lt;br /&gt;Which does the following:&lt;br /&gt;1) run gcc on the distributed version of self/compile.c&lt;br /&gt;2) this binary will be used to recompile the compiler.&lt;br /&gt;3) that binary will recompile the compiler again.&lt;br /&gt;4) the output from steps 2 and 3 are compared, they should be identical.&lt;br /&gt;&lt;br /&gt;If you're happy with the resulting compiler, you can compile an optimized&lt;br /&gt;version of self/compile.c, but be warned - you'll need a lot of memory and&lt;br /&gt;a lot of time.&lt;br /&gt;&lt;br /&gt;I am using dragonegg for optimized builds, and that seems to take about a GB&lt;br /&gt;of memory, and 18 minutes to build.  It's important to use '-O2', not '-O',&lt;br /&gt;because '-O' takes 53GB of memory and hours to compile.&lt;br /&gt;&lt;br /&gt;Very little documentation exists yet, try 'lang.html' for a brief tutorial.&lt;br /&gt;The best way to get familiar with the language is to read the source code in&lt;br /&gt;the 'self' directory, and browse over the files in "tests".&lt;br /&gt;&lt;br /&gt;-Sam&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-4795253876545342913?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/4795253876545342913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/03/self-hosted-distribution.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4795253876545342913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4795253876545342913'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/03/self-hosted-distribution.html' title='self-hosted distribution'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-553650999839382222</id><published>2011-03-09T15:03:00.000-08:00</published><updated>2011-03-09T15:03:28.313-08:00</updated><title type='text'>C compiler issues</title><content type='html'>As I came closer to completing the Irken implementation, I noticed that my edit-compile cycle was taking longer and longer. &amp;nbsp;And by that, I don't mean a linear change. &amp;nbsp;At some point a threshold was crossed, such that compiling an optimized binary could take nearly an hour with dragonegg, and much longer with gcc, consuming over 17G of memory while at it!&lt;br /&gt;&lt;br /&gt;After doing some tests, I've identified at least one of the causes: my &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;varref&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;varset&lt;/span&gt; functions.&lt;br /&gt;&lt;br /&gt;A couple of years ago, the compiler output for a varref insn looked like this:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;r0 = lenv[1][1][1][0];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Where the variable we are referencing is 3 levels up and at the 0 index. &amp;nbsp;(i.e., a De Bruijn index of (3,0)).&lt;br /&gt;&lt;br /&gt;I noticed that I could write an inline lexical function, varref(), that did this with a loop:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;r0 = varref (3, 0);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;... which is much cleaner. &amp;nbsp;With -O, gcc, llvm, and dragonegg were all unrolling the constant loop and creating code that was identical to the first version.&lt;br /&gt;&lt;br /&gt;I didn't notice the cost of this convenient feature until my program size got large enough... the compiler sources, when using the inline functions, take 5X as long to compile -O as the first version.&lt;br /&gt;&lt;br /&gt;Also, a 'platform' note: I work on OS X, where the stock compiler is still /usr/bin/gcc. &amp;nbsp;I did some timings for a non-optimized build and discovered that the stock gcc is over twice as fast as either my hand-built gcc-4.5.0, or dragonegg. &amp;nbsp;So for quick edit-compile cycles, I switched back to the stock version. &amp;nbsp;Though it'd be nice to know why the version from Apple is so much faster...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-553650999839382222?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/553650999839382222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/03/c-compiler-issues.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/553650999839382222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/553650999839382222'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/03/c-compiler-issues.html' title='C compiler issues'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-6238057117136797202</id><published>2011-03-09T14:50:00.000-08:00</published><updated>2011-03-09T14:50:41.716-08:00</updated><title type='text'>Self-hosted!</title><content type='html'>[assumed skynet joke here]&lt;br /&gt;&lt;br /&gt;A few days ago, after many weeks of frenetic work, the new self-hosted Irken compiled itself. &amp;nbsp;There's still a lot of work to do, but this major milestone has been reached. &amp;nbsp;The compiler passes the stage1==stage2 test, and I'm now concentrating on various features still missing compared to the python compiler. &amp;nbsp;Also, the edit-compile cycle is still pretty slow, because both the compiler and gcc are slower than need be. &amp;nbsp;Once I have these issues solved and some rudimentary error reporting (the current error reporting might be described as medieval) I'll make an official release.&lt;br /&gt;&lt;br /&gt;I'm also thinking about how to best re-package the system, considering orphaning the python development branch, and starting a whole new repository for the self-hosted system.&lt;br /&gt;&lt;br /&gt;In the meanwhile, if there's anyone out there that would just like to see it compile itself, I rolled a &lt;a href="http://dark.nightmare.com/rushing/irken/irken-self.tar.gz"&gt;demo tarball&lt;/a&gt; up. &amp;nbsp;Enjoy, and feedback is much appreciated!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-6238057117136797202?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/6238057117136797202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/03/self-hosted.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6238057117136797202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6238057117136797202'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/03/self-hosted.html' title='Self-hosted!'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-6487784682018704010</id><published>2011-02-14T17:20:00.000-08:00</published><updated>2011-02-14T17:20:04.510-08:00</updated><title type='text'>progress on self-hosting</title><content type='html'>Today the self-hosted Irken compiled its first complete program, all the way through substituting into the header template file, and compiling via gcc.  A nice feeling.&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; -*- Mode: Irken -*-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;datatype&lt;/span&gt; &lt;span class="nv"&gt;list&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:cons&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list &lt;/span&gt;&lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;list&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list &lt;/span&gt;&lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;%%cexp&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;%0+%1&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;length &lt;/span&gt;&lt;span class="nv"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;length &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I also finally got around to checking in the changes from the last couple of weeks, too much slacking off there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-6487784682018704010?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/6487784682018704010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/02/progress-on-self-hosting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6487784682018704010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6487784682018704010'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/02/progress-on-self-hosting.html' title='progress on self-hosting'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-6405830819534300316</id><published>2011-02-02T21:22:00.000-08:00</published><updated>2011-02-02T21:22:50.149-08:00</updated><title type='text'>Y combinator in Irken</title><content type='html'>The second version requires recursive types.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; -*- Mode: Irken -*-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; See http://en.wikipedia.org/wiki/Fixed_point_combinator&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;"lib/core.scm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Y&lt;/span&gt; &lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Y&lt;/span&gt; &lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;factabs&lt;/span&gt; &lt;span class="nv"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;= &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="mi"&gt;1&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;* &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fact&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;- &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;Y&lt;/span&gt; &lt;span class="nv"&gt;factabs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; and http://caml.inria.fr/pub/docs/u3-ocaml/ocaml-ml.html#toc5&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; let fix f' = let g f x = f' (f f) x in (g g);;&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; let fact = fix fact' in fact 5;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Y2&lt;/span&gt; &lt;span class="nv"&gt;f1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; the '^' prefix tells the compiler not to inline this function&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;;  which in this particular case would never terminate...&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;^g&lt;/span&gt; &lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;f1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;^g&lt;/span&gt; &lt;span class="nv"&gt;^g&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fact1&lt;/span&gt; &lt;span class="nv"&gt;fact&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;= &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="mi"&gt;1&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;* &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fact&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;- &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;Y2&lt;/span&gt; &lt;span class="nv"&gt;fact1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The function ^g has type &lt;pre&gt;μ(A, (A-&gt;b))-&gt;(c-&gt;d)&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-6405830819534300316?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/6405830819534300316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/02/y-combinator-in-irken.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6405830819534300316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6405830819534300316'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/02/y-combinator-in-irken.html' title='Y combinator in Irken'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-4083067581479952268</id><published>2011-02-02T17:31:00.000-08:00</published><updated>2011-02-02T17:31:00.406-08:00</updated><title type='text'>recursive types, unification, sharing</title><content type='html'>I'm having trouble with recursive types in my type reconstruction (type inference) algorithm, some kind of combinatorial explosion. &amp;nbsp;I think there are multiple triggers for this: at each call to unify(), I'm running a complete apply-subst(), rather than a level at a time. &amp;nbsp;For the massive types generated by my OO code, this means lots of wasted, repeated work.&lt;br /&gt;&lt;br /&gt;But of course there's even more going on. &amp;nbsp;I think my code that detects recursive types is not working as well as it should, and I think the cause is the lack of 'sharing'. &amp;nbsp;Remy/Pottier use a different style of unification, that involves preserving shared elements of types, and I think this where I'm screwing up: because parts of types are being copied, I'm missing links between identical parts of the graph.&lt;br /&gt;&lt;br /&gt;I found a nice presentation from Remy describing "Core ML", that explains this in (accented) English, rather than a relentless flurry of LaTeX: &lt;a href="http://caml.inria.fr/pub/docs/u3-ocaml/index.html"&gt;"Using, Understanding, and Unraveling The OCaml Language: From Practice to Theory and vice versa"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The constraint-oriented solver gave me recursive types for free, (because its output types are naturally graphs), but I'm really hoping to avoid going back to that code, because it's much slower and I frankly don't understand it as well as I'd like. &amp;nbsp;Maybe I can pull out just the multi-equation unification stuff, and get back recursive types.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-4083067581479952268?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/4083067581479952268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/02/recursive-types-unification-sharing.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4083067581479952268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4083067581479952268'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/02/recursive-types-unification-sharing.html' title='recursive types, unification, sharing'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3749805360556712062</id><published>2011-01-31T15:54:00.000-08:00</published><updated>2011-01-31T15:57:26.308-08:00</updated><title type='text'>simple approach to OO and exploding equirecursive types</title><content type='html'>While trying to port the graph algorithms (Kosaraju's algorithm / topological sort) I got to a point where I really wanted some imperative set/map objects, so I combined a 'class' using alists (for map) and lists (for set) with a few 'methods' put into records.&lt;br /&gt;&lt;br /&gt;After playing with it for a while, I found a fairly neat way to do method calls and object layouts:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set-class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="nv"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hd&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;eq? &lt;/span&gt;&lt;span class="nv"&gt;hd&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                         &lt;span class="no"&gt;#t&lt;/span&gt;&lt;br /&gt;                         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt; &lt;span class="nv"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;self::in&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;u&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;in=in&lt;/span&gt; &lt;span class="nv"&gt;add=add&lt;/span&gt; &lt;span class="nv"&gt;get=get&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;o=methods&lt;/span&gt; &lt;span class="nv"&gt;list=l&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;new&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This leads to an efficient object layout very similar to Python's: one slot identifies the object type, the other slots hold instance variables. &amp;nbsp;To support this, I added a reader hack that translates&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(var::method arg0)&lt;/pre&gt;&lt;br /&gt;into&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(var.o.method var arg0)&lt;/pre&gt;&lt;br /&gt;The result is something that I'm pretty sure will act just like Python's duck typing... for example a generic output function may call the 'write' method on an object, and its type will reflect that need: for a write method of a particular signature. &amp;nbsp;Instead of 'o' I'd probably use a slot name like '__methods__'... this suggests standard repr/str interfaces, and the other duck-typed protocols that Python makes such good use of.&lt;br /&gt;&lt;br /&gt;Pretty cool, huh?&lt;br /&gt;&lt;br /&gt;Well, as soon as I tried actually using this code, the inferencer fell to its knees.  I'm not kidding.  It went from a 30 second compile to a 20 &lt;i&gt;minute &lt;/i&gt;compile, eating up over a GB of memory. &amp;nbsp;Hmmmm... looks like my quick-and-easy implementation of μ-types has problems, surprise. &amp;nbsp;I think I was 'asking for it' by calling each method with a 'self' argument... each method call has to unify the object type twice. &amp;nbsp;And storing objects inside of other objects doesn't help, either.&lt;br /&gt;&lt;br /&gt;Back to the textbook. &amp;nbsp;I'm hoping that reading &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.2276"&gt;this paper&lt;/a&gt; again will help.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3749805360556712062?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3749805360556712062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/01/simple-approach-to-oo-and-exploding.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3749805360556712062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3749805360556712062'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/01/simple-approach-to-oo-and-exploding.html' title='simple approach to OO and exploding equirecursive types'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-4628463393174936919</id><published>2011-01-26T19:08:00.000-08:00</published><updated>2011-01-26T19:08:52.400-08:00</updated><title type='text'>self-hosting dilemma</title><content type='html'>I have nearly the whole compiler rewritten in itself. &amp;nbsp;I've saved one of the nastiest bits for last, the inliner. &amp;nbsp;I've been planning on a new design for the inliner - rather than just copying the Python code. &amp;nbsp;So of course, what happens in this late stage? &amp;nbsp;A bug in the inliner!&lt;br /&gt;&lt;br /&gt;The program types correctly if inlining is turned off, but fails if it's turned on. &amp;nbsp;This is a great example of the gains to be had by typing both before and after phases of the compiler - but unfortunately in this case it means I have to fix a bug in some code that I intend to throw away as soon as it works!&lt;br /&gt;&lt;br /&gt;Theoretically I could just turn &lt;i&gt;off&lt;/i&gt; inlining until I'm done, and then write the new inliner in the self-hosted environment - but I can't be absolutely sure that it's not a more complex interaction between the typer and the inliner.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-4628463393174936919?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/4628463393174936919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/01/self-hosting-dilemma.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4628463393174936919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4628463393174936919'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/01/self-hosting-dilemma.html' title='self-hosting dilemma'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3159396491865811120</id><published>2011-01-20T23:15:00.000-08:00</published><updated>2011-01-20T23:15:13.725-08:00</updated><title type='text'>bloated C compilers</title><content type='html'>I've been testing Irken out on my netbook (a Samsung NC10), and discovered a big problem with feeding Irken's output to gcc.&lt;br /&gt;&lt;br /&gt;When I tried to compile the self-hosted Irken with -O, the netbook fell on its knees. &amp;nbsp;After about 15 minutes, I decided to look into it... why hadn't the compile finished yet?&lt;br /&gt;&lt;br /&gt;The input Irken source was about 60kB, which exploded into a 920kB C file. &amp;nbsp;The C output is actually pretty low-level stuff, so it's probably comparable to a 300kB hand-written C file. &amp;nbsp;But let's just call it 1MB and move on...&lt;br /&gt;&lt;br /&gt;The gcc (version 4.4) process had eaten 1.4GB of virtual memory, so it was paging on the netbook.&lt;br /&gt;&lt;br /&gt;That's 1600X the size of the C input file. &amp;nbsp;It's nearly 25,000X the size of the Irken input. &amp;nbsp;Wow.&lt;br /&gt;&lt;br /&gt;So as a test I installed dragonegg and gcc-4.5. &amp;nbsp;Quite a difference. &amp;nbsp;The dragonegg compile held at 143MB for most of the compile, and peaked at around 200MB. &amp;nbsp;Only 226X the size of the C input, and a mere 3400X the size of the Irken input.&lt;br /&gt;&lt;br /&gt;But what's an order of magnitude between friends?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3159396491865811120?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3159396491865811120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/01/bloated-c-compilers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3159396491865811120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3159396491865811120'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/01/bloated-c-compilers.html' title='bloated C compilers'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3218845290314540582</id><published>2011-01-20T15:27:00.000-08:00</published><updated>2011-01-20T15:27:01.562-08:00</updated><title type='text'>The datatype + record idiom</title><content type='html'>One of the difficult decisions when working on a compiler is how to represent nodes. &amp;nbsp;There's a strain between the pure-functional and object-oriented styles that can be really painful. &amp;nbsp;I'm certainly not happy with the way I did it in Irken - a combination of pure-functional class with a bunch of attribute hacks.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While working to solve the same problem in self-hosted Irken, I've come across a pretty good idiom that captures the best of both worlds; giving me exactly the right combination of strong typing, mutability, and flexibility that I need.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The trick is to use a record as the node representation, but inside it put a slot that holds all the strongly-typed metadata that you need. &amp;nbsp;Here's what it looks like so far:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; node type holds metadata related to the node,&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;  but sub-nodes are held with the record.&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;datatype&lt;/span&gt; &lt;span class="nv"&gt;node&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:varref&lt;/span&gt; &lt;span class="nv"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:varset&lt;/span&gt; &lt;span class="nv"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:literal&lt;/span&gt; &lt;span class="nv"&gt;literal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:cexp&lt;/span&gt; &lt;span class="nv"&gt;type&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:nvcase&lt;/span&gt; &lt;span class="nv"&gt;symbol&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list &lt;/span&gt;&lt;span class="nv"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:sequence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:if&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:function&lt;/span&gt; &lt;span class="nv"&gt;symbol&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list &lt;/span&gt;&lt;span class="nv"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;;; name formals&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;node-counter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;make-counter&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; given a list of nodes, add up their sizes (+1)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum-size&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fold&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt; &lt;span class="nv"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt; &lt;span class="nv"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="nv"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;t=t&lt;/span&gt; &lt;span class="nv"&gt;subs=subs&lt;/span&gt; &lt;span class="nv"&gt;s=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum-size&lt;/span&gt; &lt;span class="nv"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;id=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node-counter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;type=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type:base&lt;/span&gt; &lt;span class="ss"&gt;'?&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node/varref&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:varref&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node/varset&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:varset&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;LIST&lt;/span&gt; &lt;span class="nv"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node/literal&lt;/span&gt; &lt;span class="nv"&gt;lit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:literal&lt;/span&gt; &lt;span class="nv"&gt;lit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node/cexp&lt;/span&gt; &lt;span class="nv"&gt;type&lt;/span&gt; &lt;span class="nv"&gt;template&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:cexp&lt;/span&gt; &lt;span class="nv"&gt;type&lt;/span&gt; &lt;span class="nv"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node/sequence&lt;/span&gt; &lt;span class="nv"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:sequence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Note how the node constructor initializes the other slots in the record. &amp;nbsp;The interesting one for me today is the type field. &amp;nbsp; This is later filled in by the typer, succinctly:&lt;/div&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type-of&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt; &lt;span class="nv"&gt;tenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type-of*&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt; &lt;span class="nv"&gt;tenv&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;apply-subst-to-program&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;apply-subst-to-type&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;for-each &lt;/span&gt;&lt;span class="nv"&gt;apply-subst-to-program&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type-program&lt;/span&gt; &lt;span class="nv"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type-of&lt;/span&gt; &lt;span class="nv"&gt;node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;alist/make&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;apply-subst-to-program&lt;/span&gt; &lt;span class="nv"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;We've still preserved the strong typing of nodes, though: here's what a typical node-visiting function looks like:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt; &lt;span class="nv"&gt;tail?&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt; &lt;span class="nv"&gt;lenv&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; override continuation when in tail position&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nv"&gt;tail?&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;k&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cont&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;k/free&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;gen-return&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:literal&lt;/span&gt; &lt;span class="nv"&gt;lit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c-literal&lt;/span&gt; &lt;span class="nv"&gt;lit&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:sequence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;              &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c-sequence&lt;/span&gt; &lt;span class="nv"&gt;tail?&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;subs&lt;/span&gt; &lt;span class="nv"&gt;lenv&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:if&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                    &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c-conditional&lt;/span&gt; &lt;span class="nv"&gt;tail?&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt; &lt;span class="nv"&gt;lenv&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:function&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;formals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c-function&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;formals&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car &lt;/span&gt;&lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;lenv&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:varref&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c-varref&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;lenv&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:varset&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c-varset&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car &lt;/span&gt;&lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;lenv&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:cexp&lt;/span&gt; &lt;span class="nv"&gt;sig&lt;/span&gt; &lt;span class="nv"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c-cexp&lt;/span&gt; &lt;span class="nv"&gt;sig&lt;/span&gt; &lt;span class="nv"&gt;template&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;subs&lt;/span&gt; &lt;span class="nv"&gt;lenv&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;node:call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                  &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c-call&lt;/span&gt; &lt;span class="nv"&gt;tail?&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt; &lt;span class="nv"&gt;lenv&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pp-node&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error1&lt;/span&gt; &lt;span class="s"&gt;"NYI"&lt;/span&gt; &lt;span class="nv"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Note how metadata that's specific to each node type is stored in the datatype (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;exp.t&lt;/span&gt;), but generic info (like the list of sub-nodes, or the size) is stored in the record.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3218845290314540582?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3218845290314540582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/01/datatype-record-idiom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3218845290314540582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3218845290314540582'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/01/datatype-record-idiom.html' title='The datatype + record idiom'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-8885630937360087629</id><published>2011-01-18T17:34:00.001-08:00</published><updated>2011-01-18T17:35:21.777-08:00</updated><title type='text'>making the match compiler smarter</title><content type='html'>The match compiler developed a little problem. &amp;nbsp;It's amazing that it didn't show up earlier. &amp;nbsp;As described in chapter 5 of Peyton-Jones' book, "&lt;a href="http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/"&gt;The Implementation of Functional Programming Languages"&lt;/a&gt;, certain 'obvious' or 'optimized' pattern matches actually compile to worse code.&lt;br /&gt;&lt;br /&gt;The following function is from the book (pg 88), and is similar to an implementation of map2.&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;demo&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nv"&gt;ys&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:A&lt;/span&gt; &lt;span class="nv"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;xs&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:B&lt;/span&gt; &lt;span class="nv"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;y&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:C&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;xs&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="nv"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The second match clause will actually compile more efficiently if you use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(x . xs)&lt;/span&gt; rather than a variable, because the match compiler knows in this case you're matching a cons cell.  (it avoids the 'mixture rule' and uses only the 'constructor rule').&lt;br /&gt;&lt;br /&gt;Regardless of this optimization, I ran into a more significant issue. &amp;nbsp;If I use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;xs&lt;/span&gt;, I get an 'incomplete match' error, because the code generated for this match has to examine the first list twice - in the first test it covers only the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;nil&lt;/span&gt; case. &amp;nbsp;In the second test, it covers the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;cons&lt;/span&gt; case, but has an 'else' clause that generates a match error.&lt;br /&gt;&lt;br /&gt;Here's what the node tree looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;290 L    primapp [33] ('%%fatbar', None) ? &lt;br /&gt;262 L      nvcase [5] ('list', ['nil']) ? &lt;br /&gt;258 L        varref [1] m0_7_i0 ? &lt;br /&gt;260 L        primapp [2] ('%vcon/A/1', None) ? &lt;br /&gt;259 L          varref [1] m1_8_i1 ? &lt;br /&gt;261 L        primapp [1] ('%%fail', None) ? &lt;br /&gt;289 L      primapp [27] ('%%fatbar', None) ? &lt;br /&gt;267 L        nvcase [5] ('list', ['nil']) ? &lt;br /&gt;263 L          varref [1] m1_8_i1 ? &lt;br /&gt;265 L          primapp [2] ('%vcon/B/1', None) ? &lt;br /&gt;264 L            varref [1] m0_7_i0 ? &lt;br /&gt;266 L          primapp [1] ('%%fail', None) ? &lt;br /&gt;288 L        nvcase [21] ('list', ['cons']) ? &lt;br /&gt;268 L          varref [1] m0_7_i0 ? &lt;br /&gt;286 L          let_splat [18] [{m2_9_i0}, {m3_10_i0}] ? &lt;br /&gt;270 L            primapp [2] ('%nvget/list/cons/0', None) ? &lt;br /&gt;269 L              varref [1] m0_7_i0 ? &lt;br /&gt;272 L            primapp [2] ('%nvget/list/cons/1', None) ? &lt;br /&gt;271 L              varref [1] m0_7_i0 ? &lt;br /&gt;285 L            nvcase [13] ('list', ['cons']) ? &lt;br /&gt;273 L              varref [1] m1_8_i1 ? &lt;br /&gt;283 L              let_splat [10] [{m4_11_i0}, {m5_12_i0}] ? &lt;br /&gt;275 L                primapp [2] ('%nvget/list/cons/0', None) ? &lt;br /&gt;274 L                  varref [1] m1_8_i1 ? &lt;br /&gt;277 L                primapp [2] ('%nvget/list/cons/1', None) ? &lt;br /&gt;276 L                  varref [1] m1_8_i1 ? &lt;br /&gt;282 L                primapp [5] ('%vcon/C/4', None) ? &lt;br /&gt;278 L                  varref [1] m2_9_i0 ? &lt;br /&gt;279 L                  varref [1] m3_10_i0 ? &lt;br /&gt;280 L                  varref [1] m4_11_i0 ? &lt;br /&gt;281 L                  varref [1] m5_12_i0 ? &lt;br /&gt;284 L              primapp [1] ('%%match-error', None) ? &lt;br /&gt;287 L          primapp [1] ('%%match-error', None) ? &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;...and in a pseudo-python:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;  &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;  &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;      &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;br /&gt;  &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The problem is that the match is actually exhaustive, because the nil case was examined already. &amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;%%match-error&lt;/span&gt; in Irken is actually a kind of sentinel, the back end doesn't know how to compile it, so you can't actually compile code that's not exhaustive.&lt;br /&gt;&lt;br /&gt;To fix this, I added an extra pass to the analysis phase that builds environments of 'already tested alternatives' for each nvcase variable.  This actually killed two birds with one stone.  In many cases, the innermost nvcase test is completely unnecessary - for this example, we've already tested for nil, and actually testing for a cons is redundant.  In this case we simply remove the nvcase test (and the erroneous match-error), and return the body.&lt;br /&gt;&lt;br /&gt;The code then generated for map is closer to what a human might write:&lt;br /&gt;&lt;br /&gt;pseudo-python:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;  &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;  &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;RTL:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;0 = constructed [] 1&lt;br /&gt;   1 = constructed [] 0&lt;br /&gt;   2 = fatbar 'fatbar_0' []&lt;br /&gt;       2 = move [0, None] 'm0_7_i0'&lt;br /&gt;       2 = nvcase 'list' [2]&lt;br /&gt;           2 = move [1, None] 'm1_8_i1'&lt;br /&gt;           2 = primop [2] ('%make-tuple', 'A', 0)&lt;br /&gt;               return [2] None&lt;br /&gt;               fail [] ('fatbar_0', 0)&lt;br /&gt;           return [2] None&lt;br /&gt;       2 = fatbar 'fatbar_1' []&lt;br /&gt;           2 = move [1, None] 'm1_8_i1'&lt;br /&gt;           2 = nvcase 'list' [2]&lt;br /&gt;               2 = move [0, None] 'm0_7_i0'&lt;br /&gt;               2 = primop [2] ('%make-tuple', 'B', 1)&lt;br /&gt;                   return [2] None&lt;br /&gt;                   fail [] ('fatbar_1', 0)&lt;br /&gt;               return [2] None&lt;br /&gt;           2 = move [0, None] 'm0_7_i0'&lt;br /&gt;           2 = primop [2] ('%vget', '0')&lt;br /&gt;           3 = move [0, None] 'm0_7_i0'&lt;br /&gt;           3 = primop [3] ('%vget', '1')&lt;br /&gt;           4 = move [1, None] 'm1_8_i1'&lt;br /&gt;           4 = primop [4] ('%vget', '0')&lt;br /&gt;           5 = move [1, None] 'm1_8_i1'&lt;br /&gt;           5 = primop [5] ('%vget', '1')&lt;br /&gt;           6 = move [2, None] 'm2_9_i0'&lt;br /&gt;           7 = move [3, None] 'm3_10_i0'&lt;br /&gt;           8 = move [4, None] 'm4_11_i0'&lt;br /&gt;           9 = move [5, None] 'm5_12_i0'&lt;br /&gt;           6 = primop [6, 7, 8, 9] ('%make-tuple', 'C', 2)&lt;br /&gt;               return [6] None&lt;br /&gt;           return [2] None&lt;br /&gt;       return [2] None&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-8885630937360087629?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/8885630937360087629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/01/making-match-compiler-smarter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8885630937360087629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8885630937360087629'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/01/making-match-compiler-smarter.html' title='making the match compiler smarter'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-5820379692463270116</id><published>2011-01-14T16:52:00.000-08:00</published><updated>2011-01-14T16:52:22.675-08:00</updated><title type='text'>progress on self-hosting</title><content type='html'>Making excellent progress on self-hosting. &amp;nbsp;Today the baby irken compiler spat up its first real code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;beast:irken rushing$ self/backend&lt;br /&gt;&lt;br /&gt;-- reader --&lt;br /&gt;(((lambda (x y) x) 3 4))&lt;br /&gt;&lt;br /&gt;-- macros --&lt;br /&gt;((function lambda (x y) x) 3 4)&lt;br /&gt;&lt;br /&gt;-- node tree --&lt;br /&gt;&lt;br /&gt;5 call&lt;br /&gt;  2 function lambda (x y)&lt;br /&gt;    1 varref x&lt;br /&gt;  1 literal {u1 3}&lt;br /&gt;  1 literal {u1 4}&lt;br /&gt;&lt;br /&gt;-- RTL --&lt;br /&gt;&lt;br /&gt;0 env 2 &lt;br /&gt;1 lit {u1 3}&lt;br /&gt;- stor 1 1 0 0 &lt;br /&gt;1 lit {u1 4}&lt;br /&gt;0 stor 1 1 0 1 &lt;br /&gt;1 close lambda&lt;br /&gt;  0 ref 0 0 &lt;br /&gt;  - ret 0&lt;br /&gt;0 tail 1 0 &lt;br /&gt;- ret 0&lt;br /&gt;&lt;br /&gt;-- C output --&lt;br /&gt;  r0 = allocate (TC_TUPLE, 3);&lt;br /&gt;  r1 = (object *) 7;&lt;br /&gt;  r0[2] = r1;&lt;br /&gt;  r1 = (object *) 9;&lt;br /&gt;  r0[3] = r1;&lt;br /&gt;  // def lambda&lt;br /&gt;  goto L0;&lt;br /&gt;  FUN_lambda:&lt;br /&gt;    r0 = varref (0, 0);&lt;br /&gt;    PXLL_RETURN(0);&lt;br /&gt;  L0:&lt;br /&gt;  r1 = allocate (TC_CLOSURE, 2);&lt;br /&gt;  r1[1] = &amp;&amp;FUN_lambda; r1 = lenv;&lt;br /&gt;  r0[1] = r1[2]; lenv = r0; goto *r1;&lt;br /&gt;  PXLL_RETURN(0);&lt;br /&gt;#u&lt;br /&gt;{total ticks: 1870544 gc ticks: 0}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-5820379692463270116?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/5820379692463270116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/01/progress-on-self-hosting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/5820379692463270116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/5820379692463270116'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/01/progress-on-self-hosting.html' title='progress on self-hosting'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-895155334549260728</id><published>2011-01-13T17:34:00.000-08:00</published><updated>2011-01-13T17:34:38.789-08:00</updated><title type='text'>format macro</title><content type='html'>How cool is this?&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; -*- Mode: Irken -*-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;"lib/core.scm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;"lib/pair.scm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;"lib/string.scm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;format&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                       &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;&amp;lt;int&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int-&amp;gt;string&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;&amp;lt;char&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;char-&amp;gt;string&lt;/span&gt; &lt;span class="nv"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;&amp;lt;bool&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bool-&amp;gt;string&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;&amp;lt;string&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;s&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-string&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;string-join&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="s"&gt;"testing"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bool&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;char&lt;/span&gt; &lt;span class="sc"&gt;#\A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre&gt;beast:irken rushing$ tests/t_format&lt;br /&gt;testing 1 #t A &lt;br /&gt;#u&lt;br /&gt;{total ticks: 154666 gc ticks: 0}&lt;/pre&gt;&lt;br /&gt;Let me explain what's going on here. &amp;nbsp;First, this is a macro definition. &amp;nbsp;Macros are specified using a pattern language. &amp;nbsp;To the left of each arrow is an input pattern - on the right is how that input will be transformed; &lt;i&gt;before&lt;/i&gt; the code gets to the compiler &amp;nbsp;(in other words, textual substitution).&lt;br /&gt;&lt;br /&gt;Symbols surrounded by angle brackets are keywords - i.e., constant symbols.  This is to distinguish them from variables. Every other name in the input pattern is bound to a variable, which can be used in the output form.&lt;br /&gt;&lt;br /&gt;So the final line is transformed into this expression:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-string&lt;/span&gt;&lt;br /&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;string-join&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;testing&amp;quot;&lt;/span&gt;&lt;br /&gt;             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int-&amp;gt;string&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bool-&amp;gt;string&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                                   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;char-&amp;gt;string&lt;/span&gt; &lt;span class="sc"&gt;#\A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                                              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;\n&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;br /&gt;  &lt;span class="s"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This is actually a very simple macro, the patterns could be much more sophisticated, with embedded list structures and other keywords.  But it creates the illusion of a variable-arity, variably-typed format function in a language that is strictly, statically typed and does not support variable arity!  And of course other macros may be invoked.  I'm sure I'll be expanding it as I work more on Irken's self-hosted back end.&lt;br /&gt;&lt;br /&gt;Usually string formatting is an ugly part of any language - one of the classic problems with C is that the format language is ill-specified and dangerous. &amp;nbsp;Only recently have compilers become smart enough to even do rudimentary checking...&lt;br /&gt;&lt;br /&gt;I'm only just beginning to see what's possible with this macro system. &amp;nbsp;I think the pattern matching syntax combines very nicely with the general pattern matching in the language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-895155334549260728?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/895155334549260728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/01/format-macro.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/895155334549260728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/895155334549260728'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/01/format-macro.html' title='format macro'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-8200525240827839249</id><published>2011-01-08T16:47:00.000-08:00</published><updated>2011-01-08T16:47:13.053-08:00</updated><title type='text'>record type declarations</title><content type='html'>I finally needed to declare record types in some complex data structures, so I spent about 10 minutes extending the type parser to support it.  The syntax is IMHO obvious.&lt;br /&gt;&lt;br /&gt;I was pleasantly surprised to see how easy it was to add this feature, and all the testing went quickly and as expected.  I think this is all a 'side-effect' (pun intended) of a relatively complete and sane type system.&lt;br /&gt;&lt;br /&gt;Here's what the syntax looks like:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; -*- Mode: Irken -*-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;lib/core.scm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;lib/pair.scm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;lib/string.scm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; declare a new datatype &amp;lt;thing&amp;gt; with only one alternative &amp;lt;t&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   which consists of an open record type... i.e., a record that&lt;/span&gt;&lt;br /&gt;&lt;span class="c1"&gt;;;   may contain other unknown fields.&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;datatype&lt;/span&gt; &lt;span class="nv"&gt;thing&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;x=int&lt;/span&gt; &lt;span class="nv"&gt;y=char&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;thing:t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;x=3&lt;/span&gt; &lt;span class="nv"&gt;y=&lt;/span&gt;&lt;span class="sc"&gt;#\b&lt;/span&gt; &lt;span class="nv"&gt;z=9&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;thing:t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;x=4&lt;/span&gt; &lt;span class="nv"&gt;y=&lt;/span&gt;&lt;span class="sc"&gt;#\c&lt;/span&gt; &lt;span class="nv"&gt;z=&lt;/span&gt;&lt;span class="sc"&gt;#\a&lt;/span&gt; &lt;span class="nv"&gt;a=&lt;/span&gt;&lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="nv"&gt;b=&lt;/span&gt;&lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; make sure it still works with *no* extra fields&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;thing:t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;x=4&lt;/span&gt; &lt;span class="nv"&gt;y=&lt;/span&gt;&lt;span class="sc"&gt;#\a&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-8200525240827839249?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/8200525240827839249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2011/01/record-type-declarations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8200525240827839249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8200525240827839249'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2011/01/record-type-declarations.html' title='record type declarations'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3683109634082966426</id><published>2010-12-19T19:00:00.000-08:00</published><updated>2010-12-19T19:00:46.756-08:00</updated><title type='text'>self-hosting</title><content type='html'>Just a quick note to explain the relative silence here recently.  I've started rewriting Irken in itself, originally just as an exercise, but now with a little enthusiasm.  Unfortunately there's the danger of &lt;a href="http://en.wikipedia.org/wiki/Second-system_effect"&gt;second-system syndrome&lt;/a&gt;, which I'm trying to keep under control by focusing on eliminating design flaws, and &lt;i&gt;not&lt;/i&gt; introducing new features.&lt;br /&gt;&lt;br /&gt;Currently, I have the reader, the transformer, and the macro packages written.  Next up are the pattern match compiler and the typing engine.  Should be pretty smooth sailing after that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3683109634082966426?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3683109634082966426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/12/self-hosting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3683109634082966426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3683109634082966426'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/12/self-hosting.html' title='self-hosting'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-6958554890600661557</id><published>2010-12-19T18:52:00.000-08:00</published><updated>2010-12-19T18:52:43.946-08:00</updated><title type='text'>how about a pattern-matching version of "let loop"?</title><content type='html'>I tend to use the "named let" idiom a lot, to me it's the most general form of looping construct, and is more readable than artificial constructs like 'do'.&lt;br /&gt;&lt;br /&gt;I've begun to pine for a pattern-matching version of that construct, though.  Not sure how well it would fly, but it would nicely generalize pattern matching.  The reason I like 'named let' is because it lets you compactly introduce a recursive function while keeping the initial arguments in a place that makes the whole construct easier to understand.&lt;br /&gt;&lt;br /&gt;Here's what the 'length' function looks like right now:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;length &lt;/span&gt;&lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;fun&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;        &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;acc&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hd&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fun&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;And here's what it might look like with a pattern-matching 'named let' variant:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;length &lt;/span&gt;&lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="nv"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;        &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;acc&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hd&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Visually I think it should be easy to distinguish from a normal let by the lack of extra levels of parens in the 'binding' spot... and this is in addition to the obvious -&amp;gt; symbols.&lt;br /&gt;&lt;br /&gt;One bad side-effect of this is that &lt;code&gt;let&lt;/code&gt; could no longer be done with &lt;code&gt;defmacro&lt;/code&gt; (as in &lt;code&gt;lib/derived.scm&lt;/code&gt;), and would require a special hack in the parser...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-6958554890600661557?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/6958554890600661557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/12/how-about-pattern-matching-version-of.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6958554890600661557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6958554890600661557'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/12/how-about-pattern-matching-version-of.html' title='how about a pattern-matching version of &quot;let loop&quot;?'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-5286292388811308637</id><published>2010-11-03T17:06:00.000-07:00</published><updated>2010-11-03T17:06:47.877-07:00</updated><title type='text'>proper datatypes for bool and symbol</title><content type='html'>I had previously been tagging user-immediates in a way that wasted tag-space and didn't match up with the obvious implementation used for things like bools and chars.&lt;br /&gt;&lt;br /&gt;This is now fixed.  A nice side-effect of this change is that matches against bools are now detected as complete or incomplete.&lt;br /&gt;&lt;br /&gt;Incomplete matches are now detected earlier in the compiler, in a way that makes it easier to figure out the code that actually triggered it.&lt;br /&gt;&lt;br /&gt;I've also, for fun, started writing the lisp reader in irken itself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-5286292388811308637?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/5286292388811308637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/11/proper-datatypes-for-bool-and-symbol.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/5286292388811308637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/5286292388811308637'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/11/proper-datatypes-for-bool-and-symbol.html' title='proper datatypes for bool and symbol'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-7878621489031002220</id><published>2010-10-26T16:04:00.000-07:00</published><updated>2010-10-26T16:04:34.639-07:00</updated><title type='text'>equirecursive types</title><content type='html'>Just a quick status update.  As my 'user' program has become larger, the type solver has begun to slow down horribly.  I'm on the wrong end of some horrible O(x) where x is probably n^4 or worse.&lt;br /&gt;&lt;br /&gt;So I decided to try an experiment, going back to the classic algorithm W.  This only took a couple of days!  However.  One thing I didn't realize I was getting for 'free' from the constraint-based solver was recursive types.  Now I'm forced to actually understand the concept.&lt;br /&gt;&lt;br /&gt;I see two potential outcomes: 1) I grok recursive types well enough to fix my unifier, and the compiler gets much much faster; or 2) I rewrite the constraint solver to be more efficient.  It's possible that I understand things well enough now to be able to do so.&lt;br /&gt;&lt;br /&gt;If anyone out there can explain how to do unification with equirecursive types, I'd love to have the help!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-7878621489031002220?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/7878621489031002220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/10/equirecursive-types.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7878621489031002220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7878621489031002220'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/10/equirecursive-types.html' title='equirecursive types'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-1519235185068247254</id><published>2010-09-19T17:01:00.000-07:00</published><updated>2010-09-19T17:01:52.184-07:00</updated><title type='text'>first draft of a language tutorial</title><content type='html'>I've slapped together a tutorial/language document, I'd love to get some feedback on it.  In order to save time and space, it is aimed at programmers that are already familiar with Lisp/Scheme; mostly it introduces the MLish concepts and unique quirks of Irken.&lt;br /&gt;&lt;br /&gt;&lt;a href=" http://dark.nightmare.com/rushing/irken/irken/lang.html"&gt;The Irken Language.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Feedback of any kind would be much appreciated!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-1519235185068247254?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/1519235185068247254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/09/first-draft-of-language-tutorial.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/1519235185068247254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/1519235185068247254'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/09/first-draft-of-language-tutorial.html' title='first draft of a language tutorial'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-815033456909145554</id><published>2010-07-26T13:52:00.000-07:00</published><updated>2010-07-26T13:56:01.157-07:00</updated><title type='text'>new 'defmacro'</title><content type='html'>Here's a taste of what the new macros look like.  It's just like syntax-rules, but without the redundant 'define-syntax'/'syntax-rules' layers.  I've also lost a layer of parens by using something closer to the Irken pattern-matching syntax.&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;;; -*- Mode: Irken -*-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; derived expressions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;and&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                 &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="no"&gt;#t&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;and &lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;and &lt;/span&gt;&lt;span class="nv"&gt;test1&lt;/span&gt; &lt;span class="nv"&gt;test2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nv"&gt;test1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;and &lt;/span&gt;&lt;span class="nv"&gt;test2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c1"&gt;;; *not* the same as a Scheme &amp;lt;or&amp;gt;, this returns a boolean.&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;or&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;or&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="no"&gt;#f&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;or &lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;or &lt;/span&gt;&lt;span class="nv"&gt;test1&lt;/span&gt; &lt;span class="nv"&gt;test2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nv"&gt;test1&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;or &lt;/span&gt;&lt;span class="nv"&gt;test2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defmacro&lt;/span&gt; &lt;span class="nv"&gt;let&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; normal &amp;lt;let&amp;gt; here, we just rename it to our core&lt;/span&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; binding construct, &amp;lt;let_splat&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="nv"&gt;body2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;let_splat&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="nv"&gt;body2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="c1"&gt;;; named let&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="nv"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="nv"&gt;body2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="k"&gt;-&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;letrec &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;body1&lt;/span&gt; &lt;span class="nv"&gt;body2&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;tag&lt;/span&gt; &lt;span class="nv"&gt;val&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-815033456909145554?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/815033456909145554/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/07/new-defmacro.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/815033456909145554'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/815033456909145554'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/07/new-defmacro.html' title='new &apos;defmacro&apos;'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-6297891412595661000</id><published>2010-07-21T13:21:00.000-07:00</published><updated>2010-07-21T13:57:59.855-07:00</updated><title type='text'>The Macro Wars</title><content type='html'>Back in the 80's I worked mostly in Common Lisp, and therefore learned the relatively simple 'defmacro'.  Over the years of exposure to Scheme, I was often curious about the more sophisticated macro systems (I think first described in R4RS, but rarely implemented).  Most Scheme systems still used a backquote-style macro facility.&lt;br /&gt;&lt;br /&gt;I never tried the 'hygienic' macro systems, partly because I didn't really care about the issue they're trying to solve, but mostly because they're just dauntingly complex.  One reason is that people &lt;i&gt;still&lt;/i&gt; seem to have not settled on one standard system.  Maybe R6RS has?&lt;br /&gt;&lt;br /&gt;If you want a taste, look over the PLT/Racket documentation &lt;a href="http://docs.racket-lang.org/guide/macros.html"&gt;here&lt;/a&gt; and &lt;a href="http://docs.racket-lang.org/reference/Macros.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://community.schemewiki.org/?hygiene-versus-gensym"&gt;This discussion covers the strain between the two camps pretty well&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've not completely decided yet whether I'm going to add macros to Irken.  I'm coding something up now to try out.  If it's a win, it stays in.  But I'm leaning toward something like 'syntax-rules', with a simplified syntax.  Pattern-matching will be a natural fit with the rest of Irken.  [Why does scheme require both 'define-syntax' and 'syntax-rules' as two separate forms, repeating the name of the macro yet again?]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-6297891412595661000?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/6297891412595661000/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/07/macro-wars.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6297891412595661000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6297891412595661000'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/07/macro-wars.html' title='The Macro Wars'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3667301205849421080</id><published>2010-06-29T20:00:00.000-07:00</published><updated>2010-06-29T20:00:44.028-07:00</updated><title type='text'>The Evil Value Restriction and Lisp Macros</title><content type='html'>One of the more annoying features of the HM type system is how it interacts poorly with imperative features.  Every few weeks I completely forget these limitations and try to do something that in any other language would be completely natural, and get bit again.&lt;br /&gt;&lt;br /&gt;The heart of the problem is exposed by the idea of using a mutable list datatype.  When you create an empty list ('nil'), it has type "list 'a" - in other words, 'nil' can take on any type you like.&lt;br /&gt;&lt;br /&gt;In Irken, as long as you stick with the datatype constructors themselves, this works.  You can create lists of different types right next to each other and have all the type safety you like.&lt;br /&gt;&lt;br /&gt;But as soon as you try to wrap that up - for example, into a stack ADT - you hit the value restriction.&lt;br /&gt;&lt;br /&gt;In OCaml, this problem manifests as 'weak' type variables - e.g., " list '_a ", which just records the fact that '_a is currently unknown, and will instantiate to only one type.&lt;br /&gt;&lt;br /&gt;One reason this keeps biting me unexpectedly is that I've changed the compiler to (by default) only type the program &lt;i&gt;after&lt;/i&gt; inlining.  This make copies of smaller polymorphic functions/interfaces, thereby side-stepping the problem with the value restriction - instead of making one copy of a function that works at multiple types, inlining causes that code to be duplicated at each site.  I only notice VR problems when I force it to type twice, or turn off inlining.&lt;br /&gt;&lt;br /&gt;I'm wondering: as a practical matter, maybe I should just embrace this.  I'm not qualified to invent a new type system that's going to fix all this.  But a 'stupid' substitution system (like C++ templates or lisp macros) makes the problem go away, and that's good enough for me.&lt;br /&gt;&lt;br /&gt;AFAIK none of the ML's have a macro system.  Is this perhaps a side-effect of ML fans' universal hatred of Lisp?&lt;br /&gt;&lt;br /&gt;How might macros interact with HM?  For example, could we design a 'polymorphic class' that would essentially copy the code at each use site?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3667301205849421080?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3667301205849421080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/06/evil-value-restriction-and-lisp-macros.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3667301205849421080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3667301205849421080'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/06/evil-value-restriction-and-lisp-macros.html' title='The Evil Value Restriction and Lisp Macros'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-65400913439306883</id><published>2010-05-21T00:23:00.000-07:00</published><updated>2010-05-21T00:23:05.661-07:00</updated><title type='text'>A possible approach to writing an LLVM backend</title><content type='html'>Playing around with dragonegg, I've found that I can get pretty detailed llvm-ir/asm output, and I can even make sense of how the C output by Irken is getting translated.  Seems like this could be a handy way of getting started on writing an llvm backend.  Not that I'm thinking of doing that.  Must... resist...&lt;br /&gt;&lt;br /&gt;Here's the count-to-a-million test code in Scheme/Irken:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(let loop ((n 1000000))&lt;br /&gt;  (if (zero? n)&lt;br /&gt;      "done"&lt;br /&gt;      (loop (- n 1))))&lt;/pre&gt;&lt;br /&gt;Here's the C output:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;FUN_loop_8:&lt;br /&gt;    r0 = varref (0,0);&lt;br /&gt;    if PXLL_IS_TRUE(PXLL_TEST(unbox(r0)==0)) {&lt;br /&gt;      r0 = (object*) &amp;constructed_0;&lt;br /&gt;      PXLL_RETURN(0);&lt;br /&gt;    } else {&lt;br /&gt;      r0 = varref (0,0);&lt;br /&gt;      r1 = (object *) 3;&lt;br /&gt;      r0 = box(unbox(r0)-unbox(r1));&lt;br /&gt;      lenv[2] = r0;&lt;br /&gt;      goto FUN_loop_8;&lt;br /&gt;    }&lt;br /&gt;    PXLL_RETURN(0);&lt;br /&gt;  L1:&lt;br /&gt;  r1 = allocate (TC_CLOSURE, 2);&lt;br /&gt;  r1[1] = &amp;&amp;FUN_loop_8; r1[2] = lenv;&lt;br /&gt;  r0[2] = r1;&lt;br /&gt;  r0 = allocate (TC_TUPLE, 2);&lt;br /&gt;  r1 = (object *) 2000001;&lt;br /&gt;  r0[2] = r1;&lt;br /&gt;  r1 = top[2];&lt;br /&gt;  r0[1] = r1[2]; lenv = r0; goto FUN_loop_8;&lt;/pre&gt;&lt;br /&gt;And the relevant LLVM IR:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;"&amp;lt;bb 12&amp;gt;":                                        ; preds = %"&amp;lt;bb 17&amp;gt;", %"&amp;lt;bb 13&amp;gt;", %"&amp;lt;bb 24&amp;gt;"&lt;br /&gt;  %D.5560_160 = phi i8* [ inttoptr (i64 2000001 to i8*), %"&amp;lt;bb 24&amp;gt;" ], [ %D.5560_160, %"&amp;lt;bb 13&amp;gt;" ], [ %4, %"&amp;lt;bb 17&amp;gt;" ] ; &amp;lt;i8*&amp;gt; [#uses=3]&lt;br /&gt;  %3 = icmp ult i8* %D.5560_160, inttoptr (i64 2 to i8*) ; &amp;lt;i1&amp;gt; [#uses=1]&lt;br /&gt;  br i1 %3, label %"&amp;lt;bb 13&amp;gt;", label %"&amp;lt;bb 17&amp;gt;"&lt;br /&gt;&lt;br /&gt;"&amp;lt;bb 13&amp;gt;":                                        ; preds = %"&amp;lt;bb 12&amp;gt;"&lt;br /&gt;  %D.4871_48 = load i8** %2, align 8              ; &amp;lt;i8*&amp;gt; [#uses=1]&lt;br /&gt;  indirectbr i8* %D.4871_48, [label %"&amp;lt;bb 12&amp;gt;", label %Lreturn]&lt;br /&gt;&lt;br /&gt;"&amp;lt;bb 17&amp;gt;":                                        ; preds = %"&amp;lt;bb 12&amp;gt;"&lt;br /&gt;  %n.85_162 = ptrtoint i8* %D.5560_160 to i64     ; &amp;lt;i64&amp;gt; [#uses=1]&lt;br /&gt;  %D.5572_16323 = add i64 %n.85_162, -2           ; &amp;lt;i64&amp;gt; [#uses=1]&lt;br /&gt;  %D.5579_167 = or i64 %D.5572_16323, 1           ; &amp;lt;i64&amp;gt; [#uses=1]&lt;br /&gt;  %4 = inttoptr i64 %D.5579_167 to i8*            ; &amp;lt;i8*&amp;gt; [#uses=2]&lt;br /&gt;  store i8* %4, i8** %11, align 8&lt;br /&gt;  br label %"&amp;lt;bb 12&amp;gt;"&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-65400913439306883?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/65400913439306883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/05/possible-approach-to-writing-llvm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/65400913439306883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/65400913439306883'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/05/possible-approach-to-writing-llvm.html' title='A possible approach to writing an LLVM backend'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3672494029603084717</id><published>2010-05-18T16:46:00.000-07:00</published><updated>2010-05-18T20:02:31.595-07:00</updated><title type='text'>the pattern-matching parser, mostly done</title><content type='html'>I have a nearly finished python-like-language parser, written using pattern matching.&lt;br /&gt;&lt;br /&gt;The lexer is generated as a DFA by &lt;a href="http://dark.nightmare.com/rushing/irken/irken/parse/lexer.py.html"&gt;parse/lexer.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The parser tables are generated by a set of tools (including &lt;a href="http://www.canonware.com/Parsing/"&gt;Jason Evans' Parsing.py module&lt;/a&gt;) from a &lt;a href="http://dark.nightmare.com/rushing/irken/irken/parse/t2.g"&gt;simplified version of the Python 1.5.2 Grammar&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The DFA engine is now in a separate file, &lt;a href="http://dark.nightmare.com/rushing/irken/irken/lib/lexer.scm.html"&gt;lib/lexer.scm&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's &lt;a href="http://dark.nightmare.com/rushing/irken/irken/tests/t_parse2.scm.html"&gt;the parser so far&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The lexer tokens are fed through a one-token buffer that generates INDENT and DEDENT tokens when necessary.  This is done by the top-level 'parse' function.&lt;br /&gt;&lt;br /&gt;Following that are the expr datatypes, print functions, and finally the parsing functions themselves.&lt;br /&gt;&lt;br /&gt;Here's a typical parsing function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(define p-while-stmt&lt;br /&gt;  ;; while_stmt: 'while' test ':' suite ['else' ':' suite]&lt;br /&gt;  (_ test _ (item:nt _ body) (item:nt _ else)) -&gt; (expr:while (p-expr test) (p-suite body) (p-else else))&lt;br /&gt;  x -&gt; (perror "p-while-stmt" x))&lt;/pre&gt;&lt;br /&gt;Oh, and here's &lt;a href="http://dark.nightmare.com/rushing/irken/irken/tests/t_parse2.exp"&gt;some sample output&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3672494029603084717?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3672494029603084717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/05/pattern-matching-parser-mostly-done.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3672494029603084717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3672494029603084717'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/05/pattern-matching-parser-mostly-done.html' title='the pattern-matching parser, mostly done'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-6801386494570838582</id><published>2010-05-18T14:46:00.000-07:00</published><updated>2010-05-18T14:46:01.312-07:00</updated><title type='text'>The Advantages of Tagged Immediates</title><content type='html'>First, a definition.  An 'immediate' is a value that can fit in a register. That is, a non-pointer value.  In lisp, these are things like ints, bools, characters.  Most lisp implementations use tag bits to identify these objects at runtime, and Irken has inherited this design.&lt;br /&gt;&lt;br /&gt;The advantage is that the garbage collector and runtime can tell pointer from non-pointer, and can print out any type without consulting some table generated by the compiler.&lt;br /&gt;&lt;br /&gt;The disadvantage is mostly with integers - Irken uses a one-bit tag, the lowest bit.  Any value with the lowest bit set is an integer immediate.  To get its value you merely shift right.  This hurt a lot in the 16-bit world, a little in the 32-bit world, and I will venture to say not at all in a 64-bit world.&lt;br /&gt;&lt;br /&gt;Bools, characters, unit types, etc... are represented by a value having the  &lt;i&gt;second&lt;/i&gt; bit set.&lt;br /&gt;&lt;br /&gt;Pointer types are any value that has the lower two bits cleared; i.e., 32-bit aligned addresses.  Very neat how that works out.&lt;br /&gt;&lt;br /&gt;Now, the hardcore ML guys (like Mlton and OCaml) have pretty much eliminated all tagging, and use unboxed tuples whenever possible (i.e., a datatype containing three values will consist of exactly three words in the heap, no type+length word).  They do this because they can, and I suppose to be more competitive with C.&lt;br /&gt;&lt;br /&gt;My feeling is that the advantages of run-time tagging outweigh the disadvantages, &lt;i&gt;especially when debugging a new compiler&lt;/i&gt;.  I've had enough experience grepping through core dumps of python processes that I really appreciate having a heap image that can be combed through, analyzed by a coroner.  [In fact, at IronPort we wrote an entire suite of tools for doing post-mortem analysis on python core files. Sadly they still haven't been open-sourced].&lt;br /&gt;&lt;br /&gt;While hacking up the first test VM, I noticed another neat hack that claws back some of the disadvantage of boxes and tags.&lt;br /&gt;&lt;br /&gt;Imagine you have a datatype like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(datatype key&lt;br /&gt;  (:number int)&lt;br /&gt;  (:letter char))&lt;/pre&gt;&lt;br /&gt;It would be rather inefficient to put 'keys' into one-tuples, only to have a tagged immediate inside.  So Irken actually detects this case, and eliminates one-tuples like this whenever possible.  At run-time, a 'key' will consist of either one or the other immediate type, distinguished by the tag that's already on these values.&lt;br /&gt;&lt;br /&gt;The hack won't work for cases where you include more than one use of the same base type, for example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(datatype key&lt;br /&gt;  (:number int)&lt;br /&gt;  (:funny int)&lt;br /&gt;  (:letter char))&lt;/pre&gt;&lt;br /&gt;Since there's no way at runtime to distinguish the two integer alternatives.  (But you'll still get it for the 'letter' alternative).&lt;br /&gt;&lt;br /&gt;This hack works really well for a VM, where you need exactly this kind of datatype to represent the union of all possible types.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-6801386494570838582?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/6801386494570838582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/05/advantages-of-tagged-immediates.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6801386494570838582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6801386494570838582'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/05/advantages-of-tagged-immediates.html' title='The Advantages of Tagged Immediates'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-2775312984318060960</id><published>2010-05-17T18:16:00.000-07:00</published><updated>2010-05-17T18:22:52.714-07:00</updated><title type='text'>Getting Comfortable with Type Inference</title><content type='html'>Now that I've had many months of experience working with a type-inferred language, I'm beginning to notice a change in the way I work.&lt;br /&gt;&lt;br /&gt;Statically-typed functional languages have a well-deserved reputation for spitting out obtuse, nearly useless type errors.  Irken is no exception.  In fact, it's probably much worse than most languages because a type error dumps you into a Python traceback.  Also, it doesn't bother to track source line number information, so you're &lt;i&gt;really&lt;/i&gt; on your own.&lt;br /&gt;&lt;br /&gt;Over the past month or two, especially since I added pattern matching, I've noticed that my 'type accuracy' is improving.  The chances that something will be correctly typed the first time I try to compile it are higher than they were.  As I become familiar with the type system, and pattern matching, Irken has been training me.  It's as if a type error (and the resulting jaunt through pdb) is a slap on the nose.  A clean compile is like a nice treat.  Good human.&lt;br /&gt;&lt;br /&gt;This has changed my edit-compile loop a little - I tend to compile more often.  If I've only changed one or two lines since my last compile, I'm pretty sure I know where the typo is.&lt;br /&gt;&lt;br /&gt;This makes me wonder if one of ML's problems is related to this.  Old-timers don't need to spend all that effort making a "Microsoft Bob" type error reporter.  They see "itypes.TypeError: ((()-&gt;wta), (wjx-&gt;vpq))" and they know they forgot to pass an argument to that function call they just added.&lt;br /&gt;&lt;br /&gt;Newcomers, though.  They get that same feeling they had the first time they struggled with a C or Ada compiler.&lt;br /&gt;&lt;br /&gt;When/if I rewrite Irken in itself, I think I'll try to do a better job.  In &lt;a href="http://www.cs.mu.oz.au/~sulzmann/publications/hmx-clpx.pdf"&gt;"HM(X) Type Inference  is CLP(X) Solving"&lt;/a&gt;, Sulzmann and Stuckey argue that a constraint-based solver can do a better job of error reporting; so here's hoping I can figure that out when the time comes.&lt;br /&gt;&lt;br /&gt;(p.s. I have to admit that OCaml's reporting is pretty snazzy, though)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-2775312984318060960?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/2775312984318060960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/05/getting-comfortable-with-type-inference.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2775312984318060960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2775312984318060960'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/05/getting-comfortable-with-type-inference.html' title='Getting Comfortable with Type Inference'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-1533899364636352115</id><published>2010-05-11T13:38:00.000-07:00</published><updated>2010-05-11T13:38:45.044-07:00</updated><title type='text'>the temptations of LLVM</title><content type='html'>I'm still plugging away at the parser and vm for the python-like-language.&lt;br /&gt;&lt;br /&gt;But in another window I have the language reference for LLVM open, and as I browse through it I'm becoming increasingly distracted.  There are many wonderful snacks - things like &lt;a href="http://llvm.org/docs/LangRef.html#int_sadd_overflow"&gt;add with overflow detection&lt;/a&gt;, intrinsic functions like memmove, nice floating-point and vector insn support, atomic swap operations, etc...&lt;br /&gt;&lt;br /&gt;An interesting aspect of LLVM is that it doesn't &lt;i&gt;really&lt;/i&gt; support a register model.  Instead, it uses SSA, which means that you just keep inventing names for each result.  Now, this will either be a &lt;b&gt;perfect&lt;/b&gt; fit for Irken's CPS-based compiler, or it will make it impossible to do.  I haven't decided yet.&lt;br /&gt;&lt;br /&gt;A long time ago, CPS and SSA were proven to be equivalent.  From what I can tell, the compiler world has moved on and pretends that CPS never existed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-1533899364636352115?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/1533899364636352115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/05/temptations-of-llvm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/1533899364636352115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/1533899364636352115'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/05/temptations-of-llvm.html' title='the temptations of LLVM'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-7695904527180383358</id><published>2010-05-03T19:27:00.000-07:00</published><updated>2010-05-03T19:27:25.627-07:00</updated><title type='text'>A statically typed VM?</title><content type='html'>Trying to wrap my head around this idea... The VM I'm playing around with right now is dynamically typed - but its implementation is statically typed.  I started thinking about making a bytecode implementation of Irken itself (rather than a Python-like language).  &lt;br /&gt;&lt;br /&gt;But I'm not sure it even makes sense to try to write a static VM in a static language, because you'd have to do the equivalent of 'void*' casting everywhere.  (Of course, this is what you do when you write a VM in C, but it feels a much more natural thing to do in C 8^).&lt;br /&gt;&lt;br /&gt;I was curious to see how OCaml dealt with this issue... and was quite surprised to find a &lt;a href="http://caml.inria.fr/cgi-bin/viewcvs.cgi/ocaml/trunk/byterun/interp.c?rev=2&amp;view=markup"&gt;VM written in C&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-7695904527180383358?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/7695904527180383358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/05/statically-typed-vm.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7695904527180383358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7695904527180383358'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/05/statically-typed-vm.html' title='A statically typed VM?'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-999411805452718466</id><published>2010-04-26T13:36:00.000-07:00</published><updated>2010-04-26T13:37:38.121-07:00</updated><title type='text'>tak20 benchmark runs in the VM</title><content type='html'>My &lt;a href="http://dark.nightmare.com/rushing/irken/irken/vm/t11.html"&gt;favorite benchmark&lt;/a&gt; now runs in the VM, since I now have all three types of procedure invocation implemented: tail calls, tail recursive calls, and normal invocation.  The last is the most complex, because it actually involves building a 'stack frame' and saving/restoring registers:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(datatype vmcont&lt;br /&gt;  (:nil)&lt;br /&gt;  (:k (vmcont) (lenv) int (vector (object)))&lt;br /&gt;  )&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Take a look at &lt;a href="http://dark.nightmare.com/rushing/irken/irken/vm/vm.html"&gt;the current VM implementation, in Irken&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So a 'VM continuation' consists of the pointer to the next frame, the lexical environment, the PC, and a vector of saved registers.&lt;br /&gt;&lt;br /&gt;The 'INVOKE' cps insn is turned into two VM insns, 'CALL' and 'POP'.&lt;br /&gt;&lt;br /&gt;Even without any serious tweaking, the tak20 benchmark seems to run about the same speed as in python.  But I plan to make specialized versions of CALL and POP for different numbers of saved registers.  This will eliminate loops in the insns and thus get rid of allocation for the insn closures.&lt;br /&gt;&lt;br /&gt;It's &lt;i&gt;very&lt;/i&gt; rewarding to finally bring all this work together.  Putting together a functioning VM is the very tip of an iceberg I've spent 2+ years building.&lt;br /&gt;&lt;br /&gt;I'm even thinking about documenting the Irken language.  Yeah, I know, crazy thoughts.&lt;br /&gt;&lt;br /&gt;Next step: start building the python-like language.  This would involve rewriting the byte-code compiler in Irken.  OR, I could continue the nearly trivial task of supporting Irken as a byte-coded language, and start rewriting &lt;i&gt;everything&lt;/i&gt; in Irken.  As we all know, only the most fashionable and respectable languages are written in themselves.  It's tempting!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-999411805452718466?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/999411805452718466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/04/tak20-benchmark-runs-in-vm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/999411805452718466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/999411805452718466'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/04/tak20-benchmark-runs-in-vm.html' title='tak20 benchmark runs in the VM'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-5379336959410053369</id><published>2010-04-22T21:40:00.000-07:00</published><updated>2010-04-22T21:40:28.493-07:00</updated><title type='text'>dragon egg</title><content type='html'>If you've ever tried to even &lt;i&gt;read&lt;/i&gt; the instructions for building llvm-gcc (much less try to build it), you understand why this is good news.&lt;br /&gt;&lt;br /&gt;http://dragonegg.llvm.org/&lt;br /&gt;&lt;br /&gt;Sounds like gcc has gained a plugin architecture, and the llvm folks are putting together a plugin, 'DragonEgg', that uses LLVM as the back end.&lt;br /&gt;&lt;br /&gt;Why do I care about this?&lt;br /&gt;&lt;br /&gt;1) Clang still does not support lexical functions, which are critically important to Irken's performance.&lt;br /&gt;2) The version of llvm-gcc distributed with Apple's XCode uses an older version of llvm that implements the address-of-label extension with a hack so horrible I would be embarrassed to describe it to you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-5379336959410053369?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/5379336959410053369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/04/dragon-egg.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/5379336959410053369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/5379336959410053369'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/04/dragon-egg.html' title='dragon egg'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-249445198646945755</id><published>2010-04-22T14:51:00.000-07:00</published><updated>2010-04-22T14:51:04.444-07:00</updated><title type='text'>first loop in the vm!</title><content type='html'>I've implemented enough instructions in the VM that I can now do a loop (a.k.a. a tail-recursive function call).&lt;br /&gt;&lt;br /&gt;I still need to work on the VM insns, there's a lot of allocation taking place that shouldn't... also, there's range-checking on each and every vector access.. even including stuff like the register file.  Given those caveats, it's only about 4X slower than a similar python loop.  I'm pretty sure I should be able to make it faster than python, we'll see.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;--- cps ---&lt;br /&gt;   0 = new_env [] 1&lt;br /&gt;   -   push_env [0] None&lt;br /&gt;   1 = close [] 'loop_0'&lt;br /&gt;       0 = lit [] 3&lt;br /&gt;       1 = varref [] ((0, 0), False, {n_1})&lt;br /&gt;       0 = primop [0, 1] ('%=',)&lt;br /&gt;       0 = test [0] None&lt;br /&gt;           0 = lit [] 1&lt;br /&gt;               return [0] None&lt;br /&gt;           0 = varref [] ((0, 0), False, {n_1})&lt;br /&gt;           1 = lit [] 2&lt;br /&gt;           0 = primop [0, 1] ('%-',)&lt;br /&gt;               tr_call [0] (1, &lt;function ['loop_0', [{n_1}], True, None] 42&gt;)&lt;br /&gt;           return [0] None&lt;br /&gt;   -   store_tuple [1, 0] (0, 1, 1)&lt;br /&gt;   0 = new_env [] 1&lt;br /&gt;   1 = lit [] 0&lt;br /&gt;   0 = store_tuple [1, 0] (0, 1, 1)&lt;br /&gt;   1 = varref [] ((0, 0), True, {loop_0})&lt;br /&gt;       invoke_tail [1, 0] &lt;function ['loop_0', [{n_1}], True, None] 42&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-249445198646945755?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/249445198646945755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/04/first-loop-in-vm.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/249445198646945755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/249445198646945755'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/04/first-loop-in-vm.html' title='first loop in the vm!'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3994597526007165544</id><published>2010-04-05T12:56:00.000-07:00</published><updated>2010-04-05T12:58:11.158-07:00</updated><title type='text'>stirrings of a vm</title><content type='html'>I'm finally beginning to think seriously about a VM.  It's been a long road.&lt;br /&gt;&lt;br /&gt;My approach, as usual, is maximally lazy.  For now, I've pushed the parser to the side while I figure out what the byte code compiler will put out.  That of course depends on what the VM will look like.&lt;br /&gt;&lt;br /&gt;To begin, I'll simply re-use the Irken compiler, which already compiles a lambda-calculus based language into a register-based CPS instruction stream.&lt;br /&gt;&lt;a href="http://www.nightmare.com/rushing/irken/irken/bytecomp.py"&gt;&lt;br /&gt;Here's what it looks like so far.&lt;/a&gt;&lt;br /&gt;This bytecode is consumed by the VM, which works in two phases.  First, it loads the bytecode into two vectors, one holding instructions, one holding data.  (Note: the insn vector is typed as "vector((-&gt;undefined))").  Then it simply invokes the first insn.  &lt;a href="http://www.nightmare.com/rushing/irken/irken/vm/vm.scm"&gt;See vm/vm.scm for details&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The vector of insns allows us to build a &lt;a href="http://en.wikipedia.org/wiki/Threaded_code"&gt;'threaded' VM&lt;/a&gt;: each insn is implemented as a no-argument function.  The last thing each insn does is fetch and execute the next insn.&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;insn-literal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;regs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;vm-data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pcd&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="nv"&gt;vm-data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;pcd&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;set! &lt;/span&gt;&lt;span class="nv"&gt;pcd&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;pcd&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;next-insn&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;"((next-insn))" compiles to a bit of C that looks like this:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;lenv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="k"&gt;goto&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This has the potential to be very fast.&lt;br /&gt;&lt;br /&gt;My current stumbling block is where/how to straddle the divide between the typed and untyped universe.  The VM is written in a strongly typed language, but I want it to implement an untyped language.  In order to do that I need to be able to store arbitrary objects into the VM registers.  I'm thinking of a couple of different approaches right now.&lt;br /&gt;&lt;br /&gt;1) Add an 'object' type to the Irken compiler - this will act like a normal declared datatype, but when you pattern match or vcase it, the compiler will emit code to detect our run-time tags instead.  I'll probably need some way of casting things to the object type.&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;2) *Remove* run-time tagging from Irken. This would make Irken even more like OCaml.  The advantages should be obvious.  The disadvantage would be I would have to implement some kind of stack map and teach the garbage collector how to use it.  Also, Irken would become much more difficult to debug.  But I could then implement the VM using fully declared and 'normal' datatypes without adding an extra layer of type tagging.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3994597526007165544?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3994597526007165544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/04/stirrings-of-vm.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3994597526007165544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3994597526007165544'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/04/stirrings-of-vm.html' title='stirrings of a vm'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-7680149363195174461</id><published>2010-03-26T13:33:00.000-07:00</published><updated>2010-03-26T13:35:37.077-07:00</updated><title type='text'>pattern matching: red-black trees</title><content type='html'>This is based on Okasaki's "Purely Functional Data Structures", Chapter 3.3.&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;lib/core.scm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;lib/random.scm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;datatype&lt;/span&gt; &lt;span class="nv"&gt;T&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:E&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:B&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T/insert&lt;/span&gt; &lt;span class="nv"&gt;root&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;lbalance&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;                     &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;rbalance&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;                     &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ins&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:E&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:E&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:E&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;k2&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;cond &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;&amp;lt; &lt;/span&gt;&lt;span class="nv"&gt;k&lt;/span&gt; &lt;span class="nv"&gt;k2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ins&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;k2&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;               &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;&amp;lt; &lt;/span&gt;&lt;span class="nv"&gt;k2&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;k2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ins&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;k2&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;cond &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;&amp;lt; &lt;/span&gt;&lt;span class="nv"&gt;k&lt;/span&gt; &lt;span class="nv"&gt;k2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lbalance&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ins&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;k2&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;               &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;&amp;lt; &lt;/span&gt;&lt;span class="nv"&gt;k2&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rbalance&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;k2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ins&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;               &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;s&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ins&lt;/span&gt; &lt;span class="nv"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;s&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;k&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;s&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:E&lt;/span&gt; &lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;impossible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-spaces&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="nv"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;cond &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-string&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;  &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;- &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-item&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-spaces&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;printn&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;T/print&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:E&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;u&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:R&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T/print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-item&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T/print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:B&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T/print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print-item&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T/print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+ &lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;n-random&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="nv"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T:E&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;= &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="nv"&gt;t&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;- &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T/insert&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;T/print&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;n-random&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-7680149363195174461?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/7680149363195174461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/pattern-matching-red-black-trees.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7680149363195174461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7680149363195174461'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/pattern-matching-red-black-trees.html' title='pattern matching: red-black trees'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3936905606554476747</id><published>2010-03-26T13:09:00.000-07:00</published><updated>2010-03-26T13:13:40.239-07:00</updated><title type='text'>parsing with pattern matching</title><content type='html'>Parsing with pattern matching is pretty sweet.&lt;br /&gt;&lt;br /&gt;Here's a test grammar:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# test a simple predicate language&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nl"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;predicate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;atom&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="o"&gt;)*&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nv"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;NAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nv"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;NAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;NUMBER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;STRING&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And the pattern-matching code to parse it into an AST:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;datatype&lt;/span&gt; &lt;span class="nv"&gt;atom&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:name&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:number&lt;/span&gt; &lt;span class="nv"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:string&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;datatype&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:pred&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:atom&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;p-atom&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:t&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;NAME&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom:name&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:t&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;NUMBER&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom:number&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;string-&amp;gt;int&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:t&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;STRING&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom:string&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;p-atom&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;p-list3&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:t&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;comma&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p-expr&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;p-list3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;p-list2&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:nt&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;list_c_1_s1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p-list3&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p-list2&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:nt&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;list_c_1_s1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;      &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;p-list2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;p-list&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:nt&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt; &lt;br /&gt;                 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;rest&lt;/span&gt; &lt;br /&gt;                 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p-expr&lt;/span&gt; &lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p-list2&lt;/span&gt; &lt;span class="nv"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;p-list&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;p-expr2&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:nt&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;predicate&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:t&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;NAME&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="c1"&gt;;; lparen&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="c1"&gt;;; rparen&lt;/span&gt;&lt;br /&gt;           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:pred&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p-list&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:nt&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;atom&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expr:atom&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p-atom&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="nv"&gt;p-expr&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;item:nt&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;expr&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:cons&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list:nil&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;p-expr2&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;p-expr&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The patterns are a little noisy due to my lack of a special syntax for lists.  I'm still on the fence about whether that's a good idea.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3936905606554476747?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3936905606554476747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/testing-pygments-blogger_26.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3936905606554476747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3936905606554476747'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/testing-pygments-blogger_26.html' title='parsing with pattern matching'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3141013724300990757</id><published>2010-03-25T15:30:00.000-07:00</published><updated>2010-03-25T15:30:59.625-07:00</updated><title type='text'>new release with pattern matching</title><content type='html'>I've checked in the pattern matching code.  There are 10 or so new tests for it, but none of them test it especially heavily.  I'll probably rewrite lib/frb.scm (the red-black tree code) using it as the next 'test'.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nightmare.com/rushing/irken/irken.100325.tar.gz"&gt;http://www.nightmare.com/rushing/irken/irken.100325.tar.gz&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3141013724300990757?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3141013724300990757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/new-release-with-pattern-matching.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3141013724300990757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3141013724300990757'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/new-release-with-pattern-matching.html' title='new release with pattern matching'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3082591882129989311</id><published>2010-03-23T16:35:00.000-07:00</published><updated>2010-03-23T16:35:15.175-07:00</updated><title type='text'>impressed with llvm, again</title><content type='html'>Testing out pattern matching against constants, I wrote the following silly function:&lt;br /&gt;&lt;pre&gt;(define thing&lt;br /&gt;  0 1 -&gt; 2&lt;br /&gt;  0 y -&gt; 3&lt;br /&gt;  1 0 -&gt; 4&lt;br /&gt;  1 x -&gt; (+ x 5)&lt;br /&gt;  y z -&gt; (+ y z)&lt;br /&gt;  )&lt;br /&gt;(thing 10 20)&lt;br /&gt;&lt;/pre&gt;Which turned into a nice set of if statements, doing 4 tests in total.  Not bad.  But I was curious to see what kind of asm LLVM would generate for it.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;_vm:&lt;br /&gt;Leh_func_begin7:&lt;br /&gt;        pushq   %rbp&lt;br /&gt;Llabel13:&lt;br /&gt;        movq    %rsp, %rbp&lt;br /&gt;Llabel14:&lt;br /&gt;        movq    _heap0(%rip), %rax&lt;br /&gt;        movq    $772, (%rax)&lt;br /&gt;        movq    $10, 8(%rax)&lt;br /&gt;        movq    $10, 16(%rax)&lt;br /&gt;        movq    $1, 24(%rax)&lt;br /&gt;        movl    $61, %eax&lt;br /&gt;        popq    %rbp&lt;br /&gt;        ret&lt;br /&gt;Leh_func_end7:&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Huh.  So that bit there at the very end, "movl $61, %eax".  Yeah.  That's the answer, "30". Even with all the tagging/untagging, registers, embedded if statements, etc... LLVM still optimized the entire program away to a constant.  Nice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3082591882129989311?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3082591882129989311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/impressed-with-llvm-again.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3082591882129989311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3082591882129989311'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/impressed-with-llvm-again.html' title='impressed with llvm, again'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-193567159665450433</id><published>2010-03-22T13:01:00.000-07:00</published><updated>2010-03-22T13:01:29.242-07:00</updated><title type='text'>pattern matching!</title><content type='html'>I managed to ignore the subject of pattern matching for a loooong time.  I wanted to see how reasonable it was to build a language using 'case'-type statements.  I viewed my ability to code up something &lt;a href="http://www.nightmare.com/rushing/irken/blog/frb.html"&gt;relatively complex like red-black trees&lt;/a&gt; as proof that they're not absolutely needed.&lt;br /&gt;&lt;br /&gt;However, now that I've seen that it's relatively easy to add (given the existing vcase support), I'm beginning to warm up.  &lt;a href="http://dark.nightmare.com/rushing/irken/blog/t_match2.html"&gt;Look over these alternate versions of 'reverse-onto'.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The problem that forced me to finally look into it was the parser.  In order to walk over complex trees of tokens - keyed by symbols - I was writing some very hairy 5-levels-deep vcase code.  And I remembered how much easier this kind of task is in a language like Erlang.  If you look through the code for ejabberd, for example, you might be confused hunting for the xml/xmpp parser, until you realize that it's embedded in the definition of the functions themselves, using pattern matching.&lt;br /&gt;&lt;br /&gt;As you might be able to tell from the example given, the constructor syntax is still pretty wordy.  There's no easy fix for this problem, which is caused by the requirements of type inference.  Most ML-like languages require that constructors are globally unique.  I find this abhorrent, so instead I'm requiring the name of the datatype to be present, e.g. "list:cons".&lt;br /&gt;&lt;br /&gt;There may be ways to make this less wordy.  It would be perfectly reasonable to define the list constructors as 'C' and 'N'. (for 'cons' and 'nil', respectively).  A tree datatype could use 'N' and 'E' (for 'node' and 'empty').  This would still be pretty readable.&lt;br /&gt;&lt;br /&gt;SML seems to use its module system to make it possible to use single-letter abbreviations like this.&lt;br /&gt;&lt;br /&gt;One other area of inequality that really bugs me: the way lists are treated specially in ML dialects.  It would be really nice for the user to be able to define their own extensions in a lisp-macro-like way.  Something to think about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-193567159665450433?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/193567159665450433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/pattern-matching.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/193567159665450433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/193567159665450433'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/pattern-matching.html' title='pattern matching!'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-396446917392373920</id><published>2010-03-20T16:06:00.000-07:00</published><updated>2010-03-20T16:14:52.763-07:00</updated><title type='text'>The Implementation of Functional Programming Languages</title><content type='html'>I'm working on adding pattern matching to Irken.  Digging through the OCaml source, I found a reference to this little gem:&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;"The Implementation of Functional Programming Languages&lt;/span&gt;&lt;span style="font-size:100%;"&gt;" (Simon Peyton Jones, published by Prentice Hall, 1987.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The book is available for free here: &lt;a href="http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/"&gt;http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Chapters 4 and 5 cover exactly what I need for pattern matching - in fact, it appears that their algorithm transforms a set of patterns into a tree of 'case' statements where their 'case' construct exactly matches my current 'vcase'.  Nice!&lt;br /&gt;&lt;br /&gt;How is it that after so many years of trudging through this space, I never knew about this book?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-396446917392373920?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/396446917392373920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/implementation-of-functional.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/396446917392373920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/396446917392373920'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/implementation-of-functional.html' title='The Implementation of Functional Programming Languages'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-144084117140242578</id><published>2010-03-13T12:25:00.000-08:00</published><updated>2010-03-13T12:36:38.147-08:00</updated><title type='text'>recent changes</title><content type='html'>&lt;ol&gt;&lt;li&gt;I've restored the ability to gc in the middle of a function.  This required coming up with a bit of a trick to copy registers in and out of gc:&lt;pre&gt;void gc_regs_in (int n) {&lt;br /&gt; switch (n) {&lt;br /&gt; case 4: heap1[6] = r3;&lt;br /&gt; case 3: heap1[5] = r2;&lt;br /&gt; case 2: heap1[4] = r1;&lt;br /&gt; case 1: heap1[3] = r0;&lt;br /&gt;}}&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Literal data built at compile-time.  Big win for programs with lots of pre-initialized data (like lexer and parser tables).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Register bindings for variables in leaf positions.  This will cut down on lots of heap allocation&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Verify the output of tests.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Filled out the type declaration syntax (type variables, recursive types, etc...) and unified it with the cexp syntax.  (Well, to the extent that they use a single parser now rather than two different ones).&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-144084117140242578?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/144084117140242578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/recent-changes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/144084117140242578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/144084117140242578'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/recent-changes.html' title='recent changes'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-6934587040029014545</id><published>2010-03-12T14:57:00.000-08:00</published><updated>2010-03-12T15:32:35.220-08:00</updated><title type='text'>syntax for literals</title><content type='html'>In Scheme/Lisp, literal lists are expressed using the quote syntax: '(1 2 3), which is expanded by the reader to (QUOTE 1 2 3).  In Lisp, quoted list structures are important, especially for macros (which I'm deliberately trying not to support in order to avoid becoming dependent on the lisp syntax).&lt;br /&gt;&lt;br /&gt;I need a literal syntax for Irken, and until now I've used QUOTE, but it's causing me a lot of trouble now that I'm using algebraic datatypes.&lt;br /&gt;&lt;br /&gt;To put this in terms that a C programmer can understand, this is a literal array of integers:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;  int thing[] = {1, 2, 3, 4, 5};&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Without a literal syntax, you'd have to do this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;  int * thing = malloc (sizeof(int) * 5);&lt;br /&gt;  thing[0] = 1;&lt;br /&gt;  ...&lt;/pre&gt;&lt;br /&gt;The 'list' datatype is declared like any other - it's not built in to the compiler (though I could certainly do that):&lt;br /&gt;&lt;pre&gt;(datatype list&lt;br /&gt; (:nil)&lt;br /&gt; (:cons 'a (list 'a))&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;The compiler will translate '(1 2) into:&lt;br /&gt;(QUOTE (list:cons 1 (list:cons 2 (list:nil)))).&lt;br /&gt;&lt;br /&gt;But this leaves all the other datatypes with no convenient syntax - and worse - with no way to identify or express literals.  This has turned into a big problem for the parser and lexer, where I really need to build the literals at compile-time (otherwise I get huge executables that do nothing but build data structures).&lt;br /&gt;&lt;br /&gt;Right now I'm playing with this syntax:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(literal (tree:node (tree:leaf 1) (tree:node (tree:leaf 2) (tree:leaf 3))))&lt;/pre&gt;The grammar for 'constructed' literals is:&lt;br /&gt;&lt;br /&gt; literal ::= (&amp;lt;constructor&amp;gt; &amp;lt;literal&amp;gt; ... ) | (vector &amp;lt;literal&amp;gt; ...) | immediate&lt;br /&gt;&lt;br /&gt;The question is - should I retain QUOTE just for lists?  I hate having two syntaxes for two very similar concepts.  All the ML-like languages have a special syntax for lists, which is probably an indicator that it's important.  On the other hand - the special syntax might encourage people to misuse the list datatype simply because it's more convenient - e.g., you might build a binary tree out of lists (which wastes a lot of heap) rather than declaring a proper datatype.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-6934587040029014545?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/6934587040029014545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/syntax-for-literals.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6934587040029014545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/6934587040029014545'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/syntax-for-literals.html' title='syntax for literals'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-2533436066741826579</id><published>2010-03-04T23:11:00.000-08:00</published><updated>2010-03-04T23:18:20.586-08:00</updated><title type='text'>Parser's Working</title><content type='html'>Ok, got the parser rewritten using the new datatypes.&lt;br /&gt;&lt;br /&gt;If you're bored, and would like to know how small a lexer and parser engine can be, take a look at &lt;a href="http://www.nightmare.com/rushing/irken/irken/tests/t_parse.scm"&gt;tests/t_parse.scm&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Note that both the lexer and the parser are bare-bones engines that are using tables generated by other tools written in Python.  In this case, a DFA lexer written by me, and an LR(1) parser generator written by Jason Evans.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-2533436066741826579?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/2533436066741826579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/parsers-working.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2533436066741826579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2533436066741826579'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/parsers-working.html' title='Parser&apos;s Working'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-7872022174995202611</id><published>2010-03-03T17:54:00.001-08:00</published><updated>2010-03-03T18:15:11.480-08:00</updated><title type='text'>polymorphic vs normal variants</title><content type='html'>Just a quick summary of the pros and cons of each alternative.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Polymorphic Variants&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pros:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Outrageously polymorphic - use them any way you like, anywhere&lt;/li&gt;&lt;li&gt;No declarations needed.&lt;/li&gt;&lt;li&gt;The runtime can associate certain meanings with the tags on polymorphic variants.  This makes them act more like lisp type tags.  For example, the runtime can identify a list and correctly print it out, rather than &lt;span style="font-family:courier new;"&gt;{u0 1 {u0 2 {u0 3 {u1}}}}&lt;/span&gt;.  [This is probably addressed in ML by treating lists specially, rather than having the 'basis' declare the list type.]&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Cons:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Each variant consumes precious tag space.  Since type tags are stored in a byte, and in particular a byte with the lower two bits zeroed, there are only about 59 such tags left.&lt;/li&gt;&lt;li&gt;Lots of work for the type solver, because of the overly detailed types...&lt;/li&gt;&lt;li&gt;...thus the compiler runs slower&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size:130%;"&gt;'Normal' Variants.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pros:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Cleanly declared datatypes.  If we're really planning on doing systems programming with this, then declared datatypes are probably non-negotiable.&lt;/li&gt;&lt;li&gt;Tag values are consumed only &lt;span style="font-style: italic;"&gt;within&lt;/span&gt; a datatype - so rather than having 59 total different types, we can have an unlimited number of types, each of which can have up to 59 different variants.  (To clarify this with an example, the list datatype uses the tags 0 and 1, because it has two variants, 'nil', and 'cons').  A tree datatype will also use tags starting at 0, since the type system guarantees that a tree will never be confused with a list at runtime.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Cons:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The runtime has no idea what it's printing out, so you can get impenetrable output like this: &lt;span style="font-family:courier new;"&gt;{u0 16 {u0 1 0} {u0 15 {u0 1 0} {u0 14 {u0 1 0}...&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:times new roman;"&gt;Datatype declarations are going to scare non-ML people off, which is a shame.  Here's what the syntax currently looks like:&lt;pre&gt;(datatype item&lt;br /&gt;  (:nt symbol (list (item 'a)))&lt;br /&gt;  (:t symbol)&lt;br /&gt;  )&lt;br /&gt;&lt;br /&gt;(datatype stack&lt;br /&gt;  (:empty)&lt;br /&gt;  (:elem (item 'a) int (stack 'a))&lt;br /&gt;  )&lt;span style="font-family:times new roman;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;Sadly, I've chosen the same solution as OCaml - to leave both kinds in.  If I could collect up the nerve to remove a lot of hard-earned code, I'd probably remove polymorphic variants.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-7872022174995202611?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/7872022174995202611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/polymorphic-vs-normal-variants.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7872022174995202611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7872022174995202611'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/polymorphic-vs-normal-variants.html' title='polymorphic vs normal variants'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-925295219538973002</id><published>2010-03-02T22:35:00.001-08:00</published><updated>2010-03-02T22:39:50.741-08:00</updated><title type='text'>status update</title><content type='html'>Finally posted a new tarball today.  Lots of changes over the past few weeks:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;'datatype' syntax and 'normal' variants (though I've left in polymorphic variants as a 'stealth' feature)&lt;/li&gt;&lt;li&gt;more tests, and run_tests.py now verifies their output&lt;/li&gt;&lt;li&gt;'let_reg' will store bindings into registers when certain conditions are met - this really cuts down on pointless allocation for local variables.&lt;/li&gt;&lt;/ol&gt;I feel like this is getting much closer to 'useful' status, and will hopefully begin work on a VM within the next couple of weeks.&lt;br /&gt;&lt;a href="http://www.nightmare.com/rushing/irken/irken.100302.tar.gz"&gt;&lt;br /&gt;Here's the tarball.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-925295219538973002?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/925295219538973002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/03/status-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/925295219538973002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/925295219538973002'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/03/status-update.html' title='status update'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-8906628691764289197</id><published>2010-02-12T14:36:00.001-08:00</published><updated>2010-02-12T16:00:24.415-08:00</updated><title type='text'>Temporarily Giving up on Polymorphic Variants</title><content type='html'>Polymorphic Variants finally reached the point where they were causing more problems than they were worth.  So I've temporarily put them aside... leaving support in the compiler, but I'm adding normal datatype/sum/union declarations back in.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The types are too expressive (see previous post)&lt;/li&gt;&lt;li&gt;Since the types are so complex, the solver gets hit with constraints leading to tens of thousands of type variables.  This is mostly triggered by large initialization expressions like parser tables.  Waiting 20 seconds to type a 40K file is not cool.&lt;/li&gt;&lt;li&gt;I need to get back to work, i.e. I need to make some progress.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;So after plugging away for a week or so, I've now run into a new problem - the value restriction.  Something I've put off dealing with for a long time.  Turns out the problem is classically triggered by type constructors for things like empty lists.  For example, this types without any problems:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(datatype list&lt;br /&gt;  (nil)&lt;br /&gt;  (cons 'a list)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(let ((l0 (list:nil)))&lt;br /&gt;  (set! l0 (list:cons 34 l0))&lt;br /&gt;  (list:cons #f l0)&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;[Note that the last line glues together a "list(bool)" onto a "list(int)"]&lt;br /&gt;&lt;br /&gt;The solution is to restrict the polymorphism of assigned variables, hence the &lt;a href="http://users.cis.fiu.edu/%7Esmithg/cop4555/valrestr.html"&gt;Value Restriction&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;-Sam&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-8906628691764289197?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/8906628691764289197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/02/temporarily-giving-up-on-polymorphic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8906628691764289197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/8906628691764289197'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/02/temporarily-giving-up-on-polymorphic.html' title='Temporarily Giving up on Polymorphic Variants'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-7970512159179334014</id><published>2010-02-05T13:50:00.000-08:00</published><updated>2010-02-05T14:19:39.387-08:00</updated><title type='text'>restraining polymorphic variants</title><content type='html'>Since I started playing with polymorphic variants, I've repeatedly stumbled into a strange problem with them.  They're &lt;span style="font-style:italic;"&gt;too&lt;/span&gt; expressive!&lt;br /&gt;&lt;br /&gt;Polymorphic variants are the flip side of polymorphic records.  This is a major feature of my type system that allows you to use any label anywhere, in any way, without having to declare it first.  I really like this ability, especially in the context of Irken, because it has a very Pythonic, dynamic-language feel to it.&lt;br /&gt;&lt;br /&gt;As an example, here's some code that creates a lisp-like list:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(:cons 1 (:cons 2 (:cons 3 (:nil)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it.  Symbols starting with colons are constructors.  No datatype declaration.  Completely type safe.  You just use constructors however you like.  OCaml has the same feature:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# `Cons (1, `Cons (2, `Cons 3, `Nil));;&lt;br /&gt;- : [&gt; `Cons of int * [&gt; `Cons of int * [&gt; `Cons of int ] * [&gt; `Nil ] ] ] =&lt;br /&gt;`Cons (1, `Cons (2, `Cons 3, `Nil))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But if you look at the type that OCaml assigns to the result you see the seed of the problem.  Watch this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# `Cons (1, `Cons ("hello", `Nil));;&lt;br /&gt;- : [&gt; `Cons of int * [&gt; `Cons of string * [&gt; `Nil ] ] ] =&lt;br /&gt;`Cons (1, `Cons ("hello", `Nil))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;See?  You could call that the datatype of lists that start with an int followed by a string.&lt;br /&gt;&lt;br /&gt;With a complex data structure like a red-black tree, you get types like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rsum(rlabel('purple', pre(product(rsum(rlabel('empty', pre(kb), rlabel('purple',&lt;br /&gt; pre(jw), rlabel('red', pre(gz), rdefault(abs()))))), rsum(rlabel('empty', pre(nq),&lt;br /&gt; rlabel('purple', pre(nl), rlabel('red', pre(ko), rdefault(abs()))))), jc, jd)), &lt;br /&gt;rlabel('empty', pre(product()), rlabel('red', pre(product(rsum(rlabel('purple', &lt;br /&gt;pre(product(hj, hk, hl, hm)), bgc)), rsum(rlabel('purple', pre(product(hn, ho, hp,&lt;br /&gt; hq)), bgp)), hh, hi)), rdefault(abs())))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What the hell is that??  Well, it's a type built during the compilation of one of the tree-balancing functions; a reflection of the matching structure used to examine the tree a few levels deep.  Think of it as a template that sits on top of a red-black tree.&lt;br /&gt;&lt;br /&gt;Here, the compiler is building incredibly detailed, complex types and checking them for me.  What I would prefer is for it to automatically recognize recursive datatypes when I use them - without have to declare them.  Or, I would like the compiler to keep variants monomorphic within a single type.&lt;br /&gt;&lt;br /&gt;This would involve a loss of some expressive power.  But how often would you want to use variants polymorphically &lt;span style="font-style:italic;"&gt;within the same object&lt;/span&gt;?  And if you needed that, why wouldn't you use a different label?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-7970512159179334014?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/7970512159179334014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2010/02/restraining-polymorphic-variants.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7970512159179334014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7970512159179334014'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2010/02/restraining-polymorphic-variants.html' title='restraining polymorphic variants'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-7113314319014031049</id><published>2009-12-19T20:05:00.000-08:00</published><updated>2009-12-19T20:19:35.338-08:00</updated><title type='text'>Thinking about a new inliner...</title><content type='html'>I recently found a problem with the inliner.  After adding the code to unpack the data attached to variant types - I deliberately left the unpacker in a form like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;((lambda (f0 f1 f2...) &amp;lt;body&amp;gt;) x.f0 x.f1 x.f2)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Something like that might be generated for a vcase expression like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;      (define (pop)&lt;br /&gt;        (vcase stack&lt;br /&gt;          ((:nil) (error "stack underflow"))&lt;br /&gt;          ((:elem item _ tail)&lt;br /&gt;           (set! stack tail)&lt;br /&gt;           item)))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I then made the inliner recognize ((lambda () ...) ...) applications and inline them when it could.  This revealed a major problem with my inliner, most easily demonstrated like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(let ((n 10))&lt;br /&gt;  ((lambda (x) (set! n 5) x) n))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This should return 10, not 5.  In the stack example above, instead of returning the popped item, it returns the new top of the stack.&lt;br /&gt;&lt;br /&gt;Some kind of assignment analysis is needed.&lt;br /&gt;&lt;br /&gt;While digging around for a good reference on the subject, I found &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.54.2438"&gt;a really good paper on inlining&lt;/a&gt; that seems to cover this and several other issues.  It looks pretty straightforward to implement, so there may be another pause-to-work-on-irken phase.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-7113314319014031049?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/7113314319014031049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/12/thinking-about-new-inliner.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7113314319014031049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7113314319014031049'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/12/thinking-about-new-inliner.html' title='Thinking about a new inliner...'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-4599754486558594087</id><published>2009-12-13T13:45:00.000-08:00</published><updated>2009-12-13T13:58:35.530-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vectors'/><category scheme='http://www.blogger.com/atom/ns#' term='gc'/><title type='text'>avoiding address range checks in the copying collector</title><content type='html'>I added this hack years ago, in another project; so I don't remember if I came up with the idea myself or borrowed it from elsewhere.&lt;br /&gt;&lt;br /&gt;The Cheney algorithm leaves a 'forwarding' pointer in fromspace to identify objects which have been evacuated to tospace.  When looking at a pointer in fromspace, you need to do an address range check on it to figure out which space it points to.  This is relatively expensive.  What I do instead is store a sentinel in place of the object header, and store the forwarding address immediately after it.  Then the scan can identify forwarded objects by just looking for the sentinel.&lt;br /&gt;&lt;br /&gt;Unfortunately, this breaks for zero-element tuples - there's nowhere to store the forwarding pointer.&lt;br /&gt;&lt;br /&gt;Normally, zero-element tuples shouldn't exist - it's more efficient to represent such an object by an immediate object (like 'nil').  This works for everything - except for vectors.  Vectors are by their nature run-time beasts that &lt;span style="font-style:italic;"&gt;must&lt;/span&gt; support zero length.&lt;br /&gt;&lt;br /&gt;So I've added support for a new immediate type - TC_EMPTY_VECTOR, which will have to be checked for at runtime, for example in "vector-length".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-4599754486558594087?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/4599754486558594087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/12/avoiding-address-range-checks-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4599754486558594087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4599754486558594087'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/12/avoiding-address-range-checks-in.html' title='avoiding address range checks in the copying collector'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-2720880193174201213</id><published>2009-12-12T17:11:00.000-08:00</published><updated>2009-12-12T17:30:26.015-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='solver'/><title type='text'>More speedups for the solver</title><content type='html'>When fed large chunks of pre-initialized data (in this case parser tables), the type solver fell over.  It was taking on the order of minutes to solve about 1000 lines of parser table (which is nowhere near the size of the full parser).&lt;br /&gt;&lt;br /&gt;The problem was that the split/unname phase of the solver doesn't kick in until the type of a particular node is completely solved - and this type was running to over 10,000 type variables.  This was triggering a lot of nasty N&amp;sup2; behavior in the solver, which shunts equations in and out of the unifier as it fuses/decomposes them.&lt;br /&gt;&lt;br /&gt;The fix I found is to trigger an 'extra' unname phase whenever 1000 tvars have been added to an s_let() frame.  This cut the time down from 1:20 to 8 seconds.&lt;br /&gt;&lt;br /&gt;Another thing I'm considering - in order to avoid the 'overly specific type' problem - which really goes crazy when fed literal lists... I may try to type variant constructors as a funcall instead.&lt;br /&gt;&lt;br /&gt;One last possibility - to add datatype declarations back, and just give up on the row-based variants.  I don't want to do that, because I think they have a very pythonic feel to them.&lt;br /&gt;&lt;br /&gt;p.s. I threw up a new tarball a few minutes ago.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-2720880193174201213?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/2720880193174201213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/12/more-speedups-for-solver.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2720880193174201213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/2720880193174201213'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/12/more-speedups-for-solver.html' title='More speedups for the solver'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-4262712853498413635</id><published>2009-12-07T19:15:00.000-08:00</published><updated>2009-12-07T19:47:06.349-08:00</updated><title type='text'>Typed call-with-current-continuation?</title><content type='html'>I ran into an interesting problem today.  In certain use cases, make-generator fails to type correctly:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define (make-generator producer)&lt;br /&gt; (let ((ready #f)&lt;br /&gt;       ;; just holding useless continuations&lt;br /&gt;       (caller (call/cc id))&lt;br /&gt;       (saved-point (call/cc id)))&lt;br /&gt;&lt;br /&gt;   (define (entry-point)&lt;br /&gt;     (call/cc&lt;br /&gt;      (lambda (k)&lt;br /&gt;        (set! caller k)&lt;br /&gt;        (if ready&lt;br /&gt;            &lt;span style="color: rgb(255, 0, 0);"&gt;(saved-point #f)&lt;/span&gt;&lt;br /&gt;            (producer yield)))))&lt;br /&gt;&lt;br /&gt;   (define (yield v)&lt;br /&gt;     (call/cc&lt;br /&gt;      (lambda (k)&lt;br /&gt;        (set! ready #t)&lt;br /&gt;        (set! saved-point k)&lt;br /&gt;        (caller v))))&lt;br /&gt;   entry-point&lt;br /&gt;   ))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note the call (saved-point #f).  This is returning #f to a normally-ignored continuation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define (make-int-generator n)&lt;br /&gt;  (make-generator&lt;br /&gt;   (lambda (consumer)&lt;br /&gt;     (let loop ((n 0))&lt;br /&gt;       &lt;span style="color: rgb(255, 0, 0);"&gt;(consumer n)&lt;/span&gt;&lt;br /&gt;       (loop (+ n 1))))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Depending on where you place a call to your consumer function, the continuation may or may not be ignored.  I got different results depending on whether I called an external function to produce values, or an inline loop.  I thought maybe by rewriting make-generator using lower-level prims putcc and getcc, I could make the problem go away.&lt;br /&gt;&lt;br /&gt;Although it has simplified make-generator, the problem hasn't really gone away:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define (make-generator producer)&lt;br /&gt;  (let ((ready #f)&lt;br /&gt;        ;; holding useless continuations&lt;br /&gt;        (caller (getcc))&lt;br /&gt;        (saved-point (getcc))&lt;br /&gt;        )&lt;br /&gt;    (define (entry-point)&lt;br /&gt;      (set! caller (getcc))&lt;br /&gt;      (if ready&lt;br /&gt;          (putcc saved-point #u)&lt;br /&gt;          (producer yield)))&lt;br /&gt;    (define (yield v)&lt;br /&gt;      (set! saved-point (getcc))&lt;br /&gt;      (set! ready #t)&lt;br /&gt;      (putcc caller v))&lt;br /&gt;    entry-point&lt;br /&gt;    ))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I made the problem go away by changing the type declaration for putcc:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define (putcc k r)&lt;br /&gt;  (%%cexp (continuation 'a -&gt; 'b) "(k=%s, %s)" k r))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It used to read (continuation 'a -&gt; 'a), and if you look at the tiny bit of C code there that's exactly what it does.  However.  We're talking about continuations here.  It's very difficult to wrap my head around what it does 'in the real world'.&lt;br /&gt;&lt;br /&gt;I'm sure that my getcc/putcc are not new, they're just the obvious way to save and store continuations.  Have I typed this correctly, or have I waved my hand?  How do the other typed languages deal with this problem?&lt;br /&gt;&lt;br /&gt;One solution I tried was to pass make-generator an extra argument, of the generated type, and use that for the call to saved-point.  It feels wrong, but ultimately may be the cleanest approach.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-4262712853498413635?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/4262712853498413635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/12/typed-call-with-current-continuation.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4262712853498413635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/4262712853498413635'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/12/typed-call-with-current-continuation.html' title='Typed call-with-current-continuation?'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-1207391916666965632</id><published>2009-12-02T13:54:00.000-08:00</published><updated>2009-12-02T14:06:50.447-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='solver'/><category scheme='http://www.blogger.com/atom/ns#' term='status'/><title type='text'>Status Update</title><content type='html'>I've spent some time trying to speed up the type solver.  My most complicated test is probably 't20.scm', which tests a generated lexer.  Since it uses symbols it includes the entire library, including red-black trees.&lt;br /&gt;&lt;br /&gt;I was able to trim the type reconstruction down from 50 seconds to about 7.  I did this mainly by 'pruning' the set of equations making up a solved type scheme - keeping only those directly or indirectly referenced by the root type variables for the scheme.  This seems to have lost me some of the outrageous type specificity, and seems similar to what Pottier's &lt;span style="font-style: italic;"&gt;mini-prototype&lt;/span&gt; code does.&lt;br /&gt;&lt;br /&gt;The 7 seconds for this is actually closer to 3.5s, since I run the typer twice.  I think I can live with this speed for a while... that's to compile about 65KB of raw scheme code.&lt;br /&gt;&lt;br /&gt;Next up: implement the LR(1) parse engine, then put the file I/O code,  lexer, and parser all together for the first time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-1207391916666965632?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/1207391916666965632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/12/status-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/1207391916666965632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/1207391916666965632'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/12/status-update.html' title='Status Update'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-7646116879148379667</id><published>2009-11-21T15:07:00.000-08:00</published><updated>2009-11-21T15:12:28.655-08:00</updated><title type='text'>Google's book search</title><content type='html'>Google's book search just came in &lt;span style="font-style: italic;"&gt;very&lt;/span&gt; handy... I came across a phrase in ATTPL using the term '&lt;span style="font-style: italic;"&gt;dominated&lt;/span&gt;', and I wasn't completely sure of its definition.  And of course, I couldn't remember where in 100 pages it was defined.&lt;br /&gt;&lt;br /&gt;Fine, I'll search the Postscript version of the chapter that I have on hand.  Wait, no.  That doesn't work.  PS != PDF.  Sigh.&lt;br /&gt;&lt;br /&gt;So I typed in a unique phrase from the book: that found the book on Google Books.  Then I simply searched for the term.  Wow, it immediately told me &lt;a href="http://books.google.com/books?id=A5ic1MPTvVsC&amp;amp;pg=PA449&amp;amp;lpg=PA449&amp;amp;dq=%22directly+or+indirectly+dominated+%28with+respect+to+U%29&amp;amp;source=bl&amp;amp;ots=PmsElFbv7s&amp;amp;sig=n7KsHwLTFLrR5-xV0FsNwfmtGH4&amp;amp;hl=en&amp;amp;ei=CnAIS6jtJJHGtAOEhJnBCQ&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;ct=result&amp;amp;resnum=1&amp;amp;ved=0CAoQ6AEwAA#v=onepage&amp;amp;q=dominated&amp;amp;f=false"&gt;exactly what I wanted to know&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-7646116879148379667?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/7646116879148379667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/11/googles-book-search.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7646116879148379667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/7646116879148379667'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/11/googles-book-search.html' title='Google&apos;s book search'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3178795045227825287</id><published>2009-11-18T20:33:00.000-08:00</published><updated>2009-11-18T20:36:02.189-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='inliner'/><category scheme='http://www.blogger.com/atom/ns#' term='solver'/><title type='text'>Typing Twice</title><content type='html'>I was having trouble propagating type information through the inlining pass.  The source nodes have types attached to them, and you can carefully copy it when instantiating each function body... but in some cases the inlined types should be more accurate than they are.&lt;br /&gt;&lt;br /&gt;Easy solution, run the type solver on the node tree again!&lt;br /&gt;&lt;br /&gt;This should also help find bugs in the inliner... if something passes muster the first pass, it should definitely go through after inlining.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3178795045227825287?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3178795045227825287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/11/typing-twice.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3178795045227825287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3178795045227825287'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/11/typing-twice.html' title='Typing Twice'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-3797295928463503042</id><published>2009-11-16T17:27:00.000-08:00</published><updated>2009-11-18T20:28:12.695-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parser'/><category scheme='http://www.blogger.com/atom/ns#' term='variants'/><title type='text'>The Resurrected Lexer</title><content type='html'>I have resurrected the lexer, after reworking lots of supportive library code, including vectors, symbols, the symbol table, lists, etc...&lt;br /&gt;&lt;br /&gt;The new variant datatypes seem very comfortable to me.  If you'd like to see the lexer working, compile and execute tests/t20.scm:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;[rushing@dark ~/src/irken]$ tests/t20 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 newline ""}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 keyword "def"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 whitespace " "}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 ident "thing"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 whitespace " "}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 lparen ""}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 ident "x"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 rparen ""}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 colon ""}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 newline ""}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 whitespace "  "}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 ident "return"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 whitespace " "}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 ident "x"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 whitespace " "}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 addop "+"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 whitespace " "}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 number "5"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{u8 newline ""}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#t&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{total ticks: 28843224 gc ticks: 0}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: times new roman;"&gt;Note that "&lt;/span&gt;&lt;span style="font-family: times new roman;font-family:courier new;" &gt;{u8 ...}&lt;/span&gt;&lt;span style="font-family: times new roman;"&gt;" is how the printer outputs the &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family: times new roman;"&gt;(:token&lt;/span&gt;&lt;kind&gt;&lt;value&gt;&lt;span style="font-family: times new roman;"&gt; kind value) &lt;span style="font-family: times new roman;"&gt;constructor.  Each variant constructor is assigned a unique integer tag.  You'll see the same (somewhat confusing) output when playing with lists - I need to either pre-allocate (and thus reserve) certain constructor names - or quit using the builtin printer code (which is in C).  I'm not sure that it's practical to teach the C printer how to print out variants, since the user can use them in different ways for different purposes.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/value&gt;&lt;/kind&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-3797295928463503042?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/3797295928463503042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/11/resurrected-lexer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3797295928463503042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/3797295928463503042'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/11/resurrected-lexer.html' title='The Resurrected Lexer'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5145015724555605651.post-478485491216268126</id><published>2009-11-15T17:07:00.000-08:00</published><updated>2009-11-18T20:28:48.671-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parser'/><title type='text'>Choosing a Parser</title><content type='html'>Here's the problem.  I need a parser for a python-like language, but written in Irken.  Of course there are no parser generators for Irken, &lt;span style="font-style: italic;"&gt;yet&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;My first sneaky plan was to generate a set of parsing tables, and then implement the parser engine in Irken.  [This is similar to my approach with the lexer - the lexer tables are generated by Python code, and emit Irken code].  I like dparser, but after looking at the parsing engine, it looked a bit intense for my purposes.  I then started playing with Earley parsers.  You can write an Earley parser in an &lt;span style="font-style: italic;"&gt;amazingly&lt;/span&gt; &lt;a href="http://www.nightmare.com/rushing/python/earley.py"&gt;small amount of code&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But Earley parsers aren't really table-driven, and it sounds like performance will be an issue.&lt;br /&gt;&lt;br /&gt;Then I discovered Jason Evans' &lt;a href="http://www.canonware.com/Parsing/"&gt;"Parsing.py" module.&lt;/a&gt;  It's perfect.  It generates a bog standard set of LR(1) tables.  However, there was still a big gap between Python/Grammar/Grammar and the input needed by Parsing.py (which consists of a class for each terminal and non-terminal, and a method for each reduction - annotated with docstring-based reduction rules).&lt;br /&gt;&lt;br /&gt;To fill that gap, I needed two things:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;A parser for the python meta-grammar syntax.&lt;/li&gt;&lt;li&gt;A translator from that grammar into a Parsing.py parser.&lt;/li&gt;&lt;/ol&gt;You'll find both in my &lt;a href="http://www.nightmare.com/rushing/python/parsing/"&gt;python/parsing subdirectory&lt;/a&gt;, enjoy!&lt;br /&gt;&lt;br /&gt;[Thanks to John Plevyak for assistance with dparser]&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nightmare.com/rushing/python/earley.py"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5145015724555605651-478485491216268126?l=alien.nightmare.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alien.nightmare.com/feeds/478485491216268126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://alien.nightmare.com/2009/11/choosing-parser.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/478485491216268126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5145015724555605651/posts/default/478485491216268126'/><link rel='alternate' type='text/html' href='http://alien.nightmare.com/2009/11/choosing-parser.html' title='Choosing a Parser'/><author><name>Sam Rushing</name><uri>http://www.blogger.com/profile/13115847299260965994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://1.bp.blogspot.com/_aehLxXOI41U/SwCqlAaCGHI/AAAAAAAAC38/CUxu0RvB-Jo/s1600-R/gir-invader-zim-327818_300_351.jpg'/></author><thr:total>1</thr:total></entry></feed>
