<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.1.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>Sufficiently Small</title>
	<link>http://www.smallshire.org.uk/sufficientlysmall</link>
	<description>sin(x) = x</description>
	<pubDate>Fri, 11 Jul 2008 14:13:54 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.1.2</generator>
	<language>en</language>
			<item>
		<title>Compiling variant function return types in BBC BASIC</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2007/06/19/compiling-variant-function-return-types-in-bbc-basic/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2007/06/19/compiling-variant-function-return-types-in-bbc-basic/#comments</comments>
		<pubDate>Tue, 19 Jun 2007 13:39:51 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[software]]></category>

		<category><![CDATA[computing]]></category>

		<category><![CDATA[.NET]]></category>

		<category><![CDATA[OWL BASIC]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/2007/06/19/compiling-variant-function-return-types-in-bbc-basic/</guid>
		<description><![CDATA[Some significant challenges to compiling BBC BASIC have been raised by Richard Russell, maintainer of BBC Basic for Windows. I have decided to explore the issues he raises through further posts here, rather than through responses to his earlier comments, since they will be quite long.
Today, we will look at the problem of the return [...]]]></description>
			<content:encoded><![CDATA[<p>Some significant <a href="http://www.smallshire.org.uk/sufficientlysmall/2007/06/10/writing-a-bbc-basic-compiler-for-the-clr/#comment-1579">challenges</a> to compiling BBC BASIC have been raised by Richard Russell, maintainer of BBC Basic for Windows. I have decided to explore the issues he raises through further posts here, rather than through responses to his earlier comments, since they will be quite long.</p>
<p>Today, we will look at the problem of the return type of functions not being known until run-time. Richard presented an example, which by his own admission was somewhat contrived, which nonetheless serves to illustrate the point.  Of course, this also applies to the built in function EVAL which may return any of the standard BBC BASIC types.</p>
<p>Richard&#8217;s example was for <code>FNunsuretype</code>, reproduced below, which I&#8217;ve incorporated into a simple, runnable program:</p>
<div class="hl-surround" ><div class="hl-main"><pre>a% = FNunsuretype
b$ = FNunsuretype
PRINT FNunsuretype
END

DEF FNunsuretype : LOCAL R%
R% = RND(2)
IF R% = 1 THEN = 12345 ELSE = “a string”</pre></div></div>
<p>As we can see, the function gives a fifty-fifty chance of returning either an integer or a string. Obviously the program has a 25% chance of failing with a Type Mismatch error when run, but we&#8217;ll ignore that for now. Let&#8217;s take a look at the equivalent code in C#, which is most definitely a compiled language:</p>
<div class="hl-surround" ><div class="hl-main"><pre>using System;

class Program
{
    static System.Random rnd = new System.Random();

    static void Main(string[] args)
    {
        int a = (int) UnsureType();
        string b = (string) UnsureType();
        Console.WriteLine(UnsureType());
    }

    static object UnsureType()
    {
        int r = rnd.Next(1);
        if (r == 0)
        {
            return 12345;
        }
        else
        {
            return &quot;a string&quot;;
        }
    }
}</pre></div></div>
<p>Here the function <code>UnsureType()</code> also returns either a number or a string with 50% probability, but we use the autoboxing feature of C# to wrap the integer or string in an object, which is what the function returns. Note that to unbox the type, we must use a cast, although not in the case of <code>Console.WriteLine</code> which calls the <code>ToString</code> method on the object, which in turns calls the <code>ToString</code> method on the boxed basic type. Note that this program also has a 25% chance of failing with an InvalidCastException, which is equivalent to a Type Mismatch in BBC BASIC.</p>
<p>Using static analysis techniques it should be possible to determine at compile time whether a BBC BASIC function needs to box its return value in an object.  Most functions will have exit points where the return type is well-defined, or can be inferred from the type of the returned expression. Such functions can be compiled with a fixed return type. Those functions which have multiple but differing return types, or unknowable return types, such as returned by EVAL, will need to box their return values in an object. It should then be possible at the call-site of the function to determine whether an implicit cast is needed to convert the returned object to a useful value.</p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2007/06/19/compiling-variant-function-return-types-in-bbc-basic/feed/</wfw:commentRss>
		</item>
		<item>
		<title>BBC BASIC lexer with PLY</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2007/06/11/bbc-basic-lexer-with-ply/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2007/06/11/bbc-basic-lexer-with-ply/#comments</comments>
		<pubDate>Mon, 11 Jun 2007 22:29:58 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[software]]></category>

		<category><![CDATA[computing]]></category>

		<category><![CDATA[.NET]]></category>

		<category><![CDATA[OWL BASIC]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/2007/06/11/bbc-basic-lexer-with-ply/</guid>
		<description><![CDATA[So having decided to build a BBC BASIC compiler for the CLR, in IronPython using PLY, the first step is to build a functioning lexer to tokenize the text input of a BBC BASIC program. BBC BASIC is normally stored in a binary tokenized format, where each keyword is stored as a one- or two-byte [...]]]></description>
			<content:encoded><![CDATA[<p>So having decided to build a <a href="http://www.smallshire.org.uk/sufficientlysmall/2007/06/10/writing-a-bbc-basic-compiler-for-the-clr/">BBC BASIC compiler for the CLR</a>, in IronPython using PLY, the first step is to build a functioning lexer to tokenize the text input of a BBC BASIC program. BBC BASIC is normally stored in a binary tokenized format, where each keyword is stored as a one- or two-byte value, although I won&#8217;t be supporting that format at this stage in the project. BBC Basic for Windows (BB4W) also uses a tokenized storage format, although <a href="http://http://bb4w.wikispaces.com/Notes+for+RISC+OS+users">this page</a> suggests that the token formats are different.  For now, we&#8217;ll stick to plain text.</p>
<p>The function of the lexer is to break down the stream of text into discrete tokens which can be passed onto the parser for syntactic analysis.</p>
<h1>Identity Parade</h1>
<p>My first attempt at building lexer was by the <a href="http://www.dabeaz.com/ply/ply.html">PLY book</a>. Most of the tokens for operators were specified as simple strings, and the BASIC commands such as <code>INPUT, PRINT, TAB</code> and <code>LEFT$</code> were handled in the manner described in the manual, by using a dictionary mapping keywords to token names, and using the token rule for identifiers to catch these:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">reserved</span><span class="hl-default"> = {
    </span><span class="hl-quotes">'</span><span class="hl-string">ABS</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">ABS</span><span class="hl-quotes">'</span><span class="hl-default">,
    </span><span class="hl-quotes">'</span><span class="hl-string">ACS</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">ACS</span><span class="hl-quotes">'</span><span class="hl-default">,
    </span><span class="hl-quotes">'</span><span class="hl-string">ADVAL</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">ADVAL</span><span class="hl-quotes">'</span><span class="hl-default">,

    ...

    </span><span class="hl-quotes">'</span><span class="hl-string">STR$</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">STR_STR</span><span class="hl-quotes">'</span><span class="hl-default">,
    </span><span class="hl-quotes">'</span><span class="hl-string">STRING$</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">STRING_STR</span><span class="hl-quotes">'</span><span class="hl-default">

    ...

    
    </span><span class="hl-quotes">'</span><span class="hl-string">VPOS</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">VPOS</span><span class="hl-quotes">'</span><span class="hl-default">,
    </span><span class="hl-quotes">'</span><span class="hl-string">WAIT</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">WAIT</span><span class="hl-quotes">'</span><span class="hl-default">
}

</span><span class="hl-reserved">def </span><span class="hl-identifier">t_ID</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">[@a-zA-Z_`][a-zA-Z_0-9`]*[$%&amp;]?</span><span class="hl-quotes">'
    </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">type</span><span class="hl-default"> = </span><span class="hl-identifier">reserved</span><span class="hl-default">.</span><span class="hl-identifier">get</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">ID</span><span class="hl-quotes">'</span><span class="hl-brackets">) </span><span class="hl-comment"># Check for reserved
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t</span></pre></div></div>
<p>Note how the regex specifing a valid identifier has been adjusted for BBC BASIC identifiers which can take the following forms: <code>A%</code> (static integer variable), <code>bravo%</code> (integer variable), <code>charlie&#038;</code> (byte variable - from BB4W), <code>delta</code> (float variable) and  <code>echo$</code> (string variable). I was also surprised to learn that ASCII 96 is also valid in identifiers! On the BBC Micro this was thr £ symbol, but is more correctly the ` grave accent, including on RISC OS.</p>
<p>I soon discovered several problems with this simple scheme. In general, BBC BASIC keywords cannot form the first part of an identifer. For example, <code>FOREVER</code> will be lexed as <code>('FOR', 'FOR'), ('ID', 'EVER')</code> where the first member of each tuple is the token type, and the second is the token value. </p>
<p>The PLY manual has the following to say on the topic:</p>
<blockquote><p>Note: You should avoid writing individual rules for reserved words. For example, if you write rules like this,</p>
<p>    t_FOR   = r&#8217;for&#8217;<br />
    t_PRINT = r&#8217;print&#8217;</p>
<p>those rules will be triggered for identifiers that include those words as a prefix such as &#8220;forget&#8221; or &#8220;printed&#8221;. This is probably not what you want.</p></blockquote>
<p>Au contraire!</p>
<p>In the case of BBC BASIC this is (almost) exactly what we want.</p>
<p>However, there is additional complexity. For obscure reasons, possibly to do with squeezing all this into 16 kB in the original ROM, there are 38 exceptions to this rule; for example <code>TIMER</code> is a valid identifer, even though it begins with the keyword <code>TIME</code>. And if this complexity wasn&#8217;t enough, some keywords form the prefix of other keywords. In fact this is surprisingly common: <code>GET > GET$; END > ENDIF, ENDPROC, ENDCASE, ENDWHILE; INKEY > INKEY$, OF > OFF; TO > TOP</code>. So we must ensure the lexer matches longer keywords before shorter ones.</p>
<p>By default, PLY sorts lexing rules specified as strings by decreasing length <i>after</i> all of the lexing rules specified by functions.  Since our rule for identifiers must be a function, somewhat tediously, all of the keywords which cannot form the start of identifers must have tokens specified by functions before the rule for identifiers. Keywords which can form the start of identifers are handled using the original mechanism of looking up their value in a dictionary of values to token names.</p>
<p>Following the above changes, our lexer code is now structured like this:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment"># Nine letter keywords
</span><span class="hl-reserved">def </span><span class="hl-identifier">t_OTHERWISE</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">OTHERWISE</span><span class="hl-quotes">'
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t

</span><span class="hl-reserved">def </span><span class="hl-identifier">t_RECTANGLE</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">RECTANGLE</span><span class="hl-quotes">'
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t

</span><span class="hl-comment"># Eight letter keywords
</span><span class="hl-reserved">def </span><span class="hl-identifier">t_ENVELOPE</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">ENVELOPE</span><span class="hl-quotes">'
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t

</span><span class="hl-comment"># Seven letter keywords
</span><span class="hl-reserved">def </span><span class="hl-identifier">t_ELLIPSE</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">ELLIPSE</span><span class="hl-quotes">'
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t</span><span class="hl-default">

...

</span><span class="hl-reserved">def </span><span class="hl-identifier">t_OR</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">OR</span><span class="hl-quotes">'
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t

</span><span class="hl-reserved">def </span><span class="hl-identifier">t_TO</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">TO</span><span class="hl-quotes">'
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t

</span><span class="hl-comment"># Reserved identifiers
</span><span class="hl-identifier">reserved</span><span class="hl-default"> = {
    </span><span class="hl-quotes">'</span><span class="hl-string">ENDWHILE</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">ENDWHILE</span><span class="hl-quotes">'</span><span class="hl-default">,
    </span><span class="hl-quotes">'</span><span class="hl-string">ENDCASE</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">ENDCASE</span><span class="hl-quotes">'</span><span class="hl-default">,
...
    </span><span class="hl-quotes">'</span><span class="hl-string">BY</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">BY</span><span class="hl-quotes">'</span><span class="hl-default">,
    </span><span class="hl-quotes">'</span><span class="hl-string">OF</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">OF</span><span class="hl-quotes">'</span><span class="hl-default">,
    </span><span class="hl-quotes">'</span><span class="hl-string">PI</span><span class="hl-quotes">'</span><span class="hl-default"> : </span><span class="hl-quotes">'</span><span class="hl-string">PI</span><span class="hl-quotes">'</span><span class="hl-default">
            }

</span><span class="hl-reserved">def </span><span class="hl-identifier">t_ID</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">[@a-zA-Z_`][a-zA-Z_0-9`]*[$%&amp;]?</span><span class="hl-quotes">'
    </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">type</span><span class="hl-default"> = </span><span class="hl-identifier">reserved</span><span class="hl-default">.</span><span class="hl-identifier">get</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">ID</span><span class="hl-quotes">'</span><span class="hl-brackets">) </span><span class="hl-comment"># Check for reserved identifiers
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t</span></pre></div></div>
<p>In this code, use of a dictionary is overkill since all the key and values are the same; a set would suffice.</p>
<p>Finally, some keywords are &#8216;decorated&#8217; by trailing symbols. A quick flick through the <a href="http://bbc.nvg.org/doc/BBCUserGuide-1.00.pdf">BBC Microcomputer System User Guide</a> [2.6 MB PDF] suggests that the trailing hash of <code>BGET#</code> and the trailing dollar of <code>CHR$</code> are integral parts of the keywords. However, some investigation on the command line will reveal that all is not consistent!</p>
<p><img src='http://www.smallshire.org.uk/sufficientlysmall/wp-content/uploads/2007/06/basic_keywords1.png' alt='BBC BASIC keyword tokens' /></p>
<p>Here we can see that the first use of <code>BGET#3</code> is understood, since the interpreter tells us that we have supplied an invalid channel number. In apparent contradition to the User Guide, the second form <code>BGET #3</code> with a space before the hash is <i>also</i> understood, as again the interpreter complains about the channel number we supplied. So in this case, and indeed for all the other keywords &#8217;suffixed&#8217; with hash in the manual we find that the hash is not considered to be part of the keyword. Interestingly, if we omit the hash completely (not shown in the session above) BASIC complains with a error <b>Missing #</b>. This suggests that the hash is actually a <i>prefix</i> for the integer channel number, in effect it is an operator which transforms an integer into a channel.</p>
<p>The example with <code>CHR$(96)</code> illustrates that the dollar is an integral part of the keyword, since if a space is inserted before the dollar, BASIC thinks <code>CHR</code> is a variable identifier. Since <code>CHR$</code> is a function, rather than a statement, the parentheses here are optional.</p>
<p>The final example is the most surprising, and caused me a good deal of confusion for a while. As we can see, both <code>TAB</code> and <code>SPC</code> work with parentheses, and <code>SPC</code> will happily work without them. Nonetheless, <code>TAB</code> insists on the parentheses being present, and furthermore, will <i>not</i> permit any space before the opening parenthesis!  Therefore, the opening parenthesis is effectively part of the <code>TAB(</code> keyword token.</p>
<p>Further investigation reveals that several other keywords fall into the same category, some of them being decorated with more than one trailing symbol: <code>RIGHT$( , STRING$( , INSTR( , LEFT$( , POINT( , MID$(</code> and of course <code>TAB(</code>. </p>
<p>All of this needs to be incorporated into the lexer definition, so that the correct rule for <code>RIGHT$(</code> becomes,</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">t_RIGHT_STR_LPAREN</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">RIGHT</span><span class="hl-special">\$\(</span><span class="hl-quotes">'
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t</span></pre></div></div>
<h1>Smooth operator</h1>
<p>The rules for operators are standard, and can be implemented as token strings. PLY will sort them by decreasing length in order to get <code>>>></code> to match before <code>>></code>. I&#8217;ve decided to implement the extended set of operators supported by BB4W, such as <code>*=</code>.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment"># Operators
</span><span class="hl-identifier">t_QUERY</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\?</span><span class="hl-quotes">'
</span><span class="hl-identifier">t_PLING</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\!</span><span class="hl-quotes">'
</span><span class="hl-identifier">t_PIPE</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\|</span><span class="hl-quotes">'
</span><span class="hl-identifier">t_HASH</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\#</span><span class="hl-quotes">'</span><span class="hl-default">
...
</span><span class="hl-identifier">t_LBRAC</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\[</span><span class="hl-quotes">'
</span><span class="hl-identifier">t_RBRAC</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\]</span><span class="hl-quotes">'
</span><span class="hl-identifier">t_CARET</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\^</span><span class="hl-quotes">'
</span><span class="hl-identifier">t_TILDE</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">~</span><span class="hl-quotes">'
</span><span class="hl-identifier">t_DOT</span><span class="hl-default"> = </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\.</span><span class="hl-quotes">'</span></pre></div></div>
<p>Note that the hash from BGET# also makes it into this this as a &#8216;channel&#8217; operator.</p>
<h1>No comment</h1>
<p>Comments in BASIC start with REM and continue until the next carriage return. Here we just look for REM </p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">t_COMMENT</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">REM[^</span><span class="hl-special">\n</span><span class="hl-string">]*</span><span class="hl-quotes">'
    </span><span class="hl-reserved">pass</span></pre></div></div>
<p>I also decided to implement the line continuations supported by BB4W. These use a trailing backslash on one line, followed by a leading backslash on the subsequent line, in order to split long lines over several lines in the file. Again, this is easily dealt with using a regular expression.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment"># Define a rule so we can split lines with a
# trailing backslash and leading backslash
</span><span class="hl-reserved">def </span><span class="hl-identifier">t_CONTINUATION</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\[ \t</span><span class="hl-string">]*[</span><span class="hl-special">\r\n</span><span class="hl-string">][ </span><span class="hl-special">\t</span><span class="hl-string">]*</span><span class="hl-special">\ </span><span class="hl-quotes">'
    </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">lexer</span><span class="hl-default">.</span><span class="hl-identifier">lineno</span><span class="hl-default"> += </span><span class="hl-number">1
    </span><span class="hl-reserved">pass</span></pre></div></div>
<h1>Literally, how long is a piece of string?</h1>
<p>The final piece of the puzzle, are literals, which in the case of BBC BASIC means strings, floats and integers in decimal, hex, or binary.</p>
<p>Strings represent a particular challenge. Unlike most programming language which use a backslash to escape special characters in literal strings, BBC BASIC supports escaping of only one character, the double-quote ASCII 34 using the convention of doubling.  <code>"Nat ""King"" Cole"</code> gives the string <strong>Nat &#8220;King&#8221; Cole</strong>. This is identified using a cryptic regex, followed by replacement of doubled double-quotes with single double-quotes.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">t_LITERAL_STRING</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">&quot;((?:[^&quot;]+|&quot;&quot;)*)&quot;(?!&quot;)</span><span class="hl-quotes">'
    </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-default"> = </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-code">:-</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-default">.</span><span class="hl-identifier">replace</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">&quot;&quot;</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">&quot;</span><span class="hl-quotes">'</span><span class="hl-brackets">)
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t</span></pre></div></div>
<p>This regex reads something like: <i>A double-quote followed by zero or more non-double-quote characters </i>or<i> a pair of double-quotes, followed by a double quote, that is </i>not<i> followed by another double quote.</i> Phew!</p>
<p>The literal numbers are straightforward:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">t_LITERAL_FLOAT</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">[+-]?</span><span class="hl-special">\d</span><span class="hl-string">*</span><span class="hl-special">\.\d</span><span class="hl-string">+(E([+-]?</span><span class="hl-special">\d</span><span class="hl-string">+))?</span><span class="hl-quotes">'
    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-default"> = </span><span class="hl-builtin">float</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">)
    </span><span class="hl-reserved">except ValueError</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Number %s is too large!</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t

</span><span class="hl-reserved">def </span><span class="hl-identifier">t_LITERAL_INTEGER</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-special">\d</span><span class="hl-string">+</span><span class="hl-quotes">'
    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-default"> = </span><span class="hl-builtin">int</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">)
    </span><span class="hl-reserved">except ValueError</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Number %s is too large!</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value
        t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-default"> = </span><span class="hl-number">0
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t

</span><span class="hl-reserved">def </span><span class="hl-identifier">t_LITERAL_HEX_INTEGER</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">&amp;[</span><span class="hl-special">\d</span><span class="hl-string">A-Fa-f]+</span><span class="hl-quotes">'
    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-default"> = </span><span class="hl-builtin">int</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-code">:</span><span class="hl-brackets">]</span><span class="hl-code">, </span><span class="hl-number">16</span><span class="hl-brackets">)
        </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">type</span><span class="hl-default"> = </span><span class="hl-quotes">'</span><span class="hl-string">LITERAL_INTEGER</span><span class="hl-quotes">'
    </span><span class="hl-reserved">except ValueError</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Number %s is too large!</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value
        t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-default"> = </span><span class="hl-number">0
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t

</span><span class="hl-reserved">def </span><span class="hl-identifier">t_LITERAL_BINARY_INTEGER</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">r</span><span class="hl-quotes">'</span><span class="hl-string">%[01]+</span><span class="hl-quotes">'
    </span><span class="hl-reserved">try</span><span class="hl-default">:
        </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-default"> = </span><span class="hl-builtin">int</span><span class="hl-brackets">(</span><span class="hl-identifier">t</span><span class="hl-code">.</span><span class="hl-identifier">value</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-code">:</span><span class="hl-brackets">]</span><span class="hl-code">, </span><span class="hl-number">2</span><span class="hl-brackets">)
        </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">type</span><span class="hl-default"> = </span><span class="hl-quotes">'</span><span class="hl-string">LITERAL_INTEGER</span><span class="hl-quotes">'
    </span><span class="hl-reserved">except ValueError</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Number %s is too large!</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">t</span><span class="hl-default">.</span><span class="hl-identifier">value
        t</span><span class="hl-default">.</span><span class="hl-identifier">value</span><span class="hl-default"> = </span><span class="hl-number">0
    </span><span class="hl-reserved">return </span><span class="hl-identifier">t</span></pre></div></div>
<p>Note how the token types of the <code>LITERAL_HEX_INTEGER</code> and <code>LITERAL_BINARY_INTEGER</code> are converted to <code>LITERAL_INTEGER</code>.</p>
<h1>Putting it all together&#8230;</h1>
<p>Putting all this together, with some standard error handling, ignorable whitespace characters and newline detection, we have a functioning lexer.  Using some boilerplate to read the contents of a text file and feed it into the lexer, we can test our construction on some genuine code. Using the BBC BASIC implementation of <a href="http://www.99-bottles-of-beer.net/language-bbc-basic-876.html">&#8220;Ninety-nine bottles of beer&#8221;</a> shown below,</p>
<div class="hl-surround" ><div class="hl-main"><pre>REM BBC BASIC version
REM by Stelio Passaris
REM http://www.stelio.net
REM Spacing around commands is not necessary.
:
a$=&quot; bottle&quot;
s$=&quot;s&quot;
b$=&quot; of beer&quot;
c$=&quot; on the wall&quot;
t$=&quot;Take one down and pass it around:&quot;
:
VDU14:REM enables paging mode; press shift to page down.
REM Substitute above line with &quot;VDU2&quot; to send text to printer.
FOR i%=99 TO 1 STEP -1
IF i%=1 THEN s$=&quot;&quot;
IF i%&lt;99 THEN PRINT;i%;a$;s$;b$;c$;&quot;.&quot;'
PRINT;i%;a$;s$;b$;c$;&quot;,&quot;'i%;a$;s$;b$;&quot;.&quot;'t$
NEXT i%
PRINT&quot;No more&quot;;a$;&quot;s&quot;;b$;c$;&quot;.&quot;
VDU15:REM disables paging mode
REM Substitute above line with &quot;VDU3&quot; to send text to printer.</pre></div></div>
<p>yields the following tokens,</p>
<div class="hl-surround" ><div class="hl-main"><pre>&gt; python bbc_lexer.py ninety_nine_bottles.bas'
LexToken(EOL,'\n',1,21)
LexToken(EOL,'\n',2,44)
LexToken(EOL,'\n',3,70)
LexToken(EOL,'\n',4,116)
LexToken(COLON,':',5,117)
LexToken(EOL,'\n',5,118)
LexToken(ID,'a$',6,119)
LexToken(EQ,'=',6,121)
LexToken(LITERAL_STRING,' bottle',6,122)
LexToken(EOL,'\n',6,131)
LexToken(ID,'s$',7,132)
LexToken(EQ,'=',7,134)
LexToken(LITERAL_STRING,'s',7,135)
LexToken(EOL,'\n',7,138)
LexToken(ID,'b$',8,139)
LexToken(EQ,'=',8,141)
LexToken(LITERAL_STRING,' of beer',8,142)
LexToken(EOL,'\n',8,152)
LexToken(ID,'c$',9,153)
LexToken(EQ,'=',9,155)
LexToken(LITERAL_STRING,' on the wall',9,156)
LexToken(EOL,'\n',9,170)
LexToken(ID,'t$',10,171)
LexToken(EQ,'=',10,173)
LexToken(LITERAL_STRING,'Take one down and pass it around:',10,174)
LexToken(EOL,'\n',10,209)
LexToken(COLON,':',11,210)
LexToken(EOL,'\n',11,211)
LexToken(VDU,'VDU',12,212)
LexToken(LITERAL_INTEGER,14,12,215)
LexToken(COLON,':',12,217)
LexToken(EOL,'\n',12,268)
LexToken(EOL,'\n',13,331)
LexToken(FOR,'FOR',14,332)
LexToken(ID,'i%',14,336)
LexToken(EQ,'=',14,338)
LexToken(LITERAL_INTEGER,99,14,339)
LexToken(TO,'TO',14,342)
LexToken(LITERAL_INTEGER,1,14,345)
LexToken(STEP,'STEP',14,347)
LexToken(MINUS,'-',14,352)
LexToken(LITERAL_INTEGER,1,14,353)
LexToken(EOL,'\n',14,354)
LexToken(IF,'IF',15,355)
LexToken(ID,'i%',15,358)
LexToken(EQ,'=',15,360)
LexToken(LITERAL_INTEGER,1,15,361)
LexToken(THEN,'THEN',15,363)
LexToken(ID,'s$',15,368)
LexToken(EQ,'=',15,370)
LexToken(LITERAL_STRING,'',15,371)
LexToken(EOL,'\n',15,373)
LexToken(IF,'IF',16,374)
LexToken(ID,'i%',16,377)
LexToken(LT,'&lt;',16,379)
LexToken(LITERAL_INTEGER,99,16,380)
LexToken(THEN,'THEN',16,383)
LexToken(PRINT,'PRINT',16,388)
LexToken(SEMICOLON,';',16,393)
LexToken(ID,'i%',16,394)
LexToken(SEMICOLON,';',16,396)
LexToken(ID,'a$',16,397)
LexToken(SEMICOLON,';',16,399)
LexToken(ID,'s$',16,400)
LexToken(SEMICOLON,';',16,402)
LexToken(ID,'b$',16,403)
LexToken(SEMICOLON,';',16,405)
LexToken(ID,'c$',16,406)
LexToken(SEMICOLON,';',16,408)
LexToken(LITERAL_STRING,'.',16,409)
LexToken(APOSTROPHE,&quot;'&quot;,16,412)
LexToken(EOL,'\n',16,413)
LexToken(PRINT,'PRINT',17,414)
LexToken(SEMICOLON,';',17,419)
LexToken(ID,'i%',17,420)
LexToken(SEMICOLON,';',17,422)
LexToken(ID,'a$',17,423)
LexToken(SEMICOLON,';',17,425)
LexToken(ID,'s$',17,426)
LexToken(SEMICOLON,';',17,428)
LexToken(ID,'b$',17,429)
LexToken(SEMICOLON,';',17,431)
LexToken(ID,'c$',17,432)
LexToken(SEMICOLON,';',17,434)
LexToken(LITERAL_STRING,',',17,435)
LexToken(APOSTROPHE,&quot;'&quot;,17,438)
LexToken(ID,'i%',17,439)
LexToken(SEMICOLON,';',17,441)
LexToken(ID,'a$',17,442)
LexToken(SEMICOLON,';',17,444)
LexToken(ID,'s$',17,445)
LexToken(SEMICOLON,';',17,447)
LexToken(ID,'b$',17,448)
LexToken(SEMICOLON,';',17,450)
LexToken(LITERAL_STRING,'.',17,451)
LexToken(APOSTROPHE,&quot;'&quot;,17,454)
LexToken(ID,'t$',17,455)
LexToken(EOL,'\n',17,457)
LexToken(NEXT,'NEXT',18,458)
LexToken(ID,'i%',18,463)
LexToken(EOL,'\n',18,465)
LexToken(PRINT,'PRINT',19,466)
LexToken(LITERAL_STRING,'No more',19,471)
LexToken(SEMICOLON,';',19,480)
LexToken(ID,'a$',19,481)
LexToken(SEMICOLON,';',19,483)
LexToken(LITERAL_STRING,'s',19,484)
LexToken(SEMICOLON,';',19,487)
LexToken(ID,'b$',19,488)
LexToken(SEMICOLON,';',19,490)
LexToken(ID,'c$',19,491)
LexToken(SEMICOLON,';',19,493)
LexToken(LITERAL_STRING,'.',19,494)
LexToken(EOL,'\n',19,497)
LexToken(VDU,'VDU',20,498)
LexToken(LITERAL_INTEGER,15,20,501)
LexToken(COLON,':',20,503)
LexToken(EOL,'\n',20,528)
LexToken(EOL,'\n',21,591)</pre></div></div>
<p>which surely counts as a great first step towards our BBC BASIC compiler for the CLR. Next time we&#8217;ll take a look at the grammar of BBC BASIC, and begin constructing a parser.</p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2007/06/11/bbc-basic-lexer-with-ply/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Writing a BBC BASIC compiler for the CLR</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2007/06/10/writing-a-bbc-basic-compiler-for-the-clr/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2007/06/10/writing-a-bbc-basic-compiler-for-the-clr/#comments</comments>
		<pubDate>Sun, 10 Jun 2007 22:26:05 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[software]]></category>

		<category><![CDATA[8 bit]]></category>

		<category><![CDATA[computing]]></category>

		<category><![CDATA[.NET]]></category>

		<category><![CDATA[OWL BASIC]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/2007/06/10/writing-a-bbc-basic-compiler-for-the-clr/</guid>
		<description><![CDATA[Of late, I&#8217;ve picked up an interest in the CLR through learning C#. After being impressed by the performance of the .NET runtime (less so for Mono, although that&#8217;s another story) I decided that an effective way to really get to grips with the system would be to write a compiler which targets the CLR.
During [...]]]></description>
			<content:encoded><![CDATA[<p>Of late, I&#8217;ve picked up an interest in the CLR through learning C#. After being impressed by the performance of the .NET runtime (less so for Mono, although that&#8217;s another story) I decided that an effective way to really get to grips with the system would be to write a compiler which targets the CLR.</p>
<p>During a nostalgic poke around the web relating to <a href="http://en.wikipedia.org/wiki/Acorn_Computers">Acorn</a> hardware, over 12 years since my last contact with BBC BASIC, I stumbled across Richard Russell&#8217;s BBC BASIC for Windows (BB4W) which reminded me of my formative years learning to code on the BBC Model B and later various Acorn Archimedes computers under <a href="http://en.wikipedia.org/wiki/RISC_OS">RISC OS</a>. This led me to start down the road of implementing a BBC BASIC <em>compiler</em> for the CLR, although the original BBC BASIC, and BB4W are <em>interpreted</em>.  The original BBC BASIC II resided in only 16 kB of ROM, so it can&#8217;t be that much work. Can it?</p>
<p>The <a href="http://www.bbcbasic.co.uk/bbcwin/bbcwin.html">BBC Basic for Windows</a> implementation, from Russell actually goes to long lengths to provide good backwards compatibility with software originally developed for the Beeb or RISC OS, such as providing a Teletext MODE 7 equivalent, and &#8216;emulated&#8217; sound and graphics support.</p>
<p>I will be taking a different tack with this project. Rather than focus on getting old code reliant on obsolete hardware features to run, I will focus on making a viable BBC BASIC compiler for the CLR, which could be used to port existing programs to .NET/Mono. It is likely that OS or machine specific functionality such as sound and graphics will be implemented in significiantly different ways compared to the originals, for example, by giving good language-level integration with the <code>System.Console</code> class in .NET, rather than trying to emulate screen modes from Acorn hardware.</p>
<p>The toolset I settled on is as follows:</p>
<ul>
<li><a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython">IronPython</a> in which to write the compiler</li>
<li><a href="http://www.dabeaz.com/ply/">PLY</a> - the Python Lex/Yacc-a-like</li>
<li><a href="http://www.mikebuk.dsl.pipex.com/beebem/">BeebEm</a> - BBC Micro emulator with BBC BASIC II</li>
<li><a href="http://b-em.bbcmicro.com/arculator/">Arculator</a> - Acorn Archimedes emulator with BBC BASIC V</li>
<li>Documentation in the form of BBC Micro and Archimedes user manuals, and various other information and examples on the web</li>
</ul>
<p>Mostly its an experiment, and for the fun of writing a compiler. I don&#8217;t expect anybody to start creating large software systems in BBC BASIC as a result of my efforts. Far from it; there are <em>much </em>better tools today.  However, I must admit to a secret aim of producing the fastest BBC BASIC implementation yet!</p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2007/06/10/writing-a-bbc-basic-compiler-for-the-clr/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Instability Irony - DamageControl</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2006/09/11/instability-irony-damagecontrol/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2006/09/11/instability-irony-damagecontrol/#comments</comments>
		<pubDate>Mon, 11 Sep 2006 19:46:17 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[software]]></category>

		<category><![CDATA[computing]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/?p=14</guid>
		<description><![CDATA[...it is nearly always beneficial to re-write or refactor. However, every project has to break out of this loop at some point...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been following the progress of a <em>continuous integration</em> build manager called <a href="http://damagecontrol.codehaus.org/">DamageControl</a> for over two years now. DamageControl is a <a href="http://www.rubyonrails.org/">Ruby on Rails</a> based framework for triggering builds of software, whenever there is a check-in to the source control system. Essentially it fulfils the same job as <a href="http://cruisecontrol.sourceforge.net/">CruiseControl</a> and <a href="http://www.mozilla.org/tinderbox.html">Mozilla Tinderbox</a> - detecting when a build has been broken by a bad check-in, but with an attractive web-front end and some nice configuration features. DamageControl interfaces very nicely to a variety of source control systems through the <a href="http://rscm.rubyforge.org/">RSCM</a> (Ruby Source Code Management) library.</p>
<p>I&#8217;ve &#8216;lurked&#8217; on the DamageControl developers and user mailing lists long enough to get a feel for how the project is progessing. However, I&#8217;ve been disappointed that although DamageControl has gone through many version increments - I came in at DC 0.3,  we&#8217;re currently around 0.6 there has never been anything approximating a stable release.</p>
<p>Now I know as much as the next open-source contributor how difficult it is to remain committed to a project, but lack of committment doesn&#8217;t seem to be the problem here. If DamageControl were a commercial offering, it condition would be diagnosed as &#8216;inability to ship&#8217;. DamageControl is perpetually undergoing, the next big refactoring, which it is promised will lead to a &#8217;stable version&#8217;. As any experienced developer knows, software is never &#8216;finished&#8217; and it is nearly always beneficial to re-write or refactor. However, every project has to break out of this loop at some point, if only temporality, to stabilize the code and benefit user feedback and bug reports from a specific version.</p>
<p>However today, after checking back at the DC site after six months I have given up hope, DamageControl has the following message on its site:</p>
<blockquote><p>DAMAGECONTROL HAS HIBERNATED</p>
<p>It&#8217;s currently not under active development.</p>
<p>It&#8217;s not completely abandoned - development may pick up again once I &#8230;. get more time to work on it.
</p></blockquote>
<p>The first lesson is that not everything created atop Ruby on Rails will be rip-roaring success. The second lesson I take from this, for my own projects, is that there is enormous value in creating <em>something</em> that works and that is incrementally useful, even if it is merely the <a href="http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html">Simplest Thing That Could Possibly Work</a>. The third lesson is that providing something that is easy to install and start actually using, hugely increases the probability of a project being successful; having to extract specific revisions from Subversion, and run them against very stringent Ruby, Rails and other package versions is a severe hindrance. Creating a community of motivated users around the product is fundamental to success. Rather this, than a sense of unrequited expectation amongst a group of potential users who find it difficult to get involved because the code train is never moving slowly enough to leap aboard.</p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2006/09/11/instability-irony-damagecontrol/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Up the Junction - Multi-user Windows iTunes</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2006/06/11/up-the-junction-multi-user-windows-itunes/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2006/06/11/up-the-junction-multi-user-windows-itunes/#comments</comments>
		<pubDate>Sun, 11 Jun 2006 19:34:11 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[computing]]></category>

		<category><![CDATA[Internet]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/?p=15</guid>
		<description><![CDATA[Sharing iTunes between multiple local Windows users]]></description>
			<content:encoded><![CDATA[<p>By default Windows iTunes stores the music metadata, although not necessarily the music itself, in the current user&#8217;s My Music folder.  For user Alice, this will be located in,</p>
<p><code>C:\Documents and Settings\alice\My Music\iTunes\</code></p>
<p>and for Bob in</p>
<p><code>C:\Documents and Settings\bob\My Music\iTunes\</code></p>
<p>which means that the two users can&#8217;t share settings, playlists and the like easily.</p>
<p>On a Unix-a-like system we could solve this with symbolic links by linking the two iTunes directories to a common location. Of course, everybodys know that symbolic links do not feature in Windows filing systems.</p>
<p>Or do they?</p>
<p>In fact NTFS supports a feature various known as Junction Points or Reparse Points which can be used to &#8216;mount&#8217; other directories or even volumes onto the location of existing directories. The facility to create junction points is not exposed through the standard Windows user interface, presumably because of the havoc you can wreak if you don&#8217;t know what you&#8217;re doing. However, for those of us who know exactly what we&#8217;re doing, they&#8217;re just what the doctor ordered.</p>
<p>In order to create junction points you can use the free tool <a href="http://www.rekenwonder.com/linkmagic.htm">Junction Link Magic</a> from Rekenwonder Software. We&#8217;ll use it to make iTunes multi-user!</p>
<p>The following procedure is documented prior to installation of iTunes. It is possible to retrofit this to an existing iTunes installation, but you need to take care to not lose your existing iTunes settings, and its not clear how to merge the settings of existing iTunes users.</p>
<p>First we need to create the common location that different Windows iTunes users will share. So whilst logged in as an Administrator, create the directory</p>
<p><code>C:\Documents and Settings\All Users\Documents\My Music\iTunes\</code></p>
<p>Before we can create the junction points themselves, we need to create &#8216;host&#8217; folders in the correct locations, so create the following two directories:</p>
<p><code>C:\Documents and Settings\alice\My Music\iTunes\</code><br />
<code>C:\Documents and Settings\bob\My Music\iTunes\</code></p>
<p>Now, having installed Junction Link Magic, use it to create a Junction Points from each users iTunes directory to the common location. When you first launch Junction Link Magic it will spend a few minutes searching your file system for existing junction points. When this process is complete you will most likely see an empty list of junction points,</p>
<p><img src='/sufficientlysmall/wp-content/junction_link1.PNG' alt='Junction Link Magic' /></p>
<p>First we will create the junction point for Alice. Click the &#8216;Create&#8217; button and select both Alice&#8217;s host iTunes folder, and the <code>All Users</code> iTunes< folder.  Note under Windows XP the browser may show different directory 'user friendly' names such as <code>All Users\Shared Documents\Shared Music\ instead of the true directory name <code>All Users\Documents\My Music\</code>  show in the label below the browser.</p>
<p><img src='/sufficientlysmall/wp-content/junction_link2.png' alt='Junction Link Magic Create' /></p>
<p>Junction Link Magic will confirm that the operation has been successful, and show you the created junction point in the table in the main window. </p>
<p>Do the equivalent operation as required for other users on your system. Depending on how permissions are configured on your system, you may be required to switch to their user in order to create the junction points from their host <code>iTunes</code> folder.</p>
<p>You can test that the junction points are working correctly by creating an empty text file in the user&#8217;s <code>iTunes</code> directories and seeing if it &#8216;appears&#8217; in the <code>All Users</code> iTunes directory. Once you&#8217;re sure everything is working, proceed to  install iTunes where all your settings will be shared.</p>
<p>Once iTunes is installed, for good measure I then modify the `iTunes Music folder location` under Edit->Preferences&#8230;->Advanced to be in the,</p>
<p><code>C:\Documents and Settings\All Users\Documents\My Music\iTunes\iTunes Music</code></p>
<p>directory.</p>
<p><img src="/sufficientlysmall/wp-content/itunes.png" width="524" height="537" alt="" /></p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2006/06/11/up-the-junction-multi-user-windows-itunes/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Programmers are real people too</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2005/12/16/programmers-are-real-people-too/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2005/12/16/programmers-are-real-people-too/#comments</comments>
		<pubDate>Fri, 16 Dec 2005 22:43:24 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[software]]></category>

		<category><![CDATA[computing]]></category>

		<category><![CDATA[Business &#038; Economics]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/?p=13</guid>
		<description><![CDATA[Liz and I have just finished watching Aardvark&#8217;d: 12 Weeks With Geeks- the documentary about the Copilot project which Joel Spolsky&#8217;s clutch of interns completed over the summer of 2005 for Fog Creek software.
The film is certainly entertaining, and had us laughing out loud on more than one occasion. Nevertheless, I can&#8217;t help feeling that [...]]]></description>
			<content:encoded><![CDATA[<p>Liz and I have just finished watching <em>Aardvark&#8217;d: 12 Weeks With Geeks</em>- the documentary about the <a href="https://www.copilot.com/">Copilot</a> project which Joel Spolsky&#8217;s clutch of interns completed over the summer of 2005 for Fog Creek software.</p>
<p>The film is certainly entertaining, and had us laughing out loud on more than one occasion. Nevertheless, I can&#8217;t help feeling that the readers of Joel&#8217;s <a href="http://www.joelonsoftware.com/">blog</a>, who probably comprise the majority of his customers will  eject the DVD having enjoyed the film, but feeling a little disappointed in retrospect. Joel is known for his expositions, not on the details of coding, but on the wider development process in which coding activity is an albeit major part, including the business and economic aspects of software projects. We found the film light on any detail of the actual development process - we saw the first demo and the release party - but I don&#8217;t feel we learnt much about what actually happened between these events. There was no real explanation of how software design was done, how developers work together, or how quality was assured. Did they do code reviews or unit testing? Did Joel do any project management, or did they just hack away at the code? We simply don&#8217;t find out.</p>
<p>The second disappointing aspect of the film is its production quality. The camera-work is of poor quality with unnecessary disorienting pans and movement, which although it may be intended to convey a sense &#8216;reality&#8217;, in actual fact it severely detracts from the overall sense of quality of the product.  Furthermore, the transfer to DVD video is definitely amatuerish, resulting in jerky motion of slow pans and moving vehicles.</p>
<p>In spite of these shortcomings, Aardvark&#8217;d gives you an excellent sense for the kind of people Joel hires and the personalities of the interns shine through. The end result is less likely to be useful to Software Developers themselves, than to &#8216;Those Who, Whether by Good Fortune or Ill Luck, Work with Them in Some Capacity&#8217;. Its doubtful that the former will learn anything new from this film, although managers and marketers may get a better sense of the kind of people software geeks really are. The most interesting part for many ambitious developers will be the digression with Paul Graham disussing the motivation and funding for software start-ups.</p>
<p>Our industry needs more films with the same objectives as <em>Aardvark&#8217;d</em>, but with deeper content on the planning and execution aspects, and a bigger budget to carry off the production successfully. Joel is to be commended for having the imagination to commission such a film.</p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2005/12/16/programmers-are-real-people-too/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Forest Jump - priority queues at Amazon?</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2005/12/16/forest-jump-priority-queues-at-amazon/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2005/12/16/forest-jump-priority-queues-at-amazon/#comments</comments>
		<pubDate>Fri, 16 Dec 2005 20:04:31 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[Internet]]></category>

		<category><![CDATA[Business &#038; Economics]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/?p=12</guid>
		<description><![CDATA[To my astonishment the predicted delivery date was six days earlier.]]></description>
			<content:encoded><![CDATA[<p>Earlier today I was dismayed to receive an e-mail from Amazon informing me that the expected delivery date for five Christmas presents I had ordered was 26-30 December. Predictably, this is entirely my own fault through placing the order too late, and expecting delivery from the UK to Norway in good time. I&#8217;d already upgraded to Priority Mail service, which made no difference whatsoever, but I had kept the default option of having all my items dispatched together.</p>
<p>I had difficulty obtaining information on when each of the individual items in the order would be in stock, so in a last-ditch attempt to get <em>something</em> out of Amazon before Christmas I selected the option to dispatch each item separately as it became available. </p>
<p>Amazon duly split my original order of five items into one order of four items and a second order with the remaining item. To my astonishment the predicted delivery date for <em>both</em> orders was 20-21 December - some six days earlier and in plenty of time for Jule!</p>
<p>Of course, this defies all logic - unless Amazon is operating some sort of priority queue system - and I have just jumped the queue because my multiple dispatch priority mail order is more profitable to Amazon than my single dispatch priority mail order - which suggests Amazon is making a healthy profit on its shipping charge.</p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2005/12/16/forest-jump-priority-queues-at-amazon/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Gangsta Wrappers</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2005/12/05/gangsta-wrappers/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2005/12/05/gangsta-wrappers/#comments</comments>
		<pubDate>Mon, 05 Dec 2005 19:04:24 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[software]]></category>

		<category><![CDATA[computing]]></category>

		<category><![CDATA[architecture]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/?p=3</guid>
		<description><![CDATA[You should stick to innovating in your own area, and supporting that process with off-the-shelf solutions for the peripheral services you need.]]></description>
			<content:encoded><![CDATA[<p>&#8220;Guns don&#8217;t kill people. Wrappers do.&#8221;</p>
<p>I doubt Welsh satirical rap crew Goldie Lookin Chain were thinking of the same wrappers as me when they wrote the above lyric. Nonetheless, the subject of when to rap and when to wrap is far more contentious amongst developers and their technical managers than I&#8217;d ever imagined.</p>
<p>The situation is something like this: Your project needs to use functionality provided by a third-party - most likely in the form of a library to link into your application. You have two choices:</p>
<ol>
<li>Throw caution to the wind, and use the library API directly</li>
<li>Painstakingly write a wrapper for the library to mitigate against the risks inherent in using code over which you have no control</li>
</ol>
<p>How do you decide? I believe this is, or at least should be,  a business decision. Is it more cost-effective to wrap the third-party library than to not wrap it over the life of the software: Yes or No?</p>
<h1>Pros and cons</h1>
<p><strong>Wrapper Pros:</strong></p>
<ul>
<li>Insulate against future API changes in the library - useful if the library is likely to be used from many places in our own code</li>
<li>Keep open the option of swapping out the library for an alternative in future. This decreases dependence on the library vendor.</li>
</ul>
<p><strong>Wrapper Cons:</strong></p>
<ul>
<li>The cost of writing, debugging, testing and maintaining the wrapper.</li>
<li>The cost of having a non-standard API to the library functionality</li>
</ul>
<h1>The arguments</h1>
<p><strong>Hiring</strong>: You can probably hire programmers with knowledge of the third-party library in question. There may be a very large, and growing, number of knowledgeable programmers with experience of this particular API in the market and eager for a job. They require no training cost, or months to acclimatise to a unique coding environment. Hiring developers is expensive in time before they become productive - and you&#8217;re probably planning on using the new library precisely so you can have programmers being <em>more </em>productive. The prospect of a job working with the API directly may be attractive to potential recruits -  it is something they know they can bring to the job. The prospect of working with a proprietary, undocumented, and doubtless buggy wrapper is not.</p>
<p><strong>Documentation:</strong> Many third part libraries are excellently documented. Even if the documentation is not perfect it is nearly always superior to in-house API documentation, because this API is <em>their</em> product so it has to be good if they want you to use it.  Furthermore,  there may be an active mailing list and user community out there providing support in addition to library vendor. </p>
<p><strong>User base:</strong> The library may be widely used - probably more widely used than the application you are thinking of integrating it into. Your code may only have tens or hundreds of users. The library code may have many thousands or even millions of users. It goes without saying that the third-party library has already received vastly more real-world testing than your own code will ever receive. Remember, the reason that you are considering it is that it is tried and tested.</p>
<p><strong>Core Business:</strong> Is the functionality provided in the third-part library your business? If your core business is database software, should you be spending your time on a user interface toolkit wrapper? Probably not. You should stick to innovating in your own area, and supporting that process with off-the-shelf solutions for the peripheral services you need. You create value for your customers by delivering your core technology. What is the value proposition for the client the paying you to create a user interface toolkit wrapper? Or is this just architecture astronautics?</p>
<p><strong>Russian Dolls:</strong> Is the third-party library already a wrapper? Many libraries exist largely to abstract-away implementation differences between platforms - for example threading libraries or user-interface toolkits. If this is a purpose you had in mind for your wrapper, don&#8217;t bother. Its been done already.</p>
<p><img src="/sufficientlysmall/wp-content/russian_dolls.png" width="428" height="281" alt="Russian Dolls" /><br />
A derivative of GFDL image from Wikipedia article <a href="http://en.wikipedia.org/wiki/Russian_doll">Russian Dolls</a></p>
<p><strong>Fear and Risk:</strong> What are you afraid of? What is your attitude to risk? Wrapping all third-party libraries is a risk-averse strategy. Lets examine some possible scenarios that could cause you future problems: </p>
<ol>
<li><em>You find a bug in the library.</em> Either the vendor fixes it in their next release, or if you are fortunate enough to have access to the library source, you fix it yourself.</li>
<li><em>The library vendor is subject to a hostile takeover in an attempt to &#8216;embrace and extend&#8217; their success.</em> This is potentially the most damaging scenario - but you need to look carefully at the real risks here. Is a new owner likely to stop supporting the library? If you have access to the source code the risk is reduced. Will the product be withdrawn? Are alternatives available?</li>
<li><em>A fabulous alternative but currently hypothetical library is released five years from now. You&#8217;re worried that at as some indeterminate time in the future you might want to use that instead.</em> No problem: Why not defer writing a wrapper until the new-fangled alternative library is a reality, and then write a wrapper for the new library that makes it API compatible with the existing library? If it never happens, we save the cost of writing and maintaining a wrapper! </li>
<li><em>The library vendor introduces some radical API changes between major versions:</em> Your invest some time an effort in porting the code - this will probably be less effort than the cumulative effort of maintaining a wrapper. Maybe they even supply tools to help you. Has the library historically had a stable API? If its version 0.9 you should be more concerned than if its version 6.4. Are changes likely to me minor or earth shattering? Probably the former. Is this upgrading effort so much more than maintaining your own wrapper for years? Obviously you should take the nature of the library into account. For example DirectX is continually chasing the breakneck release of new graphics hardware - whereas OpenGL has historically been a stable API</li>
</ol>
<p><strong>Wrapper Design:</strong> How much effort would you be prepared to invest in writing a wrapper? Are you going to hide all the details of the library? To wrap every type returned or passed to it? If you&#8217;re using C++ will you use the Cheshire Cat idiom to prevent any types from the library being visible in your wrapper API - even though doing this essentially requires to write both an inner wrapper and out wrapper - a great concept but certainly more effort.</p>
<p><strong>Leaky Abstractions:</strong> How &#8216;thick&#8217; will you wrapper be? Are you planning to add behaviour or present different abstractions to clients of the functionality? If so, be wary of combining a simple wrapper which merely insulates from changes or bugs in the third-party library with a library which layers substantial new behaviour or abstractions. These different tasks may be better separated into different layers.  Any abstraction written around a single reference implementation will leak like a sieve.</p>
<p><strong>Multiple Languages:</strong> Is your wrapper to provide an existing API in another language? Mixing language can be a powerful technique but beware if your wrapper needs to overcome a significant &#8216;impedance mismatch&#8217; between the languages in question. Using Java from Jython is easy whereas using C++ from Java through JNI requires much more discipline and understanding.</p>
<h1>Conclusion</h1>
<p>Ultimately its for you to decide, based on your own circumstances - but in general I would suggest that the effort involved in wrapping third-party libraries rarely pays off.</p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2005/12/05/gangsta-wrappers/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Jython, Swing &#038; Curry</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2005/12/03/jython-swing-curry/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2005/12/03/jython-swing-curry/#comments</comments>
		<pubDate>Sat, 03 Dec 2005 15:57:45 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[software]]></category>

		<category><![CDATA[computing]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[Jython]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/?p=8</guid>
		<description><![CDATA[...higher-order techniques can be used to aid user-interface programming with Swing...]]></description>
			<content:encoded><![CDATA[<p>Jython is currently, by far the most useful of the the three main Python implementations, <a href="http://www.jython.org">Jython</a>, <a href="http://www.python.org">CPython</a> and <a href="http://www.ironpython.com">IronPython</a>. It allows access to the Java standard library which often provides more standard, better defined, and certainly better documented alternatives to much of what is in the Python standard library. It is also more cross-platform than .NET bound IronPython and offers superior multithreading support to CPython.</p>
<p>Its well known within the Jython community that having first-class functions in Python makes development with Swing more productive in Jython than it is with Java, by allowing us to attach functions or methods directly to Swing callbacks such as <code>actionPerformed</code>, without the need for anonymous classes or excessive need for interface implementation.  This example taken from <a href="http://www.catalysoft.com/articles/GoodAboutJython.html">What&#8217;s Good About Jython?</a> shows this in action:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">javax</span><span class="hl-default">.</span><span class="hl-identifier">swing as swing

</span><span class="hl-reserved">def </span><span class="hl-identifier">printMessage</span><span class="hl-brackets">(</span><span class="hl-identifier">event</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Ouch!</span><span class="hl-quotes">&quot;
        
</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default">== </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
    </span><span class="hl-identifier">frame</span><span class="hl-default">=</span><span class="hl-identifier">swing</span><span class="hl-default">.</span><span class="hl-identifier">JFrame</span><span class="hl-brackets">(</span><span class="hl-identifier">title</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">My Frame</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">size</span><span class="hl-code">=</span><span class="hl-brackets">(</span><span class="hl-number">300</span><span class="hl-code">,</span><span class="hl-number">300</span><span class="hl-brackets">))
    </span><span class="hl-identifier">frame</span><span class="hl-default">.</span><span class="hl-identifier">defaultCloseOperation</span><span class="hl-default">=</span><span class="hl-identifier">swing</span><span class="hl-default">.</span><span class="hl-identifier">JFrame</span><span class="hl-default">.</span><span class="hl-identifier">EXIT_ON_CLOSE</span><span class="hl-default">;
    </span><span class="hl-identifier">button</span><span class="hl-default">=</span><span class="hl-identifier">swing</span><span class="hl-default">.</span><span class="hl-identifier">JButton</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Push Me!</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">actionPerformed</span><span class="hl-code">=</span><span class="hl-identifier">printMessage</span><span class="hl-brackets">)
    </span><span class="hl-identifier">frame</span><span class="hl-default">.</span><span class="hl-identifier">contentPane</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">button</span><span class="hl-brackets">)
    </span><span class="hl-identifier">frame</span><span class="hl-default">.</span><span class="hl-identifier">visible</span><span class="hl-default">=</span><span class="hl-number">1</span></pre></div></div>
<p>The most powerful result of learning different programming languages is being able to apply concepts learned in one language, in another language. This type of &#8216;technology transfer&#8217; drives progress in many science and engineering fields. This cross-fertilisation has always been possible, but is becoming both more feasible and popular thanks to multiparadigm languages such as Python and Ruby, and wider use of the STL and Boost in Standard C++ which encourage and facilitate functional and higher-order programming style. There are even books on the subject of <a href="http://hop.perl.plover.com/">Higher Order Perl</a>.</p>
<p>Although its had many notable ongoing and recent successes (<em>e.g. </em><a href="http://www.gnu.org/software/emacs/emacs.html">Emacs</a>, <a href="http://abridgegame.org/darcs/">Darcs</a>, <a href="http://www.pugscode.org/">Pugs</a>) the functional community is unfortunately widely perceived as academic or impractical. Indeed, Guido van Rossum has recently threatened to remove some functional programming support from Python, bizarrely whilst simultaneously adding higher-order features such as decorators. This is unfortunate because functional programming style and idioms can go a long way to improving software quality in any language - functions without side-effects are far easier to test, debug and reason about.</p>
<p>For example, the technique of <a href="http://en.wikipedia.org/wiki/Currying">currying </a>- fixing a function argument and returning a new function which takes the remaining parameters can be very useful for development with the Swing UI toolkit supplied with Java.</p>
<p>In this example extracted from one of my own projects, where the user interface features two radio buttons, we look at how some higher-order techniques can be used to aid user-interface programming with Swing. In the code below,</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">fixed_radio</span><span class="hl-default"> = </span><span class="hl-identifier">JRadioButton</span><span class="hl-brackets">(</span><span class="hl-identifier">text</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Regular columns of fixed width</span><span class="hl-quotes">&quot;</span><span class="hl-code">,
        </span><span class="hl-identifier">actionPerformed</span><span class="hl-code"> = </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">handleFixedOption</span><span class="hl-brackets">)

</span><span class="hl-identifier">separated_radio</span><span class="hl-default"> = </span><span class="hl-identifier">JRadioButton</span><span class="hl-brackets">(</span><span class="hl-identifier">text</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Fields separated by spaces,
        commas, or other characters</span><span class="hl-quotes">&quot;</span><span class="hl-code">,
        </span><span class="hl-identifier">actionPerformed</span><span class="hl-code"> = </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">handleSeparatedOption</span><span class="hl-brackets">)</span></pre></div></div>
<p>two bound-methods are attached to the <code>actionPerformed</code> event of each button.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">handleFixedOption</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">event</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">controller</span><span class="hl-default">.</span><span class="hl-identifier">setOption</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">controller</span><span class="hl-code">.</span><span class="hl-identifier">FIXED</span><span class="hl-brackets">)

</span><span class="hl-reserved">def </span><span class="hl-identifier">handleSeparatedOption</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">event</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">controller</span><span class="hl-default">.</span><span class="hl-identifier">setOption</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">controller</span><span class="hl-code">.</span><span class="hl-identifier">SEPARATED</span><span class="hl-brackets">)</span></pre></div></div>
<p>We don&#8217;t actually use the <code>event</code> parameter in this case, but it will be passed to the handler function we provide from <code>actionPerformed</code>, so we must accommodate it. These two methods are identical apart from the value passed to <code>setOption</code> internally, so we could factor out the common code and these two functions with a single function and pass the option value <code>FIXED</code> or <code>SEPARATED</code>  in as an extra argument,</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">handleOption</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">option</span><span class="hl-code">, </span><span class="hl-identifier">event</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">controller</span><span class="hl-default">.</span><span class="hl-identifier">setOption</span><span class="hl-brackets">(</span><span class="hl-identifier">option</span><span class="hl-brackets">)</span></pre></div></div>
<p>However, we now have a difficulty in that we can no longer bind our new function directly to the actionPerformed handler of the buttons, since <code>actionPerformed</code> expects a function which takes single <code>event</code> argument. We know at coding time which <code>option</code> value should be attached to each button - but we don&#8217;t know until the code is run, which event will be passed from<code> actionPerformed</code>. We need to bind the <code>option</code> argument before the <code>event</code> argument. The solution to this is currying. </p>
<p>Rather than writing our own currying facility, we can use on off-the-shelf implementation provided by the <a href="http://www.xoltar.org/languages/python.html">Xoltar Toolkit</a> which provides some functional programming support in Python. In particular we use the <code>curry</code> function to curry our <code>handleOption</code> function into some new functions that only take take a single <code>event</code> argument.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">from </span><span class="hl-identifier">functional </span><span class="hl-reserved">import </span><span class="hl-identifier">curry

fixed_radio</span><span class="hl-default"> = </span><span class="hl-identifier">JRadioButton</span><span class="hl-brackets">(</span><span class="hl-identifier">text</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Regular columns of fixed width</span><span class="hl-quotes">&quot;</span><span class="hl-code">,
        </span><span class="hl-identifier">actionPerformed</span><span class="hl-code"> = </span><span class="hl-identifier">curry</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">handleOption</span><span class="hl-code">,
                </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">controller</span><span class="hl-code">.</span><span class="hl-identifier">FIXED</span><span class="hl-brackets">))

</span><span class="hl-identifier">separated_radio</span><span class="hl-default"> = </span><span class="hl-identifier">JRadioButton</span><span class="hl-brackets">(</span><span class="hl-identifier">text</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">Fields separated by spaces,
        commas, or other characters</span><span class="hl-quotes">&quot;</span><span class="hl-code">,
        </span><span class="hl-identifier">actionPerformed</span><span class="hl-code"> = </span><span class="hl-identifier">curry</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">handleOption</span><span class="hl-code">,
                </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">controller</span><span class="hl-code">.</span><span class="hl-identifier">SEPARATED</span><span class="hl-brackets">))</span></pre></div></div>
<p>The curry function takes the function to be curried as its first argument. In this case we pass the bound-method <code>self.optionHandler</code>. The second argument to <code>curry</code> is the value of the first parameter to the function to be curried, which want tobe fixed to this value in the created function, for example, <code>self.controller.FIXED</code>. The result of the <code>curry</code> function is a new function which accepts one less argument than the original function - so in this case we get a new function which only accepts the remaining <code>event</code> parameter, and is therefore equivalent to the handleFixedOption function we started with, but which we have now avoided having to write.</p>
<p>The material advantage with such a simple example is minimal, but when such techniques are used throughout a project the savings in space and complexity can be substantial. The combination of functional concepts from borrowed from languages such a Haskell, facilitated by tools provided by the Xoltar Tookit, developed in dynamically-typed Jython and exploiting one of the better designed user interface APIs in the form of Swing can be concise and powerful.</p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2005/12/03/jython-swing-curry/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Nordic Winter</title>
		<link>http://www.smallshire.org.uk/sufficientlysmall/2005/11/28/nordic-winter/</link>
		<comments>http://www.smallshire.org.uk/sufficientlysmall/2005/11/28/nordic-winter/#comments</comments>
		<pubDate>Mon, 28 Nov 2005 19:20:52 +0000</pubDate>
		<dc:creator>Robert Smallshire</dc:creator>
		
		<category><![CDATA[Norway]]></category>

		<guid isPermaLink="false">http://www.smallshire.org.uk/sufficientlysmall/?p=6</guid>
		<description><![CDATA[Today winter finally arrived here in Oslo. To think we were swimming in the fjord only a four months ago! I&#8217;ll be heading out to but some skis at the weekend - both alpine (downhill) and cross-country - so I can have the full nordic skiing experience this winter around Olso.

Copyright &#169; 2008 Sufficiently Small. [...]]]></description>
			<content:encoded><![CDATA[<p>Today winter finally arrived here in Oslo. To think we were swimming in the fjord only a four months ago! I&#8217;ll be heading out to but some skis at the weekend - both alpine (downhill) and cross-country - so I can have the full nordic skiing experience this winter around Olso.</p>
<p><img src='/sufficientlysmall/wp-content/norwegian_winter.jpg' alt='The arrival of winter in Oslo, Norway' /></p>
<hr/>Copyright &copy; 2008 <strong><a href="http://www.smallshire.org.uk/sufficientlysmall">Sufficiently Small</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement. Please contact legal@smallshire.org.uk so we can take legal action immediately.<br/><span style="float: right;font-size: 7pt"><a href="http://blog.taragana.com/index.php/archive/wordpress-plugins-provided-by-taraganacom/">Plugin</a> by <a href="http://www.taragana.com/">Taragana</a></span>]]></content:encoded>
			<wfw:commentRss>http://www.smallshire.org.uk/sufficientlysmall/2005/11/28/nordic-winter/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
