<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8273201239805322932</id><updated>2012-01-31T06:01:36.837-06:00</updated><category term='ruby'/><category term='flash'/><category term='relaxng'/><category term='xaml'/><category term='squeak'/><category term='mef'/><category term='ironpython'/><category term='javascript'/><category term='ecmascript'/><category term='erlang'/><category term='perl'/><category term='boo'/><category term='continuations'/><category term='c#'/><category term='objective-c'/><category term='apl'/><category term='f#'/><category term='powershell'/><category term='python'/><category term='java3d'/><category term='functional'/><category term='haskell'/><category term='vbnet'/><category term='parallel'/><category term='.net'/><category term='podcasts'/><category term='eclipse'/><category term='actionscript'/><category term='mgrammar'/><category term='fortress'/><category term='javafx'/><category term='xml'/><category term='scheme'/><category term='tom'/><category term='linq'/><category term='scala'/><category term='dlr'/><category term='emacs'/><category term='java'/><category term='air'/><category term='logic'/><category term='xsd'/><category term='abcexplorationlib'/><category term='refactoring'/><category term='silverlight'/><category term='arrays'/><category term='smalltalk'/><category term='metaprogramming'/><category term='lisp'/><category term='flex'/><category term='netbeans'/><category term='m'/><category term='pattern matching'/><category term='ironruby'/><category term='j'/><category term='groovy'/><category term='mvvm'/><category term='oo'/><category term='mercury'/><category term='wpf'/><category term='list comprehensions'/><category term='snobol'/><category term='jruby'/><category term='vb9'/><category term='examples'/><category term='haxe'/><category term='google'/><category term='newspeak'/><title type='text'>Exploring Beautiful Languages</title><subtitle type='html'>Programming language exploration blog</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default?start-index=101&amp;max-results=100'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>108</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-4311624998243677854</id><published>2012-01-23T06:10:00.000-06:00</published><updated>2012-01-23T06:11:40.376-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Creating a small parser using Parsec</title><content type='html'>In this post I'm going to show a small parser for a Scheme-like language written in Haskell using the &lt;a href="http://www.haskell.org/haskellwiki/Parsec"&gt;Parsec&lt;/a&gt; parsing combinator library.&lt;br /&gt;&lt;br /&gt;We're going to start by defining an AST for Scheme-like expressions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;data&lt;/span&gt; Expr = ScSymbol String&lt;br /&gt;            | ScString String&lt;br /&gt;            | ScNumber Integer&lt;br /&gt;            | ScDouble Double &lt;br /&gt;            | ScCons Expr Expr&lt;br /&gt;            | ScNil&lt;br /&gt;            | ScBool Bool&lt;br /&gt;            | ScQuote Expr&lt;br /&gt;     &lt;span class="srckeyw"&gt;deriving&lt;/span&gt; Show&lt;/code&gt;&lt;/pre&gt; &lt;br /&gt;For this experiment I'm going to use the &lt;a href="http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-Parsec-Token.html"&gt;Text.Parsec.Token&lt;/a&gt; and &lt;a href="http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-Parsec-Language.html"&gt;Text.Parsec.Language&lt;/a&gt; packages which have useful functions for creating language parsers.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;idSymbol = oneOf &lt;span class="srctext"&gt;":!$%&amp;*+/&lt;=&gt;?@\\^|-~"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;schemeLanguageDef :: LanguageDef st&lt;br /&gt;schemeLanguageDef = emptyDef { &lt;br /&gt;                   commentLine = &lt;span class="srctext"&gt;";;"&lt;/span&gt;&lt;br /&gt;                   , identStart = letter &amp;lt;|&amp;gt idSymbol&lt;br /&gt;                   , identLetter = alphaNum &amp;lt;|&amp;gt; idSymbol&lt;br /&gt;                   , opStart = parserZero&lt;br /&gt;                   , opLetter = parserZero&lt;br /&gt;                 }&lt;br /&gt;&lt;br /&gt;schemeTokenParser = makeTokenParser schemeLanguageDef&lt;br /&gt;&lt;br /&gt;TokenParser {&lt;br /&gt;   identifier = idParser,&lt;br /&gt;   reservedOp = opParser,&lt;br /&gt;   stringLiteral = stringLiteralParser,&lt;br /&gt;   parens = parParser,&lt;br /&gt;   lexeme = lexParser,&lt;br /&gt;   naturalOrFloat = naturalOrFloatParser&lt;br /&gt;} = schemeTokenParser&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Given these definitions we get parsers for identifiers, numbers, string literals "for free". &lt;br /&gt;&lt;br /&gt;Boolean literals are parsed using the following parser:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;boolLiteral = lexParser (&lt;br /&gt;                 &lt;span class="srckeyw"&gt;do&lt;/span&gt; &lt;br /&gt;                   char &lt;span class="srctext"&gt;'#'&lt;/span&gt;&lt;br /&gt;                   val &amp;lt;- (char &lt;span class="srctext"&gt;'t'&lt;/span&gt;) &amp;lt;|&amp;gt; (char &lt;span class="srctext"&gt;'f'&lt;/span&gt;)&lt;br /&gt;                   &lt;span class="srckeyw"&gt;return&lt;/span&gt; $ ScBool $ val == &lt;span class="srctext"&gt;'t'&lt;/span&gt;&lt;br /&gt;             )&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Basic quotations are parsed as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;quoteParser = lexParser (&lt;br /&gt;              &lt;span class="srckeyw"&gt;do&lt;/span&gt; &lt;br /&gt;                char &lt;span class="srctext"&gt;'\'&lt;/span&gt;'&lt;br /&gt;                val &amp;lt;- expressionParser&lt;br /&gt;                &lt;span class="srckeyw"&gt;return&lt;/span&gt; $ ScQuote val&lt;br /&gt;          )&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Atomic expressions are parsed as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;atomParser =&lt;br /&gt;   (&lt;span class="srckeyw"&gt;do&lt;/span&gt; &lt;br /&gt;      id &amp;lt;- idParser&lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; $ ScSymbol id)&lt;br /&gt;   &amp;lt;|&amp;gt;&lt;br /&gt;    (&lt;span class="srckeyw"&gt;do&lt;/span&gt; &lt;br /&gt;       fnumber &amp;lt;- naturalOrFloatParser&lt;br /&gt;       &lt;span class="srckeyw"&gt;return&lt;/span&gt; $ case fnumber of&lt;br /&gt;                Left num -&amp;gt; ScNumber num&lt;br /&gt;                Right num -&amp;gt; ScDouble num)&lt;br /&gt;   &amp;lt;|&amp;gt;        &lt;br /&gt;    (&lt;span class="srckeyw"&gt;do&lt;/span&gt; str &amp;lt;- stringLiteralParser&lt;br /&gt;        &lt;span class="srckeyw"&gt;return&lt;/span&gt; $ ScString str)&lt;br /&gt;   &amp;lt;|&amp;gt; boolLiteral&lt;br /&gt;   &amp;lt;|&amp;gt; quoteParser&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Next we need to consider &lt;a href="http://en.wikipedia.org/wiki/S-expression"&gt;S-Expressions&lt;/a&gt;. This kind of expressions are combinationsof the above elements surrounded by parentheses.&lt;br /&gt;&lt;br /&gt;For example:&lt;br/&gt;&lt;pre&gt;&lt;code&gt;(+ 1 2 3)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;dottedSuffixParser =     &lt;br /&gt;   &lt;span class="srckeyw"&gt;do&lt;/span&gt; &lt;br /&gt;      dotParser&lt;br /&gt;      finalExpr &amp;lt;- expressionParser&lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; finalExpr&lt;br /&gt;&lt;br /&gt;parExpressionParser = &lt;br /&gt;   &lt;span class="srckeyw"&gt;do&lt;/span&gt; (exprs, last) &amp;lt;- parParser &lt;br /&gt;                (&lt;span class="srckeyw"&gt;do&lt;/span&gt; &lt;br /&gt;                   seq &amp;lt;- many expressionParser&lt;br /&gt;                   dottedSuffix &amp;lt;- optionMaybe dottedSuffixParser &lt;br /&gt;                   &lt;span class="srckeyw"&gt;return&lt;/span&gt; (case dottedSuffix of&lt;br /&gt;                            Just lastExpr -&amp;gt; (seq, lastExpr)&lt;br /&gt;                            Nothing -&amp;gt; (seq, ScNil)))&lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; $ foldr ScCons last exprs&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As shown above, the parser need to verify if there was a dot ('.') before the last element for example:&lt;pre&gt;&lt;code&gt;(1 . 2)&lt;/code&gt;&lt;/pre&gt;More details on the dot syntax can be found &lt;a href="http://download.plt-scheme.org/doc/html/guide/Pairs__Lists__and_Scheme_Syntax.html"&gt;here&lt;/a&gt;.&lt;br /&gt;Finally we define expressions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;       expressionParser =&lt;br /&gt;            atomParser &amp;lt;|&amp;gt; parExpressionParser&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;       parseIt input = parse expressionParser "" input&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can use this function to parse this expressions as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;*SCParser&amp;gt; parseIt "(- x 1)"&lt;br /&gt;Right (ScCons (ScSymbol "-") (ScCons (ScSymbol "x") (ScCons (ScNumber 1) ScNil)))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There's a great a series of articles on implementing a Scheme interpreter in Haskell called &lt;a href="http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours"&gt;"Write Yourself a Scheme in 48 Hours/Parsing"&lt;/a&gt; which is a great source of information on this topic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-4311624998243677854?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/4311624998243677854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=4311624998243677854' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/4311624998243677854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/4311624998243677854'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2012/01/small-parser-with-parsec.html' title='Creating a small parser using Parsec'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-8472251356408416134</id><published>2012-01-02T21:21:00.000-06:00</published><updated>2012-01-02T21:22:13.719-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='continuations'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>A call-with-current-continuation example</title><content type='html'>The &lt;code&gt;call-with-current-continuation&lt;/code&gt; (or &lt;code&gt;call/cc&lt;/code&gt; for short) function in Scheme allows the creation of powerful control structures.  It basically allows you to capture the current state of a computation as a first class value. This value could be assigned to a variable and invoked later.&lt;br /&gt;&lt;br /&gt;For a great introduction to this function see the &lt;a href="http://community.schemewiki.org/?call-with-current-continuation"&gt;&lt;code&gt;call/cc&lt;/code&gt; entry&lt;/code&gt;&lt;/a&gt; in the &lt;a href="http://community.schemewiki.org/"&gt;Community-Scheme-Wiki&lt;/a&gt; .&lt;br /&gt;&lt;br /&gt;The following &lt;span style="font-style:italic;"&gt;toy&lt;/span&gt; example shows how this function is used to do an incremental search inside a tree. Say that you have the following tree structure definition:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(define tree-data&lt;br /&gt;    '(html&lt;br /&gt;        (head (title "test"))&lt;br /&gt;        (body&lt;br /&gt;           (p "foo" (i "goo"))&lt;br /&gt;           (ol&lt;br /&gt;            (li "xoo" (i "moo"))&lt;br /&gt;            (li (i "loo")))&lt;br /&gt;           (p))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We want to define a function to search for elements identified by a predicate. For example, if looking for a "i" element we can write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(define (is-italic? element)&lt;br /&gt;  (and (list? element) &lt;br /&gt;       (not (null? element))&lt;br /&gt;       (eq? 'i (car element))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We want to create a function to perform an incremental search inside a tree structure. That is, we want to find the first element and then request the next element if needed.&lt;br /&gt;&lt;br /&gt;Here's a demo of the function we want to create:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; (define hit (search is-italic? tree-data))&lt;br /&gt;                                           &lt;br /&gt;&amp;gt; hit&lt;br /&gt;((i "goo") #&amp;lt;continuation&amp;gt;)&lt;br /&gt;&amp;gt; (set! hit (get-next-result hit))&lt;br /&gt;&amp;gt; hit&lt;br /&gt;((i "moo") #&amp;lt;continuation&amp;gt;)&lt;br /&gt;&amp;gt; (set! hit (get-next-result hit))&lt;br /&gt;&amp;gt; hit&lt;br /&gt;((i "loo") #&amp;lt;continuation&amp;gt;)&lt;br /&gt;&amp;gt; (set! hit (get-next-result hit))&lt;br /&gt;&amp;gt; hit&lt;br /&gt;(() #&amp;lt;continuation&amp;gt;)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This function is defined using &lt;code&gt;call-with-current-continuation&lt;/code&gt; as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(define (search pred? tree)&lt;br /&gt;  (call-with-current-continuation&lt;br /&gt;   (lambda (c)&lt;br /&gt;     (searching pred? tree c))))&lt;br /&gt;&lt;br /&gt;(define (searching pred? tree return)&lt;br /&gt;  (set! return&lt;br /&gt;        (call-with-current-continuation&lt;br /&gt;         (lambda (continuation)&lt;br /&gt;           (if (pred? tree)&lt;br /&gt;               (return (list tree continuation))&lt;br /&gt;               return))))&lt;br /&gt;  (if (list? tree)&lt;br /&gt;      (for-each&lt;br /&gt;       (lambda (item)&lt;br /&gt;         (set! return (cadr (searching pred? item return))))&lt;br /&gt;       tree))&lt;br /&gt;  (list '() return))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The entry point is the &lt;code&gt;search&lt;/code&gt; function which captures the current continuation in the &lt;code&gt;return&lt;/code&gt; variable. This continuation value allows us to jump to the point where &lt;code&gt;call-with-current-continuation&lt;/code&gt; was called. We pass this value to the &lt;code&gt;searching&lt;/code&gt; function which contains the logic to search inside the tree.&lt;br /&gt;&lt;br /&gt;The first expression of the &lt;code&gt;searching&lt;/code&gt; function seems confusing since it contains another call to &lt;code&gt;call-with-current-continuation&lt;/code&gt; and an assignment of &lt;code&gt;return&lt;/code&gt;. This code is used to do the following things:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Return a search result (remember that &lt;code&gt;return&lt;/code&gt; contains a continuation)&lt;/li&gt;&lt;li&gt;Capture the current state of the tree traversal (this is done by the &lt;code&gt;call-with-current-continuation&lt;/code&gt; call)&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;...&lt;br /&gt;  (set! return&lt;br /&gt;        (call-with-current-continuation&lt;br /&gt;         (lambda (continuation)&lt;br /&gt;           (if (pred? tree)&lt;br /&gt;               (return (list tree continuation))&lt;br /&gt;               return))))&lt;br /&gt;...&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that a search result contains two things:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The tree fragment that makes the predicate true&lt;/li&gt;&lt;li&gt;The continuation of the point where the element was found (which can be used to restore the traversal)&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One key thing to understand is that we change the value of &lt;code&gt;return&lt;/code&gt; to the result of the &lt;code&gt;call/cc&lt;/code&gt; call. This is done this way because we will change the &lt;code&gt;return&lt;/code&gt; continuation to retrieve new results. This is done using the &lt;code&gt;get-next-result&lt;/code&gt; function as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(define (get-next-result result)&lt;br /&gt;  (if (not (null? (car result)))&lt;br /&gt;      (call-with-current-continuation (cadr result))&lt;br /&gt;      result))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Calling &lt;code&gt;call-with-current-continuation&lt;/code&gt; with the last captured continuation will result on setting it to the &lt;code&gt;return&lt;/code&gt; variable in &lt;code&gt;searching&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-8472251356408416134?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/8472251356408416134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=8472251356408416134' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/8472251356408416134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/8472251356408416134'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2012/01/call-with-current-continuation-example.html' title='A call-with-current-continuation example'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-4492143800390144943</id><published>2011-03-31T05:42:00.042-06:00</published><updated>2011-04-05T06:17:49.109-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apl'/><category scheme='http://www.blogger.com/atom/ns#' term='arrays'/><title type='text'>A quick look at APL</title><content type='html'>In this post I'm going to show an implementation of polynomial multiplication written in APL and the steps to create it. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;APL&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/APL_(programming_language)"&gt;APL&lt;/a&gt; is an &lt;a href="http://en.wikipedia.org/wiki/Array_programming"&gt;array oriented&lt;/a&gt; programming language which means it's good for manipulating vectors, matrices and other kinds of arrays. &lt;br /&gt;&lt;br /&gt;APL has many interesting characteristics among them is its syntax which uses non ASCII characters .&lt;br /&gt;&lt;br /&gt;Here's a very nice video showing how to implement the Conway's Game Of Life in APL:&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" width="480" height="390" src="http://www.youtube.com/embed/a9xAKttWgP4" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;A very nice APL resource is the &lt;a href="http://aplwiki.com/"&gt;APL Wiki&lt;/a&gt;  it has lots of information. Another very nice resource is  &lt;a href="http://aplwiki.com/FinnAplIdiomLibrary"&gt;The FinnAPL Idiom Library&lt;/a&gt; which contains lots little examples of code. Another nice resource is &lt;a href="http://www.vector.org.uk"&gt;Vector the journal of the British APL Association&lt;/a&gt; which has information on the community around APL related languages.&lt;br /&gt;&lt;br /&gt;The examples presented in this post were written using &lt;a href="http://www.nars2000.org/"&gt;NARS2000&lt;/a&gt; a nice open source implementation of APL.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Polynomial multiplication&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As with a &lt;a href="http://langexplr.blogspot.com/2009/10/quick-look-at-j.html"&gt;previous post on J&lt;/a&gt; I'm going to show the implementation of polynomial multiplication . &lt;br /&gt;&lt;br /&gt;The following example shows the process of multiplying two polynomials:&lt;br /&gt;&lt;code&gt;&lt;br&gt;(4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1)   *   (2x&lt;sup&gt;2&lt;/sup&gt; - x - 3) &lt;br&gt;&lt;br&gt;= ((4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1) * 2x&lt;sup&gt;2&lt;/sup&gt;) + &lt;br&gt;  ((4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1) * -x) +&lt;br&gt;  ((4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1) * -3)&lt;br&gt;&lt;br&gt;= (8x&lt;sup&gt;5&lt;/sup&gt; - 46x&lt;sup&gt;4&lt;/sup&gt; + 2x&lt;sup&gt;3&lt;/sup&gt; + 2x&lt;sup&gt;2&lt;/sup&gt;) + &lt;br&gt;  (-4x&lt;sup&gt;4&lt;/sup&gt; + 23x&lt;sup&gt;3&lt;/sup&gt; - x&lt;sup&gt;2&lt;/sup&gt; - x)  +&lt;br&gt;  (-12x&lt;sup&gt;3&lt;/sup&gt; + 69x&lt;sup&gt;2&lt;/sup&gt; - 3x - 3) &lt;br&gt;&lt;br&gt;= (8x&lt;sup&gt;5&lt;/sup&gt; - 50x&lt;sup&gt;4&lt;/sup&gt; + 13x&lt;sup&gt;3&lt;/sup&gt; + 70x&lt;sup&gt;2&lt;/sup&gt; - 4x - 3)  &lt;br&gt;&lt;/code&gt;&lt;br /&gt;This example will be used to illustrate the parts of the code in the following sections.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The program&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The final program to calculate polynomial multiplication looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-DLlE-l_9JPA/TZmwQ6JloTI/AAAAAAAAAUg/5-A9otzCuHY/s1600/aplpolymulti_complete2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 23px;" src="http://4.bp.blogspot.com/-DLlE-l_9JPA/TZmwQ6JloTI/AAAAAAAAAUg/5-A9otzCuHY/s400/aplpolymulti_complete2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591694216891048242" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Where &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are the polynomials.&lt;br /&gt;&lt;br /&gt;As with the &lt;a href="http://langexplr.blogspot.com/2009/10/quick-look-at-j.html"&gt;previous post on J&lt;/a&gt; I'm sure there's a shorter way to write this program &lt;br /&gt;(the number of parenthesis seems to indicate this!).  &lt;br /&gt;&lt;br /&gt;One key aspect to understand APL code is to remember that it evaluates expressions from right to left. See the &lt;a href="http://aplwiki.com/LearnApl/SimpleArithmetic#Order_of_execution"&gt;Order of execution&lt;/a&gt; section of the APL Wiki for more information.&lt;br /&gt;&lt;br /&gt;A description of each part of this program is presented in the following sections.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Polynomial representation&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;To represent polynomials we're going to use vectors  the following way:&lt;br /&gt;&lt;br /&gt;For:&lt;br /&gt;&lt;br /&gt;  &lt;code&gt;(4x&lt;sup&gt;3&lt;/sup&gt; + 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1) &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;the array will be:&lt;br /&gt;&lt;br /&gt;  &lt;code&gt;1 1 23 4&lt;/code&gt; &lt;br /&gt;&lt;br /&gt;In APL arrays are written as sequences of numbers separated by spaces (as above). You can manipulate this values easily, for example here we create two variables with two polynomials and add them:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-uMiG1S5HGS8/TZh6hx-DA9I/AAAAAAAAAS4/gyKfVPLxxuI/s1600/aplpolyaddition.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 271px; height: 102px;" src="http://1.bp.blogspot.com/-uMiG1S5HGS8/TZh6hx-DA9I/AAAAAAAAAS4/gyKfVPLxxuI/s400/aplpolyaddition.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591353658148324306" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In order to multiply each element of the array by a value we can simply write:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-sZ-s43SuCwE/TZh7Kx9T6_I/AAAAAAAAATA/JHnHuBaT9QM/s1600/aplscalarmult.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 149px; height: 55px;" src="http://1.bp.blogspot.com/-sZ-s43SuCwE/TZh7Kx9T6_I/AAAAAAAAATA/JHnHuBaT9QM/s400/aplscalarmult.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591354362519874546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Outer product&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://aplwiki.com/LearnApl/AplOperators#Outer_and_inner_products"&gt;outer product&lt;/a&gt; operator lets you apply an operation to all the combinations of the elements of the operands. For example if we want to multiply each value of the two arrays representing the polynomials we want to multiply we can write:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-WCM58qonxBU/TZh888U-W3I/AAAAAAAAATI/2071AmHkDPA/s1600/aplpolymulti_outerproduct.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 302px; height: 185px;" src="http://4.bp.blogspot.com/-WCM58qonxBU/TZh888U-W3I/AAAAAAAAATI/2071AmHkDPA/s400/aplpolymulti_outerproduct.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591356323808566130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Creating a matrix of  intermediate polynomials&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;We need to obtain a matrix with the intermediate polynomials given the result of the outer product. But first I'm going to introduce the &lt;a href="http://aplwiki.com/LearnApl/BuiltInFunctions#Manipulative_functions"&gt;rho function&lt;/a&gt;. This function can be used to with one argument (&lt;a href="http://en.wikipedia.org/wiki/APL_syntax_and_symbols#Monadic_and_dyadic_functions"&gt;monadic&lt;/a&gt;) to obtain the dimensions of the given array for example:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-_kU7qNvPaZg/TZiAz10aDRI/AAAAAAAAATQ/NjZL_g8bcwM/s1600/aplpolymulti_rhomond.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 291px; height: 100px;" src="http://4.bp.blogspot.com/-_kU7qNvPaZg/TZiAz10aDRI/AAAAAAAAATQ/NjZL_g8bcwM/s400/aplpolymulti_rhomond.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591360565489044754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Or it can be used with two arguments (&lt;a href="http://en.wikipedia.org/wiki/APL_syntax_and_symbols#Monadic_and_dyadic_functions"&gt;dyadic&lt;/a&gt;) to create an array of the given shape.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-BuGsitJ4Bic/TZiA8P_kZzI/AAAAAAAAATY/L4k1w3hyK2Q/s1600/aplpolymulti_rhodyad.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 298px; height: 213px;" src="http://3.bp.blogspot.com/-BuGsitJ4Bic/TZiA8P_kZzI/AAAAAAAAATY/L4k1w3hyK2Q/s400/aplpolymulti_rhodyad.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591360709954135858" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We can use this function combined with &lt;a href="http://aplwiki.com/LearnApl/BuiltInFunctions#Manipulative_functions"&gt;comma function&lt;/a&gt; to expand the matrix of polynomials:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-9GlOZweFJf0/TZiC2mWrtUI/AAAAAAAAATg/uPgac7KnWCE/s1600/aplmulti_concat.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 120px;" src="http://4.bp.blogspot.com/-9GlOZweFJf0/TZiC2mWrtUI/AAAAAAAAATg/uPgac7KnWCE/s400/aplmulti_concat.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591362811900704066" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://aplwiki.com/LearnApl/BuiltInFunctions#Algebraic_functions"&gt;iota function&lt;/a&gt; lets you, among other things, create arrays of sequences of values. We're going to use it to create the values used to rotate each polynomial in our matrix:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-ZQ0nIvizQK8/TZiFgwxyvQI/AAAAAAAAATo/jKprOx26xOo/s1600/aplmulti_iota.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 327px; height: 163px;" src="http://4.bp.blogspot.com/-ZQ0nIvizQK8/TZiFgwxyvQI/AAAAAAAAATo/jKprOx26xOo/s400/aplmulti_iota.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5591365735276526850" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The rotation of each matrix element is performed using the &lt;a href="http://aplwiki.com/LearnApl/BuiltInFunctions#Manipulative_functions"&gt;rotate function&lt;/a&gt; as follows:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-9-kK9cbrsnA/TZiGlkr-YmI/AAAAAAAAATw/7gVH1Kt1vc0/s1600/aplpolyrot.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 100px;" src="http://3.bp.blogspot.com/-9-kK9cbrsnA/TZiGlkr-YmI/AAAAAAAAATw/7gVH1Kt1vc0/s400/aplpolyrot.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591366917441872482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The final step is to sum every vector in this matrix. We can do that by using the &lt;a href="http://aplwiki.com/LearnApl/AplOperators#Reduce_and_scan"&gt;reduce operator&lt;/a&gt; (/) . This operator lets you apply a dyad operation to every element of an array accumulating the result. For example:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-x6W7Gf2cUR8/TZmpibHg8-I/AAAAAAAAAT4/sbrpVYh61wg/s1600/aplpolyreduce.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 261px; height: 59px;" src="http://1.bp.blogspot.com/-x6W7Gf2cUR8/TZmpibHg8-I/AAAAAAAAAT4/sbrpVYh61wg/s400/aplpolyreduce.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591686821217104866" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The nice thing about it is that if you apply it to a matrix, it will do the right thing by summing up every 1d vector. In our case we need to sum the rows so we &lt;a href="http://aplwiki.com/LearnApl/AplOperators#Axis"&gt;change the axis&lt;/a&gt; of the operation.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-yQ6Hg79XhHI/TZmpnRpTO0I/AAAAAAAAAUA/mLi3XNco-8c/s1600/aplpolyreduce2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 292px; height: 236px;" src="http://4.bp.blogspot.com/-yQ6Hg79XhHI/TZmpnRpTO0I/AAAAAAAAAUA/mLi3XNco-8c/s400/aplpolyreduce2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591686904573803330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Index origin&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Before defining the final function we need to take an additional consideration.  There is a system variable  which modifies the origin of the &lt;code&gt;iota&lt;/code&gt; function among other things. For example:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-5Z3EulBRXxk/TZmriuM4C1I/AAAAAAAAAUI/u7UVvzeJhzk/s1600/aplpoly_indexorigin.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 193px; height: 182px;" src="http://2.bp.blogspot.com/-5Z3EulBRXxk/TZmriuM4C1I/AAAAAAAAAUI/u7UVvzeJhzk/s400/aplpoly_indexorigin.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591689025363118930" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In other to make our code independent of the value of &lt;code&gt;IO&lt;/code&gt; by using it instead of references to '1' as above.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Defining a function&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The final function definition looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-YcbS1yVZTvA/TZmw6Xuc4xI/AAAAAAAAAUo/NwHa3E0jhKg/s1600/aplpolymulti_function2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 28px;" src="http://1.bp.blogspot.com/-YcbS1yVZTvA/TZmw6Xuc4xI/AAAAAAAAAUo/NwHa3E0jhKg/s400/aplpolymulti_function2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5591694929204929298" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We can use this function as follows:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-eNy042ntlYo/TZmysF4tqbI/AAAAAAAAAUw/LazVWURoZHw/s1600/aplpolymulti_functionuses.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 342px; height: 297px;" src="http://1.bp.blogspot.com/-eNy042ntlYo/TZmysF4tqbI/AAAAAAAAAUw/LazVWURoZHw/s400/aplpolymulti_functionuses.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5591696882921220530" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-4492143800390144943?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/4492143800390144943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=4492143800390144943' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/4492143800390144943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/4492143800390144943'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2011/03/quick-look-at-apl.html' title='A quick look at APL'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/a9xAKttWgP4/default.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-8076217489146648144</id><published>2011-02-02T05:26:00.004-06:00</published><updated>2011-02-02T05:32:13.139-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mvvm'/><category scheme='http://www.blogger.com/atom/ns#' term='wpf'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><title type='text'>IronPython &amp; WPF: Data binding with TreeView's selected element</title><content type='html'>In this post I'm going to show a small example of using data binding with the selected element of a WPF TreeView with an IronPython class.&lt;br /&gt;&lt;br /&gt;A couple of days ago I had the necessity of using data binding to keep track of the selected value of a &lt;a href="http://msdn.microsoft.com/en-us/library/ms595700.aspx"&gt;WPF TreeView&lt;/a&gt; . At first it seemed to be an easy task so I wrote:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;TreeView SelectedValue="{Binding selected, Mode=TwoWay}" ... /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running this code results on the following error:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;SystemError: 'Provide value on 'System.Windows.Data.Binding' threw an exception.' Line number '12' and line position '7'.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The problem is that the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.treeview.selectedvalue.aspx"&gt;SelectedValue&lt;/a&gt; (and &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.treeview.selecteditem.aspx"&gt;SelectedItem&lt;/a&gt;) property is read-only.&lt;br /&gt;&lt;br /&gt;There are &lt;a href="http://www.google.co.cr/search?hl=en&amp;q=%22TreeView's+selected+item%22&amp;aq=f&amp;aqi=&amp;aql=&amp;oq="&gt;several ways&lt;/a&gt; to deal with this problem.  One alternative is to use a technique similar to the one described in the &lt;a href="http://wpfglue.wordpress.com/2009/12/03/forwarding-the-result-of-wpf-validation-in-mvvm/"&gt;"Forwarding the Result of WPF Validation in MVVM"&lt;/a&gt; post. We're going to define an attached property which works as an "output only" property that could be used with data binding.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Attached property definition&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;I couldn't find a way to wrote the definition of the attached property in IronPython because it needed to be instanciated by &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader.aspx"&gt;XamlReader&lt;/a&gt;. So the definition was written using C#:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System.Windows.Markup;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System.Windows;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System.Windows.Controls;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System.IO;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System.Collections.ObjectModel;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;namespace&lt;/span&gt; Langexplr &lt;br /&gt;{&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;class&lt;/span&gt; TreeViewSelectedBehavior&lt;br /&gt;   {&lt;br /&gt;      &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;readonly&lt;/span&gt; DependencyProperty MySelectedProperty = &lt;br /&gt;             System.Windows.DependencyProperty.RegisterAttached(&lt;br /&gt;                                       &lt;span class="srctext"&gt;"MySelected"&lt;/span&gt;,&lt;br /&gt;                                       &lt;span class="srckeyw"&gt;typeof&lt;/span&gt;(object),&lt;br /&gt;                                       &lt;span class="srckeyw"&gt;typeof&lt;/span&gt;(TreeViewSelectedBehavior)&lt;br /&gt;                                    );&lt;br /&gt;      &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; object GetMySelected(TreeView t)&lt;br /&gt;      {&lt;br /&gt;         &lt;span class="srckeyw"&gt;return&lt;/span&gt; t.GetValue(MySelectedProperty);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;void&lt;/span&gt; SetMySelected(TreeView t, object theValue)&lt;br /&gt;      {&lt;br /&gt;         t.SetValue(MySelectedProperty, theValue);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;                                    &lt;br /&gt;      &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; readonly DependencyProperty SelectedHelperProperty =&lt;br /&gt;             System.Windows.DependencyProperty.RegisterAttached(&lt;br /&gt;                                       &lt;span class="srctext"&gt;"SelectedHelper"&lt;/span&gt;,&lt;br /&gt;                                       &lt;span class="srckeyw"&gt;typeof&lt;/span&gt;(TreeViewSelectedHelper),&lt;br /&gt;                                       &lt;span class="srckeyw"&gt;typeof&lt;/span&gt;(TreeViewSelectedBehavior),&lt;br /&gt;                                       &lt;span class="srckeyw"&gt;new&lt;/span&gt; UIPropertyMetadata(null,OnSelectedHelperChanged)&lt;br /&gt;                                    );&lt;br /&gt;&lt;br /&gt;      &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt;  TreeViewSelectedHelper GetSelectedHelper(TreeView t) &lt;br /&gt;      {&lt;br /&gt;          &lt;span class="srckeyw"&gt;return&lt;/span&gt; (TreeViewSelectedHelper)t.GetValue(SelectedHelperProperty);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;void&lt;/span&gt; SetSelectedHelper(TreeView t, &lt;br /&gt;                                           TreeViewSelectedHelper theValue) &lt;br /&gt;      {&lt;br /&gt;          t.SetValue(SelectedHelperProperty, theValue);&lt;br /&gt;      }&lt;br /&gt;      &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;void&lt;/span&gt; OnSelectedHelperChanged(&lt;br /&gt;                    DependencyObject depObj, &lt;br /&gt;                    DependencyPropertyChangedEventArgs e)&lt;br /&gt;      {&lt;br /&gt;         ((TreeViewSelectedHelper)e.NewValue).Register((TreeView)depObj);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;   }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This class define two properties: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;MySelected&lt;/code&gt;: the output property that is used to set the selected element in the view model&lt;/li&gt;&lt;li&gt;&lt;code&gt;SelectedHelper&lt;/code&gt;: which is used to as an object that modifies the value of &lt;code&gt;MySelected&lt;/code&gt; when the selected item changes(see below).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The following helper class is used to subscribe the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.treeview.selecteditemchanged(v=VS.95).aspx"&gt;SelectedItemChanged&lt;/a&gt; event and change "&lt;code&gt;MySelected&lt;/code&gt;" .&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;class&lt;/span&gt; TreeViewSelectedHelper &lt;br /&gt;   {&lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; TreeViewSelectedHelper() { }&lt;br /&gt;       &lt;span class="srckeyw"&gt;void&lt;/span&gt; SelectedItemChanged(object sender, &lt;br /&gt;                                RoutedPropertyChangedEventArgs&amp;lt;object&amp;gt; args)&lt;br /&gt;       {&lt;br /&gt;           (sender &lt;span class="srckeyw"&gt;as&lt;/span&gt; TreeView).SetValue(&lt;br /&gt;                        TreeViewSelectedBehavior.MySelectedProperty,&lt;br /&gt;                        ((sender &lt;span class="srckeyw"&gt;as&lt;/span&gt; TreeView)).SelectedItem);&lt;br /&gt;       }&lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;void&lt;/span&gt; Register(TreeView t)&lt;br /&gt;       {&lt;br /&gt;           t.SelectedItemChanged += SelectedItemChanged;&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can now compile this class:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;set NETFX4=c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\&lt;br /&gt;set WPFPATH=%NETFX4%\WPF&lt;br /&gt;csc /debug /r:%NETFX4%System.Xaml.dll /r:%WPFPATH%\WindowsBase.dll /r:%WPFPATH%\PresentationCore.dll /r:%WPFPATH%\PresentationFramework.dll  /target:library utils.cs&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The example&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Having defined this attached property and helper class we can now write the following example.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;Window xmlns=&lt;span class="srctext"&gt;"http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;/span&gt;&lt;br /&gt;        xmlns:x=&lt;span class="srctext"&gt;"http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt;&lt;br /&gt;        &lt;span style="font-weight:bold;"&gt;xmlns:utils=&lt;span class="srctext"&gt;"clr-namespace:Langexplr;assembly=utils"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        Title=&lt;span class="srctext"&gt;"TreeView selection test"&lt;/span&gt; Width=&lt;span class="srctext"&gt;"300"&lt;/span&gt; Height=&lt;span class="srctext"&gt;"300"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;   &amp;lt;Window.Resources&amp;gt;&lt;br /&gt;     &amp;lt;utils:TreeViewSelectedHelper x:Key=&lt;span class="srctext"&gt;"selHelper"&lt;/span&gt; /&amp;gt;&lt;br /&gt;   &amp;lt;/Window.Resources&amp;gt;&lt;/span&gt;&lt;br /&gt;   &amp;lt;StackPanel&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;TextBlock Text=&lt;span class="srctext"&gt;"{Binding selected.label}"&lt;/span&gt;/&amp;gt; &lt;br /&gt;         &amp;lt;TreeView ItemsSource=&lt;span class="srctext"&gt;"{Binding roots}"&lt;/span&gt;      &lt;br /&gt;                   &lt;span style="font-weight:bold;"&gt;utils:TreeViewSelectedBehavior.SelectedHelper=&lt;span class="srctext"&gt;"{StaticResource selHelper}"&lt;/span&gt;&lt;/span&gt;&amp;gt;&lt;br /&gt;             &lt;span style="font-weight:bold;"&gt;&amp;lt;utils:TreeViewSelectedBehavior.MySelected&amp;gt;&lt;br /&gt;               &amp;lt;Binding Path=&lt;span class="srctext"&gt;"selected"&lt;/span&gt; Mode=&lt;span class="srctext"&gt;"OneWayToSource"&lt;/span&gt;/&amp;gt; &lt;br /&gt;             &amp;lt;/utils:TreeViewSelectedBehavior.MySelected&amp;gt;&lt;/span&gt; &lt;br /&gt;              &amp;lt;TreeView.ItemTemplate&amp;gt;&lt;br /&gt;                  &amp;lt;HierarchicalDataTemplate ItemsSource=&lt;span class="srctext"&gt;"{Binding children}"&lt;/span&gt;&amp;gt;&lt;br /&gt;       &amp;lt;TextBlock Text=&lt;span class="srctext"&gt;"{Binding label}"&lt;/span&gt;/&amp;gt;&lt;br /&gt;    &amp;lt;/HierarchicalDataTemplate&amp;gt;&lt;br /&gt;       &amp;lt;/TreeView.ItemTemplate&amp;gt;&lt;br /&gt;         &amp;lt;/TreeView&amp;gt;&lt;br /&gt;   &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With this XAML definition we can write the following IronPython code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clr&lt;br /&gt;clr.AddReference(&lt;span class="srctext"&gt;"PresentationCore"&lt;/span&gt;)  &lt;br /&gt;clr.AddReference(&lt;span class="srctext"&gt;"PresentationFramework"&lt;/span&gt;)  &lt;br /&gt;clr.AddReference(&lt;span class="srctext"&gt;"WindowsBase"&lt;/span&gt;)  &lt;br /&gt;clr.AddReference(&lt;span class="srctext"&gt;'GalaSoft.MvvmLight.WPF4.dll'&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Markup &lt;span class="srckeyw"&gt;import&lt;/span&gt; XamlReader&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; Application&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.IO &lt;span class="srckeyw"&gt;import&lt;/span&gt; File&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Controls &lt;span class="srckeyw"&gt;import&lt;/span&gt; TreeView&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; System&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clrtype&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; GalaSoft.MvvmLight &lt;span class="srckeyw"&gt;import&lt;/span&gt; ViewModelBase&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Collections.ObjectModel &lt;span class="srckeyw"&gt;import&lt;/span&gt; ObservableCollection&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; TestModel(ViewModelBase):&lt;br /&gt;   __metaclass__ = clrtype.ClrClass&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;       self.name = &lt;span class="srctext"&gt;'algo'&lt;/span&gt;&lt;br /&gt;       self.root = NodeModel(&lt;span class="srctext"&gt;'x1'&lt;/span&gt;,[NodeModel(&lt;span class="srctext"&gt;'y2'&lt;/span&gt;,[NodeModel(&lt;span class="srctext"&gt;'z2'&lt;/span&gt;,[])]),&lt;br /&gt;                                   NodeModel(&lt;span class="srctext"&gt;'y3'&lt;/span&gt;,[])])&lt;br /&gt;&lt;br /&gt;       self.sselected = NodeModel(&lt;span class="srctext"&gt;''&lt;/span&gt;,[])&lt;br /&gt;&lt;br /&gt;   @property&lt;br /&gt;   @clrtype.accepts()&lt;br /&gt;   @clrtype.returns(System.Object)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; selected(self): &lt;br /&gt;      result = self.sselected&lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; result&lt;br /&gt;&lt;br /&gt;   @selected.setter&lt;br /&gt;   @clrtype.accepts(System.Object)&lt;br /&gt;   @clrtype.returns()&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; selected(self, value):&lt;br /&gt;      self.sselected = value&lt;br /&gt;      self.RaisePropertyChanged(&lt;span class="srctext"&gt;'selected'&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;   @property&lt;br /&gt;   @clrtype.accepts()&lt;br /&gt;   @clrtype.returns(System.Object)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; roots(self): &lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; [self.root]&lt;br /&gt;&lt;br /&gt;   @property&lt;br /&gt;   @clrtype.accepts()&lt;br /&gt;   @clrtype.returns(System.String)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; label(self): &lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; self.name&lt;br /&gt; &lt;br /&gt;   @label.setter&lt;br /&gt;   @clrtype.accepts(System.String)&lt;br /&gt;   @clrtype.returns()&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; label(self, value):&lt;br /&gt;      self.name = value&lt;br /&gt;      self.RaisePropertyChanged(&lt;span class="srctext"&gt;'label'&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; NodeModel:&lt;br /&gt;   __metaclass__ = clrtype.ClrClass&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self,label, initchildren):&lt;br /&gt;      self.children_collection = ObservableCollection[System.Object](initchildren)&lt;br /&gt;      self.name = label&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   @property&lt;br /&gt;   @clrtype.accepts()&lt;br /&gt;   @clrtype.returns(System.Object)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; label(self): &lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; self.name&lt;br /&gt;&lt;br /&gt;   @property&lt;br /&gt;   @clrtype.accepts()&lt;br /&gt;   @clrtype.returns(System.Object)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; children(self): &lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; self.children_collection&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;xamlFile = File.OpenRead(&lt;span class="srctext"&gt;'test.xaml'&lt;/span&gt;)&lt;br /&gt;window = XamlReader.Load(xamlFile)&lt;br /&gt;window.DataContext = TestModel()&lt;br /&gt;xamlFile.Close()&lt;br /&gt;&lt;br /&gt;Application().Run(window)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By running this example we can see how the label of the selected element of the TreeView is reflected in the TextBlock defined above.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/TUf3ckK0ZNI/AAAAAAAAAR8/zjQ8rFs8HLA/s1600/ipywpftreeviewselitem.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 141px; height: 80px;" src="http://4.bp.blogspot.com/_qePSufqunG4/TUf3ckK0ZNI/AAAAAAAAAR8/zjQ8rFs8HLA/s320/ipywpftreeviewselitem.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5568691534384358610" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-8076217489146648144?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/8076217489146648144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=8076217489146648144' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/8076217489146648144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/8076217489146648144'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2011/02/ironpython-wpf-data-binding-with.html' title='IronPython &amp; WPF: Data binding with TreeView&apos;s selected element'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_qePSufqunG4/TUf3ckK0ZNI/AAAAAAAAAR8/zjQ8rFs8HLA/s72-c/ipywpftreeviewselitem.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-269377140119201227</id><published>2011-01-31T05:31:00.002-06:00</published><updated>2011-01-31T05:36:06.376-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='xaml'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><title type='text'>IronPython &amp; Silverlight Part VI: Using the TreeView control</title><content type='html'>In this post I'm going to show a small example of using the Silverlight 4 &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.treeview%28v=vs.95%29.aspx"&gt;TreeView control&lt;/a&gt; with IronPython.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Referencing System.Windows.Controls.dll&lt;/h4&gt;&lt;br /&gt;Before we start using the TreeView control we need to add a reference to &lt;code&gt;System.Windows.Controls.dll&lt;/code&gt; . This assembly can be found in the &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=b3deb194-ca86-4fb6-a716-b67c2604a139&amp;displaylang=en"&gt;"Microsoft Silverlight 4 Tools for Visual Studio 2010"&lt;/a&gt; package.&lt;br /&gt;&lt;br /&gt;You need to copy this assembly to the location of &lt;code&gt;chiron.exe&lt;/code&gt; (ex. &lt;code&gt;IronPython2.7\Silverlight\bin&lt;/code&gt;) and add a reference to it in the &lt;code&gt;AppManifest.xaml&lt;/code&gt; file.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" &lt;br /&gt;            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" &lt;br /&gt;            &lt;span style="font-weight:bold;"&gt;RuntimeVersion="4.0.50917.0" &lt;/span&gt;&lt;br /&gt;            EntryPointAssembly="Microsoft.Scripting.Silverlight"  &lt;br /&gt;            EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication" &lt;br /&gt;            ExternalCallersFromCrossDomain="ScriptableOnly"&amp;gt;&lt;br /&gt;  &amp;lt;!-- Add assembly references here --&amp;gt;&lt;br /&gt;  &amp;lt;Deployment.Parts&amp;gt;&lt;br /&gt;... &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;    &amp;lt;AssemblyPart Source="System.Windows.Controls.dll" /&amp;gt;&lt;/span&gt;&lt;br /&gt;  &amp;lt;/Deployment.Parts&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;/Deployment&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Since we're using  Silverlight 4 we need to change the runtime version to "4.0.50917.0" (see this &lt;a href="http://langexplr.blogspot.com/2011/01/ironpython-silverlight-part-v-using.html"&gt;post&lt;/a&gt; for more details).&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Using the TreeView in XAML&lt;/h4&gt;&lt;br /&gt;Now that we have access to the assembly we can use it in &lt;code&gt;app.xaml&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;UserControl x:Class=&lt;span class="srctext"&gt;"System.Windows.Controls.UserControl"&lt;/span&gt;&lt;br /&gt; xmlns=&lt;span class="srctext"&gt;"http://schemas.microsoft.com/client/2007"&lt;/span&gt;&lt;br /&gt; xmlns:x=&lt;span class="srctext"&gt;"http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt;&lt;br /&gt;        xmlns:sdk=&lt;span class="srctext"&gt;"clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"&lt;/span&gt;&lt;br /&gt;        xmlns:wsdk=&lt;span class="srctext"&gt;"clr-namespace:System.Windows;assembly=System.Windows.Controls"&lt;/span&gt;&amp;gt;&lt;br /&gt;  &amp;lt;StackPanel x:Name=&lt;span class="srctext"&gt;"layout_root"&lt;/span&gt; Background=&lt;span class="srctext"&gt;"White"&lt;/span&gt;&amp;gt;&lt;br /&gt;    &amp;lt;TextBlock x:Name=&lt;span class="srctext"&gt;"Message"&lt;/span&gt; FontSize=&lt;span class="srctext"&gt;"30"&lt;/span&gt; Text=&lt;span class="srctext"&gt;"TreeView experiment"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;sdk:TreeView x:Name=&lt;span class="srctext"&gt;"tree"&lt;/span&gt;&amp;gt;&lt;br /&gt;       &amp;lt;sdk:TreeView.ItemTemplate&amp;gt;&lt;br /&gt;           &amp;lt;wsdk:HierarchicalDataTemplate ItemsSource=&lt;span class="srctext"&gt;"{Binding nodes}"&lt;/span&gt;&amp;gt;&lt;br /&gt;               &amp;lt;TextBlock Foreground=&lt;span class="srctext"&gt;"Red"&lt;/span&gt; Text=&lt;span class="srctext"&gt;"{Binding label}"&lt;/span&gt; /&amp;gt;&lt;br /&gt;           &amp;lt;/wsdk:HierarchicalDataTemplate&amp;gt;&lt;br /&gt;       &amp;lt;/sdk:TreeView.ItemTemplate&amp;gt;&lt;br /&gt;    &amp;lt;/sdk:TreeView&amp;gt;&lt;br /&gt;  &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;lt;/UserControl&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;TreeView data binding&lt;/h4&gt;&lt;br /&gt;The XAML file above shows that we're binding the content of the tree view to the &lt;code&gt;nodes&lt;/code&gt; property of the data source object. Here's the definition of the Python class used for this example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; Application&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Controls &lt;span class="srckeyw"&gt;import&lt;/span&gt; UserControl&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System &lt;span class="srckeyw"&gt;import&lt;/span&gt; Object&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Collections.ObjectModel &lt;span class="srckeyw"&gt;import&lt;/span&gt; ObservableCollection&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clrtype&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clr&lt;br /&gt;&lt;br /&gt;clr.AddReferenceToFile(&lt;span class="srctext"&gt;'GalaSoft.MvvmLight.SL4.dll'&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; GalaSoft.MvvmLight.Command &lt;span class="srckeyw"&gt;import&lt;/span&gt; RelayCommand&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; Node:&lt;br /&gt;  __metaclass__ = clrtype.ClrClass&lt;br /&gt;  __clrnamespace = &lt;span class="srctext"&gt;"LangexplrExperiments"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self,label,children):&lt;br /&gt;    self.text = label&lt;br /&gt;    self.children = children&lt;br /&gt;&lt;br /&gt;  @property &lt;br /&gt;  @clrtype.accepts()&lt;br /&gt;  @clrtype.returns(str)&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; label(self): &lt;br /&gt;     &lt;span class="srckeyw"&gt;return&lt;/span&gt; self.text&lt;br /&gt;&lt;br /&gt;  @property &lt;br /&gt;  @clrtype.accepts()&lt;br /&gt;  @clrtype.returns(Object)&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; nodes(self): &lt;br /&gt;     &lt;span class="srckeyw"&gt;return&lt;/span&gt; self.children&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class App:&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;    root = Application.Current.LoadRootVisual(UserControl(), &lt;span class="srctext"&gt;"app.xaml"&lt;/span&gt;)&lt;br /&gt;    root.tree.ItemsSource = [Node(&lt;span class="srctext"&gt;'level1'&lt;/span&gt;,&lt;br /&gt;                                 [Node(&lt;span class="srctext"&gt;'level11'&lt;/span&gt;,[]),&lt;br /&gt;                                  Node(&lt;span class="srctext"&gt;'level12'&lt;/span&gt;,[Node(&lt;span class="srctext"&gt;'level121'&lt;/span&gt;,[])])&lt;br /&gt;                                 ])]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;App()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With this changes we can run &lt;code&gt;chiron.exe /b&lt;/code&gt; and we get:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_qePSufqunG4/TUadgWktJ7I/AAAAAAAAAR0/kFkoQJxV53w/s1600/treeviewslipyexample.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 187px;" src="http://3.bp.blogspot.com/_qePSufqunG4/TUadgWktJ7I/AAAAAAAAAR0/kFkoQJxV53w/s320/treeviewslipyexample.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5568311168431105970" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-269377140119201227?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/269377140119201227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=269377140119201227' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/269377140119201227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/269377140119201227'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2011/01/ironpython-silverlight-part-vi-treeview.html' title='IronPython &amp; Silverlight Part VI: Using the TreeView control'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_qePSufqunG4/TUadgWktJ7I/AAAAAAAAAR0/kFkoQJxV53w/s72-c/treeviewslipyexample.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-6892275980565925070</id><published>2011-01-29T06:21:00.003-06:00</published><updated>2011-01-29T06:23:05.381-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='xaml'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><title type='text'>IronPython &amp; Silverlight Part V: Using the MVVM Light Toolkit</title><content type='html'>In this post I'm going to show a small example of using the &lt;a href="http://www.galasoft.ch/mvvm/getstarted//"&gt;MVVM Light Toolkit&lt;/a&gt; in Silverlight with &lt;a href="http://ironpython.net/"&gt;IronPython&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;MVVM Light&lt;/h4&gt;&lt;br /&gt;According to its website, MVVM Light Toolkit is a:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;...set of components helping people to get started in the Model - View - ViewModel pattern in Silverlight and WPF...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;It provides useful elements such an implementation of "&lt;a href="http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030"&gt;Relay Command&lt;/a&gt;" and a feature to expose events as commands (&lt;a href="http://geekswithblogs.net/lbugnion/archive/2009/11/05/mvvm-light-toolkit-v3-alpha-2-eventtocommand-behavior.aspx"&gt;EventToCommand&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;In the context of IronPython it will save us a lot of code.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Adding a reference to MVVM Light&lt;/h4&gt;&lt;br /&gt;There are several ways to add a reference to the MVVM Light Toolkit assembly. However the first step is to set the Silverlight version to 4 (see &lt;a href="http://langexplr.blogspot.com/2011/01/ironpython-silverlight-part-iv-using.html"&gt;this post&lt;/a&gt; for more information).&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Adding the reference using the manifest&lt;/h4&gt;&lt;br /&gt;One way to add the reference is to use the manifest &lt;code&gt;AppManifest.xaml&lt;/code&gt;. Once we generated this file(using &lt;code&gt;chiron.exe /m&lt;/code&gt; and copying it to &lt;code&gt;app/&lt;/code&gt;) and changed the Silverlight version to 4 (see &lt;a href="http://langexplr.blogspot.com/2011/01/ironpython-silverlight-part-iv-using.html"&gt;here&lt;/a&gt;) we can add an entry referencing the &lt;code&gt;GalaSoft.MvvmLight.SL4.dll&lt;/code&gt; assembly.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" &lt;br /&gt;            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&lt;br /&gt;            &lt;span style="font-weight:bold;"&gt;RuntimeVersion="4.0.50401.0" &lt;/span&gt;&lt;br /&gt;            EntryPointAssembly="Microsoft.Scripting.Silverlight" &lt;br /&gt;            EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication" &lt;br /&gt;            ExternalCallersFromCrossDomain="ScriptableOnly"&amp;gt;&lt;br /&gt;  &amp;lt;!-- Add assembly references here --&amp;gt;&lt;br /&gt;  &amp;lt;Deployment.Parts&amp;gt;&lt;br /&gt;...    &lt;br /&gt;    &lt;span style="font-weight:bold;"&gt;&amp;lt;AssemblyPart Source="GalaSoft.MvvmLight.SL4.dll"/&amp;gt;&lt;/span&gt;&lt;br /&gt;...    &lt;br /&gt;  &amp;lt;/Deployment.Parts&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;/Deployment&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Also we need to  copy of the &lt;code&gt;GalaSoft.MvvmLight.SL4.dll&lt;/code&gt; file to the &lt;code&gt;chiron.exe&lt;/code&gt; folder (ex. &lt;code&gt;IronPython\Silvelright\bin&lt;/code&gt;). &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Using it in Python&lt;/h4&gt;&lt;br /&gt;Once we referenced this file using the manifest we need to reference it from code.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;import clr&lt;br /&gt;clr.AddReferenceToFile('GalaSoft.MvvmLight.SL4.dll')&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Example&lt;/h4&gt;&lt;br /&gt;The following example shows the use of &lt;code&gt;RelayCommand&lt;/code&gt; and &lt;code&gt;ViewModelBase&lt;/code&gt; from IronPython.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;app.xaml:&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;UserControl x:Class="System.Windows.Controls.UserControl"&lt;br /&gt; xmlns="http://schemas.microsoft.com/client/2007"&lt;br /&gt; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&lt;br /&gt;        xmlns:wbc="clr-namespace:System.Windows.Controls"&amp;gt;&lt;br /&gt;  &amp;lt;StackPanel Width="300" x:Name="layout_root" Background="White"&amp;gt;&lt;br /&gt;     &amp;lt;TextBox x:Name="my_text_box" &lt;br /&gt;              Text="{Binding text_to_display, Mode=TwoWay}" /&amp;gt;&lt;br /&gt;&lt;br /&gt;     &amp;lt;TextBlock Text="{Binding text_to_display}" /&amp;gt;&lt;br /&gt;     &amp;lt;Button Content="Reset" Command="{Binding reset_command}"/&amp;gt;&lt;br /&gt;  &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;lt;/UserControl&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;app.py&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clr&lt;br /&gt;clr.AddReferenceToFile('GalaSoft.MvvmLight.SL4.dll')&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; Application&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Controls &lt;span class="srckeyw"&gt;import&lt;/span&gt; UserControl&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; System&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clrtype&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; MessageBox&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; GalaSoft.MvvmLight.Command &lt;span class="srckeyw"&gt;import&lt;/span&gt; RelayCommand&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; GalaSoft.MvvmLight &lt;span class="srckeyw"&gt;import&lt;/span&gt; ViewModelBase&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; MyBasicModel(ViewModelBase):&lt;br /&gt;   __metaclass__ = clrtype.ClrClass&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;      self.text = &lt;span class="srctext"&gt;'Initial text'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   @property&lt;br /&gt;   @clrtype.accepts()&lt;br /&gt;   @clrtype.returns(System.String)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; text_to_display(self): return self.text&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   @text_to_display.setter&lt;br /&gt;   @clrtype.accepts(System.String)&lt;br /&gt;   @clrtype.returns()&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; text_to_display(self, value): &lt;br /&gt;       self.text = value&lt;br /&gt;       self.RaisePropertyChanged(&lt;span class="srctext"&gt;'text_to_display'&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;   @property&lt;br /&gt;   @clrtype.accepts()&lt;br /&gt;   @clrtype.returns(System.Object)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; reset_command(self): &lt;br /&gt;      return RelayCommand(&lt;span class="srckeyw"&gt;lambda&lt;/span&gt;: self.perform_reset_text() )&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; perform_reset_text(self):&lt;br /&gt;      self.text_to_display = &lt;span class="srctext"&gt;''&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; App:&lt;br /&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;&lt;br /&gt;    self.model = MyBasicModel()&lt;br /&gt;    self.root = Application.Current.LoadRootVisual(UserControl(), &lt;span class="srctext"&gt;"app.xaml"&lt;/span&gt;)&lt;br /&gt;    self.root.DataContext = self.model&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;theApp = App()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Using this library from IronPython saves us from many thins such as having to declare events to comply with the &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.95).aspx"&gt;INotifyPropertyChanged&lt;/a&gt; interface.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-6892275980565925070?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/6892275980565925070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=6892275980565925070' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/6892275980565925070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/6892275980565925070'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2011/01/ironpython-silverlight-part-v-using.html' title='IronPython &amp; Silverlight Part V: Using the MVVM Light Toolkit'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-2128687619803908870</id><published>2011-01-25T06:00:00.001-06:00</published><updated>2011-01-25T06:23:44.918-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><title type='text'>IronPython &amp; Silverlight Part IV: Using Silverlight 4</title><content type='html'>The default Silverlight runtime version of programs created with &lt;a href="http://ironpython.codeplex.com/releases/view/48818"&gt;IronPython 2.7 Beta 1&lt;/a&gt;  is "2.0.31005.0". If you want to take advantage of &lt;a href="http://www.silverlight.net/getstarted/silverlight-4/"&gt;Silverlight 4&lt;/a&gt; features you have to make a small change to AppManifest.xaml.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For example, say that you want to add a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.richtextbox%28v=vs.95%29.aspx"&gt;RichTextBox&lt;/a&gt; control(available on Silverlight 4).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;UserControl x:Class="System.Windows.Controls.UserControl"&lt;br /&gt; xmlns="http://schemas.microsoft.com/client/2007"&lt;br /&gt; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&lt;br /&gt;        xmlns:wbc="clr-namespace:System.Windows.Controls"&amp;gt;&lt;br /&gt;  &amp;lt;StackPanel Width="300" x:Name="layout_root" Background="White"&amp;gt;&lt;br /&gt;     &amp;lt;wbc:RichTextBox x:Name="rtb" /&amp;gt;&lt;br /&gt;     &amp;lt;Button x:Name="my_button" Content="Ok"/&amp;gt;&lt;br /&gt;  &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;lt;/UserControl&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; Application&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Controls &lt;span class="srckeyw"&gt;import&lt;/span&gt; UserControl&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; System&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; App:&lt;br /&gt;&lt;br /&gt;  def __init__(self):&lt;br /&gt;    self.theText = &lt;span class="srctext"&gt;"""&lt;br /&gt;this&lt;br /&gt;is&lt;br /&gt;some&lt;br /&gt;text"""&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    self.root = Application.Current.LoadRootVisual(UserControl(), &lt;span class="srctext"&gt;"app.xaml"&lt;/span&gt;)&lt;br /&gt;    self.root.rtb.Selection.Select(self.root.rtb.ContentStart, self.root.rtb.ContentEnd)&lt;br /&gt;    self.root.rtb.Selection.Text = self.theText&lt;br /&gt;&lt;br /&gt;theApp = App()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In order to make this program work you have to add the &lt;code&gt;AppManifest.xaml&lt;/code&gt; to the &lt;code&gt;app/&lt;/code&gt; folder of your application. You can get a copy of this file using &lt;code&gt;chiron.exe /m&lt;/code&gt; :&lt;br /&gt;&lt;br /&gt;By default this file looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" &lt;br /&gt;            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" &lt;br /&gt;            &lt;span style="font-weight:bold;"&gt;RuntimeVersion="2.0.31005.0" &lt;/span&gt;&lt;br /&gt;            EntryPointAssembly="Microsoft.Scripting.Silverlight" &lt;br /&gt;            EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication" &lt;br /&gt;            ExternalCallersFromCrossDomain="ScriptableOnly"&amp;gt;&lt;br /&gt;  &amp;lt;!-- Add assembly references here --&amp;gt;&lt;br /&gt;  &amp;lt;Deployment.Parts&amp;gt;&lt;br /&gt;    &amp;lt;!-- In the XAP --&amp;gt;&lt;br /&gt;    &amp;lt;!-- &amp;lt;AssemblyPart Source="Foo.dll" /&amp;gt; --&amp;gt;&lt;br /&gt;    &amp;lt;!-- Outside the XAP, same domain --&amp;gt;&lt;br /&gt;    &amp;lt;!-- &amp;lt;AssemblyPart Source="/Foo.dll" /&amp;gt; --&amp;gt;&lt;br /&gt;    &amp;lt;!-- Outside the XAP, different domain --&amp;gt;&lt;br /&gt;    &amp;lt;!-- &amp;lt;AssemblyPart Source="http://bar.com/Foo.dll" /&amp;gt; --&amp;gt;&lt;br /&gt;    &amp;lt;AssemblyPart Source="Microsoft.Scripting.Silverlight.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;AssemblyPart Source="System.Numerics.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;AssemblyPart Source="Microsoft.Scripting.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;AssemblyPart Source="Microsoft.Dynamic.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;AssemblyPart Source="IronPython.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;AssemblyPart Source="IronPython.Modules.dll" /&amp;gt;&lt;br /&gt;  &amp;lt;/Deployment.Parts&amp;gt;&lt;br /&gt;  &amp;lt;!-- Add transparent platform extensions (.slvx) references here --&amp;gt;&lt;br /&gt;  &amp;lt;Deployment.ExternalParts&amp;gt;&lt;br /&gt;    &amp;lt;!-- Example --&amp;gt;&lt;br /&gt;    &amp;lt;!-- &amp;lt;ExtensionPart Source="http://bar.com/v1/Foo.slvx" /&amp;gt; --&amp;gt;&lt;br /&gt;  &amp;lt;/Deployment.ExternalParts&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;/Deployment&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After copying this file to the &lt;code&gt;app/&lt;/code&gt; folder you have to change the &lt;code&gt;RuntimeVersion&lt;/code&gt; attribute value to &lt;code&gt;"4.0.50401.0"&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Now to can run the application and have access to Silverlight 4 features.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-2128687619803908870?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/2128687619803908870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=2128687619803908870' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2128687619803908870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2128687619803908870'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2011/01/ironpython-silverlight-part-iv-using.html' title='IronPython &amp; Silverlight Part IV: Using Silverlight 4'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-282108151071746233</id><published>2010-12-15T05:58:00.003-06:00</published><updated>2010-12-17T16:26:32.187-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><title type='text'>IronPython &amp; Silverlight Part III: Basic Data Binding</title><content type='html'>One of the nicest features of Silverlight is &lt;a href="http://msdn.microsoft.com/en-us/library/cc278072(v=vs.95).aspx"&gt;data binding&lt;/a&gt;. This feature allows you to perform and receive changes on the UI without explicitly adding or removing elements from UI controls.  For example: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;TextBox Text="{Binding TextToDisplay}"&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This &lt;a href="http://msdn.microsoft.com/en-us/library/cc189036(v=vs.95).aspx"&gt;XAML&lt;/a&gt; code says that the value of the &lt;code&gt;Text&lt;/code&gt; property is bound to the &lt;code&gt;TextToDisplay&lt;/code&gt; property of the of the object specified by the &lt;code&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.datacontext(v=vs.95).aspx"&gt;DataContext&lt;/a&gt;&lt;/code&gt; property.&lt;br /&gt;&lt;br /&gt;As with other Silverlight features data binding requires you to use a .NET object with properties. We can use &lt;a href="https://github.com/IronLanguages/main/tree/master/Languages/IronPython/Samples/ClrType"&gt;clrtype&lt;/a&gt; to take advantage of this feature with IronPython.&lt;br /&gt;&lt;br /&gt;For example, say that we want to bind a text property to a Python object to a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox%28v=vs.95%29.aspx"&gt;TextBox&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;UserControl x:Class="System.Windows.Controls.UserControl"&lt;br /&gt; xmlns="http://schemas.microsoft.com/client/2007"&lt;br /&gt; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&amp;gt;&lt;br /&gt;  &amp;lt;StackPanel Width="300" x:Name="layout_root" Background="White"&amp;gt;&lt;br /&gt;     &amp;lt;TextBox x:Name="my_text_box" &lt;br /&gt;              Text="{Binding text_to_display, Mode=TwoWay}" /&amp;gt;&lt;br /&gt;     &amp;lt;Button x:Name="my_button" Content="Show text"/&amp;gt;&lt;br /&gt;  &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;lt;/UserControl&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;app.py&lt;/code&gt; file looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; Application&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Controls &lt;span class="srckeyw"&gt;import&lt;/span&gt; UserControl&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; System&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clrtype&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; MessageBox&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; MyData:&lt;br /&gt;   __metaclass__ = clrtype.ClrClass&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;      self.text = &lt;span class="srckeyw"&gt;'Initial text'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   @property&lt;br /&gt;   @clrtype.accepts()&lt;br /&gt;   @clrtype.returns(System.String)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; text_to_display(self): return self.text&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   @text_to_display.setter&lt;br /&gt;   @clrtype.accepts(System.String)&lt;br /&gt;   @clrtype.returns()&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; text_to_display(self, value): &lt;br /&gt;       self.text = value&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; App:&lt;br /&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; handle_click(self, sender, event_args):&lt;br /&gt;      MessageBox.Show(self.data.text)&lt;br /&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;    self.data = MyData()&lt;br /&gt;    self.root = Application.Current.LoadRootVisual(UserControl(), &lt;span class="srckeyw"&gt;"app.xaml"&lt;/span&gt;)&lt;br /&gt;    self.root.my_text_box.DataContext = self.data&lt;br /&gt;    self.root.my_button.Click += lambda s,ea: self.handle_click(s,ea)&lt;br /&gt;&lt;br /&gt;theApp = App()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here the definition of &lt;code&gt;MyData&lt;/code&gt; is decorated with the information on how to generate the .NET class elements to be exposed .&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Since the binding is declarated as &lt;code&gt;TwoWay&lt;/code&gt; modifications to the &lt;code&gt;TextBox&lt;/code&gt; are reflected in the &lt;code&gt;data&lt;/code&gt; instance.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/TQg3_t3VUVI/AAAAAAAAARU/phaKE5M38vU/s1600/tmpslipdbimg.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 314px; height: 142px;" src="http://2.bp.blogspot.com/_qePSufqunG4/TQg3_t3VUVI/AAAAAAAAARU/phaKE5M38vU/s320/tmpslipdbimg.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5550748108517101906" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As with &lt;a href="http://langexplr.blogspot.com/2010/11/using-ironpython-with-silverlight-part.html"&gt;Part I &lt;/a&gt;and &lt;a href="http://langexplr.blogspot.com/2010/12/ironpython-silverlight-part-ii-basic.html"&gt;Part II&lt;/a&gt; of these series, IronPython 2.7 beta 1 is used for all examples.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-282108151071746233?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/282108151071746233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=282108151071746233' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/282108151071746233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/282108151071746233'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/12/ironpython-silverlight-part-iii-basic.html' title='IronPython &amp; Silverlight Part III: Basic Data Binding'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_qePSufqunG4/TQg3_t3VUVI/AAAAAAAAARU/phaKE5M38vU/s72-c/tmpslipdbimg.JPG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-1753046392175319185</id><published>2010-12-07T06:05:00.000-06:00</published><updated>2010-12-07T06:06:43.090-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><title type='text'>IronPython &amp; Silverlight Part II: Basic event handling</title><content type='html'>There are a couple of ways to add event handlers to Silverlight controls. The common way is to add the event handlers directly in &lt;a href="http://msdn.microsoft.com/en-us/library/cc189036(VS.95).aspx"&gt;XAML&lt;/a&gt;. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;Button x:Name="ButtonGo" Content="Go!" Click="MyClickHandler" /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Given that there's a definition for the &lt;code&gt;MyClickHandler&lt;/code&gt; method in your C# code. However for IronPython there's a couple of options:&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Directly in Python code&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Event handlers can be added as in C# by using the '+=' operator. For example say that you have the following XAML code describing an UserControl:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;UserControl x:Class="System.Windows.Controls.UserControl"&lt;br /&gt; xmlns="http://schemas.microsoft.com/client/2007"&lt;br /&gt; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;StackPanel Width="300" x:Name="layout_root" Background="White"&amp;gt;&lt;br /&gt;    &amp;lt;TextBlock x:Name="Message" FontSize="30" /&amp;gt;&lt;br /&gt;    &amp;lt;Button x:Name="ButtonGo" Content="Go!" /&amp;gt;&lt;br /&gt;  &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;  &amp;lt;UserControl.Resources&amp;gt;&lt;br /&gt;     &amp;lt;Storyboard x:Name="MyStoryboard"&amp;gt;&lt;br /&gt;        &amp;lt;DoubleAnimation &lt;br /&gt;             Storyboard.TargetName="Message"&lt;br /&gt;             Storyboard.TargetProperty="Opacity"&lt;br /&gt;             From="1.0" To="0.0" Duration="0:0:3"&lt;br /&gt;             AutoReverse="True"&lt;br /&gt;             RepeatBehavior="Forever"/&amp;gt;&lt;br /&gt;     &amp;lt;/Storyboard&amp;gt;&lt;br /&gt;  &amp;lt;/UserControl.Resources&amp;gt;&lt;br /&gt;&amp;lt;/UserControl&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Say we want to start the 'MyStoryboard' animation in the event handler for the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.buttonbase.click(v=VS.95).aspx"&gt;Click event&lt;/a&gt; of the &lt;code&gt;ButtonGo&lt;/code&gt; button. We can write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows import Application&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Controls import UserControl&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;def&lt;/span&gt; handle_click(sender, event_args):&lt;br /&gt;   theApp.root.MyStoryboard.Begin()&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; App:&lt;br /&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;    self.root = Application.Current.LoadRootVisual(MyUserControl(), "app.xaml")&lt;br /&gt;    self.root.Message.Text = &lt;span class="srckeyw"&gt;"Welcome to Python and Silverlight!"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;    self.root.ButtonGo.Click += handle_click&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;theApp = App()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Using &lt;code&gt;clrtype&lt;/code&gt;&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;clrtype&lt;/code&gt; module can be used to define .NET classes from (Iron)Python classes . This module can be found in the &lt;a href="http://ironpython.codeplex.com/wikipage?title=Samples"&gt;IronPython samples package&lt;/a&gt; or &lt;a href="https://github.com/IronLanguages/main/tree/master/Languages/IronPython/Samples/ClrType"&gt;here&lt;/a&gt; in the GitHub repository.  The &lt;a href="http://gui-at.blogspot.com/"&gt;GUI Automated Testing&lt;/a&gt; blog has some &lt;a href="http://gui-at.blogspot.com/2010/05/silverlight-validation-in-ironpython.html"&gt;nice&lt;/a&gt; &lt;a href="http://gui-at.blogspot.com/2009/11/wcf-service-in-pure-ironpython.html"&gt;tutorials&lt;/a&gt; on using clrtype. &lt;br /&gt;&lt;br /&gt;To use this module, you have to copy the &lt;code&gt;clrtype.py&lt;/code&gt; file to your &lt;code&gt;app/&lt;/code&gt; folder. &lt;br /&gt;&lt;br /&gt;We can change the code this way:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; Application&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Controls &lt;span class="srckeyw"&gt;import&lt;/span&gt; UserControl&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; MessageBox&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; System&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clrtype&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; MyUserControl(UserControl):&lt;br /&gt;   __metaclass__ = clrtype.ClrClass&lt;br /&gt;&lt;br /&gt;   _clrnamespace = &lt;span class="srctext"&gt;"MyNs"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;   @clrtype.accepts(System.Object, System.EventArgs)&lt;br /&gt;   @clrtype.returns(System.Void)&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; my_click_handler(self, sender, event_args):&lt;br /&gt;      theApp.root.MyStoryboard.Begin()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __getattr__(self, name):&lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; self.FindName(name)&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;def&lt;/span&gt; handle_click(sender,event_args):&lt;br /&gt;   theApp.root.MyStoryboard.Begin()&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; App:&lt;br /&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;    self.root = Application.Current.LoadRootVisual(MyUserControl(), "app.xaml")&lt;br /&gt;    self.root.Message.Text = &lt;span class="srctext"&gt;"Welcome to Python and Silverlight!"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;theApp = App()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With these definitions we can change the XAML code for the &lt;code&gt;Button&lt;/code&gt; to have be:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;Button x:Name="ButtonGo" Content="Go!" &lt;span style="font-weight:bold;"&gt;Click="my_click_handler"&lt;/span&gt;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that the definition of &lt;code&gt;MyUserControl&lt;/code&gt; has a definition for &lt;code&gt;__getattr__&lt;/code&gt;. This definition is used to still be able to access the definitions of child controls for example &lt;code&gt;theApp.root.MyStoryboard&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Final words&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Another way to do event handling is to use &lt;a href="http://johnpapa.net/silverlight/5-simple-steps-to-commanding-in-silverlight/"&gt;Commanding&lt;/a&gt;. This approach is preferred for &lt;a href="http://en.wikipedia.org/wiki/Model_View_ViewModel"&gt;MVVM&lt;/a&gt;. For future posts I'll try to cover the use of Commanding with IronPython.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-1753046392175319185?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/1753046392175319185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=1753046392175319185' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/1753046392175319185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/1753046392175319185'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/12/ironpython-silverlight-part-ii-basic.html' title='IronPython &amp; Silverlight Part II: Basic event handling'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-9093614259898705878</id><published>2010-11-30T21:42:00.000-06:00</published><updated>2010-11-30T21:43:45.694-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><title type='text'>Using IronPython with Silverlight, Part I</title><content type='html'>This is the first of series of posts on the topic of using &lt;a href="http://ironpython.codeplex.com/"&gt;IronPython &lt;/a&gt;to create &lt;a href="http://www.silverlight.net/"&gt;Silverlight&lt;/a&gt; programs. Experimenting with these technologies is nice because you only need a text editor and the IronPython distribution.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Getting started&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In these series of posts I'll be using &lt;a href="http://ironpython.codeplex.com/releases/view/48818"&gt;IronPython 2.7&lt;/a&gt; (which is in beta right now) and Silverlight 4 . &lt;br /&gt;&lt;br /&gt;Once these packages are installed the first step is to copy a basic program template to a your work directory. The template is located in &lt;code&gt;(IronPython path)\Silverlight\script\templates\python&lt;/code&gt;. &lt;br /&gt;&lt;br /&gt;This template contains the following structure:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;C:.&lt;br /&gt;¦   index.html&lt;br /&gt;¦&lt;br /&gt;+---app&lt;br /&gt;¦       app.py&lt;br /&gt;¦       app.xaml&lt;br /&gt;¦&lt;br /&gt;+---css&lt;br /&gt;¦       screen.css&lt;br /&gt;¦&lt;br /&gt;+---js&lt;br /&gt;        error.js&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;app.py&lt;/code&gt; and &lt;code&gt;app.xaml&lt;/code&gt; files contain the code for the entry point of the demo Silverlight application. The &lt;code&gt;index.html&lt;/code&gt; file contains the Silverlight control host.&lt;br /&gt;&lt;br /&gt;The default &lt;code&gt;app.xaml&lt;/code&gt; code looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;UserControl x:Class="System.Windows.Controls.UserControl"&lt;br /&gt; xmlns="http://schemas.microsoft.com/client/2007"&lt;br /&gt; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;Grid x:Name="layout_root" Background="White"&amp;gt;&lt;br /&gt;    &amp;lt;TextBlock x:Name="Message" FontSize="30" /&amp;gt;&lt;br /&gt;  &amp;lt;/Grid&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/UserControl&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The default &lt;code&gt;app.py&lt;/code&gt; code looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows &lt;span class="srckeyw"&gt;import&lt;/span&gt; Application&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Windows.Controls &lt;span class="srckeyw"&gt;import&lt;/span&gt; UserControl&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; App:&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;    root = Application.Current.LoadRootVisual(UserControl(), &lt;span class="srctext"&gt;"app.xaml"&lt;/span&gt;)&lt;br /&gt;    root.Message.Text = &lt;span class="srctext"&gt;"Welcome to Python and Silverlight!"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;App()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see this code loads the &lt;a href="http://msdn.microsoft.com/en-us/library/cc189036(VS.95).aspx"&gt;XAML&lt;/a&gt; file for defining the 'root visual' . The 'root.Message.Text = ...' assignment changes the text displayed by the 'Message' TextBlock instance. Notice that it uses the name of the control as if it were a member of the UserControl instance returned by LoadRootVisual.  This is accomplished by using a &lt;a href="http://dlr.codeplex.com/"&gt;DLR&lt;/a&gt; feature defined in the &lt;code&gt;FrameworkElementExtension&lt;/code&gt; class (see &lt;a href="https://github.com/IronLanguages/main/blob/master/Hosts/Silverlight/Microsoft.Scripting.Silverlight/ExtensionTypes.cs"&gt;ExtensionTypes.cs&lt;/a&gt; )&lt;br /&gt;&lt;br /&gt;You can easily run this example by going to the command line and running Chiron:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;C:\development\blog\ipy\basictest&amp;gt;c:\development\IronPython-2.7\Silverlight\bin\Chiron.exe /b&lt;br /&gt;Chiron - Silverlight Dynamic Language Development Utility. Version 1.0.0.0&lt;br /&gt;Chiron serving 'C:\development\blog\ipy\basictest' as http://localhost:2060/&lt;br /&gt;21:03:45 200     1,185 /&lt;br /&gt;21:03:45 200       792 /style.css!&lt;br /&gt;21:03:45 200     2,492 /sl.png!&lt;br /&gt;21:03:45 200       642 /slx.png!&lt;br /&gt;21:03:49 404       580 /favicon.ico [Resource not found]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running Chiron this way will start the web server and will open a web browser in its root.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/TPW8m_fneqI/AAAAAAAAAQ8/WK2X-07_53g/s1600/basicchrion1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 246px;" src="http://2.bp.blogspot.com/_qePSufqunG4/TPW8m_fneqI/AAAAAAAAAQ8/WK2X-07_53g/s320/basicchrion1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5545545894241729186" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(Note: For IronPython 2.7 Beta you have to copy the &lt;code&gt;System.Numerics.dll&lt;/code&gt; assembly in the %IPY_HOME\Silverlight\bin folder, this file could be found in the &lt;a href="https://www.silverlight.net/getstarted/"&gt;Silverlight SDK&lt;/a&gt; distribution).&lt;br /&gt;&lt;br /&gt;When you select the &lt;code&gt;index.html&lt;/code&gt; file the Silverlight program is executed. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_qePSufqunG4/TPW8879ikmI/AAAAAAAAARE/0tZjN99fu2I/s1600/basicchrion2.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 265px;" src="http://1.bp.blogspot.com/_qePSufqunG4/TPW8879ikmI/AAAAAAAAARE/0tZjN99fu2I/s320/basicchrion2.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5545546271250616930" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see an IronPython REPL console is activated by default in this template. This console is activated by using the following tag in the HTML file.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;param name="initParams" value="reportErrors=errorLocation, &lt;span style="font-weight:bold;"&gt;console=true&lt;/span&gt;" /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The nice thing about this is that you can manipulate the Silverlight application while is executing. To see an example of this, we can change the definition of the &lt;code&gt;App&lt;/code&gt; class to be like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; App:&lt;br /&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(self):&lt;br /&gt;    self.root = Application.Current.LoadRootVisual(UserControl(), &lt;span class="srckeyw"&gt;"app.xaml"&lt;/span&gt;)&lt;br /&gt;    self.root.Message.Text = &lt;span class="srckeyw"&gt;"Welcome to Python and Silverlight!"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;theApp = App()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With this change we can now have access to the UI elements defined in XAML. For example:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_qePSufqunG4/TPW_PotnucI/AAAAAAAAARM/3isz_QVVKZk/s1600/basicchrion3.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 283px;" src="http://1.bp.blogspot.com/_qePSufqunG4/TPW_PotnucI/AAAAAAAAARM/3isz_QVVKZk/s320/basicchrion3.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5545548791524342210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For future posts I'm going to talk about specific topics on the use of Silverlight and IronPython.&lt;br /&gt;&lt;br /&gt;A nice source of information on this topic is the following page by Michael Foord &lt;a href="http://www.voidspace.org.uk/ironpython/silverlight/index.shtml"&gt;"Python in your Browser with Silverlight"&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-9093614259898705878?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/9093614259898705878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=9093614259898705878' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/9093614259898705878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/9093614259898705878'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/11/using-ironpython-with-silverlight-part.html' title='Using IronPython with Silverlight, Part I'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_qePSufqunG4/TPW8m_fneqI/AAAAAAAAAQ8/WK2X-07_53g/s72-c/basicchrion1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-3006038926263670422</id><published>2010-10-25T05:44:00.004-06:00</published><updated>2010-10-25T05:51:37.509-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Writing Python's groupby in C#</title><content type='html'>A couple of days ago, while working on a C# program, I had the necessity of grouping contiguous  elements from a sequence given a property. A group needs to be created each time the value of the property changes in a similar way to the &lt;a href="http://en.wikipedia.org/wiki/Uniq"&gt;uniq&lt;/a&gt; Unix utility.&lt;br /&gt;&lt;br /&gt;Python has a function called &lt;a href="http://docs.python.org/library/itertools.html#itertools.groupby"&gt;groupby&lt;/a&gt; which is part of the nice &lt;a href="http://docs.python.org/library/itertools.html"&gt;itertools&lt;/a&gt; module which does exactly what I want. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; strList = ["abc","ert","bre","sd","ghj","awe","ew","gh"]&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; [list(g) for i,g in groupby(strList,lambda x: len(x))]&lt;br /&gt;[['abc', 'ert', 'bre'], ['sd'], ['ghj', 'awe'], ['ew', 'gh']]&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; numList = [1,2,2,2,1,1,1,5,5]&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; [list(g) for i,g in groupby(numList)]&lt;br /&gt;[[1], [2, 2, 2], [1, 1, 1], [5, 5]]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In .NET a class called &lt;a href="http://msdn.microsoft.com/en-us/library/system.linq.enumerable.aspx"&gt;Enumerable&lt;/a&gt; with lots of extension methods to manipulate with sequences (&lt;a href="http://msdn.microsoft.com/en-us/library/9eekhta0.aspx"&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/a&gt;). This class includes an extension method called &lt;a href="http://msdn.microsoft.com/en-us/library/bb549272.aspx"&gt;GroupBy&lt;/a&gt; which groups values according to a key. However it behaves more like  &lt;a href="http://www.w3schools.com/sql/sql_groupby.asp"&gt;SQL's Group by&lt;/a&gt; in that it considers all the values of the collection. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;csharp&amp;gt; using System.Collections.Generic;&lt;br /&gt;csharp&amp;gt; var strList = new List&amp;lt;string&amp;gt;() {"abc","ert","bre","sd","ghj","awe","ew","gh"}; &lt;br /&gt;&lt;br /&gt;csharp&amp;gt; strList.GroupBy(x =&amp;gt; x.Length);&lt;br /&gt;{ { "abc", "ert", "bre", "ghj", "awe" }, { "sd", "ew", "gh" } }&lt;br /&gt;&lt;br /&gt;csharp&amp;gt; var numList = new List&amp;lt;int&amp;gt;() {1,2,2,2,1,1,1,5,5}; &lt;br /&gt;&lt;br /&gt;csharp&amp;gt; numList.GroupBy(x =&amp;gt; x);&lt;br /&gt;{ { 1, 1, 1, 1 }, { 2, 2, 2 }, { 5, 5 } }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(The C# examples will be presented using the very useful &lt;a href="http://www.mono-project.com/CsharpRepl"&gt;Mono C# REPL&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Writing the equivalent function in C# turned out to be a nice programming excessive. Also trying to write the function using only "&lt;a href="http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx"&gt;yield return&lt;/a&gt;" turned out the more challenging than I thought!. &lt;br /&gt;&lt;br /&gt;As a first try we can write this function using intermediate collections to store the partial groups:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="srckeyw"&gt;namespace&lt;/span&gt; Langexplr.Experiments &lt;br /&gt;{&lt;br /&gt;  &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;class&lt;/span&gt; MyTuple&amp;lt;T,K&amp;gt;&lt;br /&gt;  { &lt;br /&gt;     &lt;span class="srckeyw"&gt;public&lt;/span&gt; T Item1 { get; set; }&lt;br /&gt;     &lt;span class="srckeyw"&gt;public&lt;/span&gt; K Item2 { get; set; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;     &lt;span class="srckeyw"&gt;public&lt;/span&gt; static MyTuple&amp;lt;T1,K1&amp;gt; Create&amp;lt;T1,K1&amp;gt;(T1 first, K1 second)&lt;br /&gt;     {&lt;br /&gt;        &lt;span class="srckeyw"&gt;return&lt;/span&gt; &lt;span class="srckeyw"&gt;new&lt;/span&gt; MyTuple&amp;lt;T1,K1&amp;gt;() {Item1 = first, Item2 = second};&lt;br /&gt;     }&lt;br /&gt;  }&lt;br /&gt;  &lt;span class="srckeyw"&gt;public&lt;/span&gt; static &lt;span class="srckeyw"&gt;class&lt;/span&gt; GroupByTests&lt;br /&gt;  {&lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; static IEnumerable&amp;lt;MyTuple&amp;lt;K,IList&amp;lt;T&amp;gt;&amp;gt;&amp;gt; MyGroupByWithLists&amp;lt;T,K&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; en,Func&amp;lt;T,K&amp;gt; keyExtraction)&lt;br /&gt;       {&lt;br /&gt;          K currentKey = &lt;span class="srckeyw"&gt;default&lt;/span&gt;(K);&lt;br /&gt;          &lt;span class="srckeyw"&gt;bool&lt;/span&gt; firstTime = true;&lt;br /&gt;          IList&amp;lt;T&amp;gt; currentGroup = &lt;span class="srckeyw"&gt;new&lt;/span&gt; List&amp;lt;T&amp;gt;();&lt;br /&gt;          &lt;span class="srckeyw"&gt;foreach&lt;/span&gt;(var aValue in en)&lt;br /&gt;          {&lt;br /&gt;             &lt;span class="srckeyw"&gt;if&lt;/span&gt; (firstTime)&lt;br /&gt;             {&lt;br /&gt;                currentKey = keyExtraction(aValue);&lt;br /&gt;                firstTime = false;&lt;br /&gt;             }&lt;br /&gt;             &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;             {&lt;br /&gt;                K tmpKey = keyExtraction(aValue);&lt;br /&gt;                &lt;span class="srckeyw"&gt;if&lt;/span&gt; (!tmpKey.Equals(currentKey))&lt;br /&gt;                {&lt;br /&gt;                   &lt;span class="srckeyw"&gt;yield&lt;/span&gt; &lt;span class="srckeyw"&gt;return&lt;/span&gt; MyTuple&amp;lt;K,IList&amp;lt;T&amp;gt;&amp;gt;.Create(currentKey, currentGroup); &lt;br /&gt;                   currentGroup = &lt;span class="srckeyw"&gt;new&lt;/span&gt; List&amp;lt;T&amp;gt;();&lt;br /&gt;                   currentKey = tmpKey;&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;             }&lt;br /&gt;             currentGroup.Add(aValue);&lt;br /&gt;          }&lt;br /&gt;          &lt;span class="srckeyw"&gt;if&lt;/span&gt; (currentGroup.Count &amp;gt; 0)&lt;br /&gt;          {&lt;br /&gt;             &lt;span class="srckeyw"&gt;yield&lt;/span&gt; &lt;span class="srckeyw"&gt;return&lt;/span&gt; MyTuple&amp;lt;K,IList&amp;lt;T&amp;gt;&amp;gt;.Create(currentKey, currentGroup); &lt;br /&gt;          }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Here I'm defining a class called &lt;code&gt;MyTuple&lt;/code&gt; which is very similar to .NET 4' Tuple class to store group's key and members.&lt;br /&gt;&lt;br /&gt;This function works as expected, for example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;csharp&amp;gt; strList.MyGroupByWithLists(x =&amp;gt; x.Length).Select(x =&amp;gt; x.Item2).ToList();&lt;br /&gt;{ { "abc", "ert", "bre" }, { "sd" }, { "ghj", "awe" }, { "ew", "gh" } }&lt;br /&gt;csharp&amp;gt; numList.MyGroupByWithLists(x =&amp;gt; x).Select(x =&amp;gt; x.Item2).ToList();       &lt;br /&gt;{ { 1 }, { 2, 2, 2 }, { 1, 1, 1 }, { 5, 5 } }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One of the interesting things about the Python version of &lt;code&gt;groupby&lt;/code&gt; is that it doesn't create an intermediate collections for each group. The itertools module reference has the code for the groupby &lt;a href="http://docs.python.org/library/itertools.html#itertools.groupby"&gt;implementation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Trying to write a this function with similar characteristics in C# resulted in the following (scary) code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; IEnumerable&amp;lt;MyTuple&amp;lt;K,IEnumerable&amp;lt;T&amp;gt;&amp;gt;&amp;gt; MyGroupBy&amp;lt;T,K&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; en,Func&amp;lt;T,K&amp;gt; keyExtraction)&lt;br /&gt; {&lt;br /&gt;    K currentGroupKey = &lt;span class="srckeyw"&gt;default&lt;/span&gt;(K);&lt;br /&gt;    &lt;span class="srckeyw"&gt;bool&lt;/span&gt; firstTime = true;&lt;br /&gt;    &lt;span class="srckeyw"&gt;bool&lt;/span&gt; hasMoreElements = &lt;span class="srckeyw"&gt;false&lt;/span&gt;;&lt;br /&gt;    &lt;span class="srckeyw"&gt;bool&lt;/span&gt; yieldNewValue = &lt;span class="srckeyw"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    IEnumerator&amp;lt;T&amp;gt; enumerator = en.GetEnumerator();&lt;br /&gt;    hasMoreElements = enumerator.MoveNext();&lt;br /&gt;    &lt;span class="srckeyw"&gt;while&lt;/span&gt; (hasMoreElements) &lt;br /&gt;    {&lt;br /&gt;       &lt;span class="srckeyw"&gt;if&lt;/span&gt; (firstTime)&lt;br /&gt;       {&lt;br /&gt;          firstTime = &lt;span class="srckeyw"&gt;false&lt;/span&gt;;&lt;br /&gt;          yieldNewValue = true;&lt;br /&gt;          currentGroupKey = keyExtraction(enumerator.Current); &lt;br /&gt;       }&lt;br /&gt;       &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;       {&lt;br /&gt;          K lastKey;&lt;br /&gt;          &lt;span class="srckeyw"&gt;while&lt;/span&gt;((lastKey = keyExtraction(enumerator.Current)).Equals( currentGroupKey) &amp;amp;&amp;amp;&lt;br /&gt;                (hasMoreElements = enumerator.MoveNext()))&lt;br /&gt;          {&lt;br /&gt;&lt;br /&gt;          }&lt;br /&gt;          &lt;span class="srckeyw"&gt;if&lt;/span&gt;(hasMoreElements &amp;amp;&amp;amp;&lt;br /&gt;             !lastKey.Equals(currentGroupKey))&lt;br /&gt;          {&lt;br /&gt;             currentGroupKey = lastKey;&lt;br /&gt;             yieldNewValue = true;&lt;br /&gt;          }&lt;br /&gt;          &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;          {&lt;br /&gt;             yieldNewValue = &lt;span class="srckeyw"&gt;false&lt;/span&gt;;&lt;br /&gt;          }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="srckeyw"&gt;if&lt;/span&gt; (yieldNewValue) {&lt;br /&gt;          &lt;span class="srckeyw"&gt;yield&lt;/span&gt; &lt;span class="srckeyw"&gt;return&lt;/span&gt; MyTuple&amp;lt;K,IEnumerable&amp;lt;T&amp;gt;&amp;gt;.Create(&lt;br /&gt;                          currentGroupKey, &lt;br /&gt;                          ReturnSubSequence((x) =&amp;gt; { &lt;br /&gt;                             hasMoreElements = enumerator.MoveNext();&lt;br /&gt;                             &lt;span class="srckeyw"&gt;return&lt;/span&gt; hasMoreElements &amp;amp;&amp;amp;&lt;br /&gt;                                    x.Equals(keyExtraction(enumerator.Current)); },&lt;br /&gt;                            enumerator,&lt;br /&gt;                            currentGroupKey,&lt;br /&gt;                            enumerator.Current));&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt; }&lt;br /&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; ReturnSubSequence&amp;lt;T,K&amp;gt;(Predicate&amp;lt;K&amp;gt; pred, IEnumerator&amp;lt;T&amp;gt; seq,K currentElement,T first)&lt;br /&gt; {&lt;br /&gt;    &lt;span class="srckeyw"&gt;yield&lt;/span&gt; &lt;span class="srckeyw"&gt;return&lt;/span&gt; first; &lt;br /&gt;    &lt;span class="srckeyw"&gt;while&lt;/span&gt;( pred(currentElement)) &lt;br /&gt;    {&lt;br /&gt;       &lt;span class="srckeyw"&gt;yield&lt;/span&gt; &lt;span class="srckeyw"&gt;return&lt;/span&gt; seq.Current;&lt;br /&gt;    }&lt;br /&gt; }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Using this function we can write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;csharp&amp;gt; numList.MyGroupBy().Select(x =&amp;gt; x.Item1);         &lt;br /&gt;{ 1, 2, 1, 5 }&lt;br /&gt;csharp&amp;gt; numList.MyGroupBy().Select(x =&amp;gt; x.Item2.ToList());&lt;br /&gt;{ { 1 }, { 2, 2, 2 }, { 1, 1, 1 }, { 5, 5 } }&lt;br /&gt;csharp&amp;gt; strList.MyGroupBy(s =&amp;gt; s.Length).Select(x =&amp;gt; x.Item1);&lt;br /&gt;{ 3, 2, 3, 2 }&lt;br /&gt;csharp&amp;gt; strList.MyGroupBy(s =&amp;gt; s.Length).Select(x =&amp;gt; x.Item2.ToList());&lt;br /&gt;{ { "abc", "ert", "bre" }, { "sd" }, { "ghj", "awe" }, { "ew", "gh" } }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One interesting fact about this way of writing the &lt;code&gt;groupby&lt;/code&gt; function is that, you have to be very careful handling the resulting iterator/enumerable.  From Python's groupby documentation:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The returned group is itself an iterator that shares the underlying iterable with groupby(). Because the source is shared, when the groupby() object is advanced, the previous group is no longer visible&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;For example in Python, the following effect occurs if we consume the complete iterator before consuming each group:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; l = groupby(strList,lambda s: len(s))&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; consumed = list(groupby(strList,lambda s: len(s)))&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; [list(g) for k,g in consumed]&lt;br /&gt;[[], ['gh'], [], []]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In our C# version we have a similar restriction, for example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;csharp&amp;gt; var consumed = strList.MyGroupBy(s =&amp;gt; s.Length).ToList();&lt;br /&gt;csharp&amp;gt; consumed.Select(x =&amp;gt; x.Item2);&lt;br /&gt;{ { "abc" }, { "sd" }, { "ghj" }, { "ew" } }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://gist.github.com/644768"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-3006038926263670422?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/3006038926263670422/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=3006038926263670422' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/3006038926263670422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/3006038926263670422'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/10/writing-pythons-groupby-in-c.html' title='Writing Python&apos;s groupby in C#'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-5245479946979978414</id><published>2010-10-13T21:18:00.010-06:00</published><updated>2010-10-13T22:46:03.606-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vbnet'/><category scheme='http://www.blogger.com/atom/ns#' term='ironruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Using C#'s implicit type conversions from other .NET languages</title><content type='html'>One interesting &lt;a href="http://msdn.microsoft.com/en-us/vcsharp/default.aspx"&gt;C#&lt;/a&gt; feature is the ability to define a method that implements implicit conversion from one type to another. In this post I'm going to show how to use this feature from &lt;a href="http://ironpython.net/"&gt;IronPython&lt;/a&gt;, &lt;a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/"&gt;F#&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/vbasic/default.aspx"&gt;VB.NET&lt;/a&gt; and &lt;a href="http://ironruby.net/"&gt;IronRuby&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Example&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In order to illustrate the implicit conversion feature we're going to use the following classes:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;namespace&lt;/span&gt; Langexplr.Experiments&lt;br /&gt;{&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;class&lt;/span&gt; Complex &lt;br /&gt;   {&lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;double&lt;/span&gt; Real { &lt;span class="srckeyw"&gt;get&lt;/span&gt;; &lt;span class="srckeyw"&gt;set&lt;/span&gt;; }&lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;double&lt;/span&gt; Img { &lt;span class="srckeyw"&gt;get&lt;/span&gt;; &lt;span class="srckeyw"&gt;set&lt;/span&gt;; }&lt;br /&gt;       &lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;implicit operator&lt;/span&gt; Complex(&lt;span class="srckeyw"&gt;double&lt;/span&gt; real) &lt;br /&gt;       {&lt;br /&gt;           &lt;span class="srckeyw"&gt;return&lt;/span&gt; &lt;span class="srckeyw"&gt;new&lt;/span&gt; Complex() { Real = real };&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;implicit operator&lt;/span&gt; Polar(Complex complex) &lt;br /&gt;       {&lt;br /&gt;           &lt;span class="srckeyw"&gt;return&lt;/span&gt; &lt;span class="srckeyw"&gt;new&lt;/span&gt; Polar() { Angle = Math.Atan(complex.Img/complex.Real),&lt;br /&gt;                                Length = Math.Sqrt(complex.Real*complex.Real +&lt;br /&gt;                                                   complex.Img*complex.Img) };&lt;br /&gt;       }&lt;br /&gt;    &lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;implicit operator&lt;/span&gt; &lt;span class="srckeyw"&gt;double&lt;/span&gt;(Complex complex) &lt;br /&gt;       {&lt;br /&gt;           &lt;span class="srckeyw"&gt;return&lt;/span&gt; Math.Sqrt(complex.Real*complex.Real +&lt;br /&gt;                            complex.Img*complex.Img);&lt;br /&gt;       }&lt;br /&gt;       &lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;class&lt;/span&gt; Polar &lt;br /&gt;   {&lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;double&lt;/span&gt; Angle { &lt;span class="srckeyw"&gt;get&lt;/span&gt;; &lt;span class="srckeyw"&gt;set&lt;/span&gt;; }&lt;br /&gt;       &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;double&lt;/span&gt; Length { &lt;span class="srckeyw"&gt;get&lt;/span&gt;; &lt;span class="srckeyw"&gt;set&lt;/span&gt;; }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;Complex&lt;/code&gt; class is a simple definition of a complex number. The &lt;code&gt;Polar&lt;/code&gt; class is defined(conveniently) to represent a complex number in polar form. The &lt;code&gt;Complex&lt;/code&gt; class defines three implicit conversions:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;From &lt;code&gt;double&lt;/code&gt; to a complex number&lt;/li&gt;&lt;br /&gt;&lt;li&gt;From &lt;code&gt;Complex&lt;/code&gt; to &lt;code&gt;Polar&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;From &lt;code&gt;Complex&lt;/code&gt; to &lt;code&gt;double&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;The following C# code shows a use of this feature:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; Langexplr.Experiments;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; main &lt;br /&gt;{ &lt;br /&gt;  &lt;span class="srckeyw"&gt;public static&lt;/span&gt; &lt;span class="srckeyw"&gt;void&lt;/span&gt; Main(&lt;span class="srckeyw"&gt;string&lt;/span&gt;[] args) &lt;br /&gt;  {    &lt;br /&gt;       Complex c = 10.3;&lt;br /&gt;       Polar p = new Complex() {Real = 12.3, Img = 5.2};&lt;br /&gt;       &lt;span class="srckeyw"&gt;double&lt;/span&gt; abs = c;&lt;br /&gt;&lt;br /&gt;       Console.WriteLine(&lt;span class="srckeyw"&gt;"abs:{0} Polar: {1},{2}"&lt;/span&gt;, abs ,p.Angle ,p.Length);&lt;br /&gt;    } &lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By looking at the definitions generated by the compiler for the &lt;code&gt;Complex&lt;/code&gt; class, we can see several definitions for the &lt;code&gt;op_Implicit&lt;/code&gt; method with different parameters and return types.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;...&lt;br /&gt;.method public hidebysig specialname static &lt;br /&gt;        class Langexplr.Experiments.Complex &lt;br /&gt;        op_Implicit(float64 real) cil managed&lt;br /&gt;...&lt;br /&gt;.method public hidebysig specialname static &lt;br /&gt;        class Langexplr.Experiments.Polar &lt;br /&gt;        op_Implicit(class Langexplr.Experiments.Complex complex) cil managed&lt;br /&gt;...&lt;br /&gt;.method public hidebysig specialname static &lt;br /&gt;        float64  op_Implicit(class Langexplr.Experiments.Complex complex) cil managed&lt;br /&gt;...&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now these uses of the &lt;code&gt;Complex&lt;/code&gt; class will be presented on different .NET languages.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;IronPython&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As described in &lt;a href="http://www.voidspace.org.uk/ironpython/dark-corners.shtml"&gt;"Dark Corners of IronPython"&lt;/a&gt; by Michael Foord the &lt;code&gt;clr.Convert&lt;/code&gt; function can be used to convert between types using the &lt;code&gt;op_Implicit&lt;/code&gt;  if necessary.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clr&lt;br /&gt;clr.AddReference("ImplicitTest")&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; Langexplr.Experiments &lt;span class="srckeyw"&gt;import&lt;/span&gt; *&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System &lt;span class="srckeyw"&gt;import&lt;/span&gt; Double&lt;br /&gt;&lt;br /&gt;c = clr.Convert(10.3, Complex)&lt;br /&gt;nC = Complex()&lt;br /&gt;nC.Real = 12.3&lt;br /&gt;nC.Img = 5.2&lt;br /&gt;p = clr.Convert(nC, Polar)&lt;br /&gt;abs = clr.Convert(c, Double)&lt;br /&gt;&lt;br /&gt;print &lt;span class="srctxt"&gt;'abs: %(0)f Polar: %(1)f,%(2)f\n'&lt;/span&gt; % \&lt;br /&gt;       { &lt;span class="srctxt"&gt;'0'&lt;/span&gt;: abs, &lt;span class="srctxt"&gt;'1'&lt;/span&gt; : p.Angle, &lt;span class="srctxt"&gt;'2'&lt;/span&gt; : p.Length }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;IronRuby&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;IronRuby will use the &lt;code&gt;op_Implicit&lt;/code&gt; definition if a conversion required at a particular call. I couldn't find a nice way to do this directly as with IronPython's &lt;code&gt;clr.Convert&lt;/code&gt; . However the following function definition seems to do the trick:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;def&lt;/span&gt; dotnet_convert(value,type)&lt;br /&gt;   f =  System::Func[type,type].new {|x| x}&lt;br /&gt;   f.invoke(value)&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This conversion function works since IronRuby tries to convert the value to the expected .NET type in the call to 'invoke' . &lt;br /&gt;&lt;br /&gt;Using this definition we can write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;require &lt;span class="srctext"&gt;'ImplicitTest.dll'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;c = dotnet_convert(10.3,Langexplr::Experiments::Complex)&lt;br /&gt;nC = Langexplr::Experiments::Complex.new&lt;br /&gt;nC.Real = 12.3&lt;br /&gt;nC.Img = 5.2&lt;br /&gt;p = dotnet_convert(nC,Langexplr::Experiments::Polar)&lt;br /&gt;abs = dotnet_convert(c,System::Double)&lt;br /&gt;&lt;br /&gt;print &lt;span class="srctext"&gt;"abs: #{abs} Polar: #{p.Angle},#{p.Length} \n"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;F#&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In F# we can call the &lt;code&gt;op_Implicit&lt;/code&gt; method directly and F# will use type inference to determine the correct overload to use.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; Langexplr.Experiments&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; c : Complex = Complex.op_Implicit 10.3&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; p : Polar = Complex.op_Implicit (&lt;span class="srckeyw"&gt;new&lt;/span&gt; Complex(Real=12.3, Img=5.2))&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; abs : &lt;span class="srckeyw"&gt;double&lt;/span&gt; = Complex.op_Implicit c&lt;br /&gt;&lt;br /&gt;System.Console.WriteLine(&lt;span class="srctext"&gt;"1. {0} Polar: {1},{2} "&lt;/span&gt;, abs, p.Angle, p.Length )&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There's a nice post called &lt;a href="http://codebetter.com/blogs/matthew.podwysocki/archive/2009/06/11/f-duck-typing-and-structural-typing.aspx"&gt;"F# – Duck Typing and Structural Typing"&lt;/a&gt; by Matthew Podwysocki, which describes a nice way to define a generic function to use the op_Implicit operator.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; &lt;span class="srckeyw"&gt;inline&lt;/span&gt; convert (x:^a) : ^b =  ((^a &lt;span class="srckeyw"&gt;or&lt;/span&gt; ^b) : (&lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;member&lt;/span&gt; op_Implicit : ^a -&amp;gt; ^b) x )&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This function can be used as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; c2:Complex = convert 10.3&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; p2:Polar = convert (&lt;span class="srckeyw"&gt;new&lt;/span&gt; Complex(Real=12.3, Img=5.2))&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; abs2:&lt;span class="srckeyw"&gt;float&lt;/span&gt; = convert c&lt;br /&gt;&lt;br /&gt;System.Console.WriteLine(&lt;span class="srctext"&gt;"2. {0} Polar: {1},{2} "&lt;/span&gt;,abs2,p2.Angle,p2.Length)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;VB.NET&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Finally in Visual Basic .NET the implicit conversion is used automatically as in C#. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;Imports&lt;/span&gt; System&lt;br /&gt;&lt;span class="srckeyw"&gt;Imports&lt;/span&gt; Langexplr.Experiments&lt;br /&gt;&lt;span class="srckeyw"&gt;Module&lt;/span&gt; Test&lt;br /&gt;   &lt;span class="srckeyw"&gt;Sub&lt;/span&gt; Main&lt;br /&gt;      &lt;span class="srckeyw"&gt;Dim&lt;/span&gt; c &lt;span class="srckeyw"&gt;As&lt;/span&gt; Complex = 10.3&lt;br /&gt;      &lt;span class="srckeyw"&gt;Dim&lt;/span&gt; p &lt;span class="srckeyw"&gt;As&lt;/span&gt; Polar = new Complex() With { _&lt;br /&gt;            .Real = 12.3, _&lt;br /&gt;            .Img = 5.2 _&lt;br /&gt;      }&lt;br /&gt;      &lt;span class="srckeyw"&gt;Dim&lt;/span&gt; abs &lt;span class="srckeyw"&gt;As&lt;/span&gt; Double = c&lt;br /&gt;      Console.WriteLine(&lt;span class="srctext"&gt;"abs:{0} Polar: {1},{2}"&lt;/span&gt;,abs,p.Angle,p.Length)&lt;br /&gt;   &lt;span class="srckeyw"&gt;End&lt;/span&gt; &lt;span class="srckeyw"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;End&lt;/span&gt; &lt;span class="srckeyw"&gt;Module&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-5245479946979978414?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/5245479946979978414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=5245479946979978414' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/5245479946979978414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/5245479946979978414'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/10/using-cs-implicit-type-conversions-from.html' title='Using C#&apos;s implicit type conversions from other .NET languages'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-7809875603887461932</id><published>2010-08-23T05:37:00.001-06:00</published><updated>2010-08-23T05:37:26.672-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Extracting elements from Win32 resource files with F#</title><content type='html'>Recently I had the necessity of extracting cursors, bitmaps and icons stored in a Win32 compiled resource script file (.res) file. Although there are tools that could do that, this seems like a good excuse to use &lt;a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/"&gt;F#&lt;/a&gt; and code from &lt;br /&gt;a previous post: &lt;a href="http://langexplr.blogspot.com/2008/10/using-f-computation-expressions-to-read.html"&gt;"Using F# computation expressions to read binary files"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Resource file format&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The format for the compiled resource file is documented in MSDN &lt;a href="http://msdn.microsoft.com/en-us/library/ms648007(VS.85).aspx"&gt;"Resource File Formats"&lt;/a&gt; . According with this document each entry of the resource file is prefixed by the following header (RESOURCEHEADER) :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  DWORD DataSize;&lt;br /&gt;  DWORD HeaderSize;&lt;br /&gt;  DWORD TYPE;&lt;br /&gt;  DWORD NAME;&lt;br /&gt;  DWORD DataVersion;&lt;br /&gt;  WORD  MemoryFlags;&lt;br /&gt;  WORD  LanguageId;&lt;br /&gt;  DWORD Version;&lt;br /&gt;  DWORD Characteristics;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;DataSize&lt;/code&gt; field indicates the size of the resource data following the header.  According to &lt;a href="http://msdn.microsoft.com/en-us/library/ms648027(v=VS.85).aspx"&gt;"RESOURCEHEADER Structure"&lt;/a&gt; The TYPE and NAME fields could be stored in two different ways. It could be a zero terminated unicode string or a &lt;code&gt;int16&lt;/code&gt; identifier prefixed by a &lt;span style="font-style:italic;"&gt;-1&lt;/span&gt; &lt;code&gt;int16&lt;/code&gt; value.  Also after the type/name and entries and after the data of each resource we need to read extra padding bytes that align the entry to  &lt;span style="font-weight:bold;"&gt;DWORD&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Using the code defined for &lt;span style="font-weight:bold;"&gt;reading &lt;/span&gt;binary files the &lt;code&gt;RESOURCEHEADER&lt;/code&gt; structure could be specified as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; ResourceId =&lt;br /&gt;     | Numeric &lt;span class="srckeyw"&gt;of&lt;/span&gt; &lt;span class="srckeyw"&gt;int16&lt;/span&gt;&lt;br /&gt;     | Name &lt;span class="srckeyw"&gt;of&lt;/span&gt; &lt;span class="srckeyw"&gt;char&lt;/span&gt;[]&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let &lt;/span&gt;pBuilder = new BinParserBuilder()&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let &lt;/span&gt;resourceParser = pBuilder {&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; dataSize = RInt&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; headerSize = RInt&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; typePrefix = RShort   &lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; resourceType =&lt;br /&gt;            &lt;span class="srckeyw"&gt;if&lt;/span&gt; typePrefix = -1s &lt;span class="srckeyw"&gt;then&lt;/span&gt;&lt;br /&gt;                wrap(RShort, Numeric)&lt;br /&gt;            &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;                wrap(RZString,&lt;br /&gt;                     (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; data -&amp;gt; Name(Array.concat&lt;br /&gt;                                          [[|char(typePrefix)|];&lt;br /&gt;                                           data] )))&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; namePrefix = RShort   &lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; resourceName =&lt;br /&gt;            &lt;span class="srckeyw"&gt;if&lt;/span&gt; namePrefix = -1s &lt;span class="srckeyw"&gt;then&lt;/span&gt;&lt;br /&gt;                wrap(RShort, Numeric)&lt;br /&gt;            &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;                wrap(RZString,&lt;br /&gt;                     (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; data -&amp;gt; Name(Array.concat&lt;br /&gt;                                          [[|char(namePrefix)|];&lt;br /&gt;                                           data] )))&lt;br /&gt;     &lt;span class="srckeyw"&gt;let &lt;/span&gt;typeAndNameLength = sizeOfResourceId resourceType +&lt;br /&gt;                             sizeOfResourceId resourceName &lt;br /&gt;                             &lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; _ = RDWordAlignData(typeAndNameLength)&lt;br /&gt;     &lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; dataVersion = RInt&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; memoryFlags = RShort&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; languageId = RShort&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; version = RInt&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; characteristics = RInt&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; contents = RByteBlock(dataSize)&lt;br /&gt;&lt;br /&gt;     &lt;span class="srckeyw"&gt;let!&lt;/span&gt; _ = RDWordAlignData(dataSize)&lt;br /&gt;&lt;br /&gt;     &lt;span class="srckeyw"&gt;return&lt;/span&gt; (resourceName,resourceType,contents)&lt;br /&gt;   }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Using this code we can extract each entry of the resource file by writing the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; file = new FileStream(fileName, FileMode.Open)&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; binaryReader = new BinaryReader(file, System.Text.Encoding.Unicode)&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; resources = &lt;br /&gt;  &lt;span class="srckeyw"&gt;seq&lt;/span&gt; {&lt;br /&gt;     &lt;span class="srckeyw"&gt;while&lt;/span&gt;(file.Position &amp;lt; file.Length) &lt;span class="srckeyw"&gt;do&lt;/span&gt;&lt;br /&gt;       &lt;span class="srckeyw"&gt;match&lt;/span&gt; (resourceParser.Function binaryReader) with&lt;br /&gt;       | Success (t,_) -&amp;gt; &lt;span class="srckeyw"&gt;yield&lt;/span&gt; (Some t)&lt;br /&gt;       | Failure _ -&amp;gt; printf "Error!"&lt;br /&gt;                      &lt;span class="srckeyw"&gt;yield&lt;/span&gt; None&lt;br /&gt;  } |&amp;gt;  List.ofSeq&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Extracting Icons&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Icons have two entries inside the resource files. The first entry has information about the image and the other contains the actual image data.&lt;br /&gt;&lt;br /&gt;The following function writes all the icons in the resource list:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;resources |&amp;gt;&lt;br /&gt;   filterMap (fun current -&amp;gt;&lt;br /&gt;                   cursorIconInfo current 14s getIconInfo "ico") |&amp;gt;&lt;br /&gt;   filterMap (fun (originalid, (_, i, planes, bitcount, bytes, iconId)) -&amp;gt; &lt;br /&gt;                  &lt;span class="srckeyw"&gt;match&lt;/span&gt; (List.find (isEntryWithId iconId) resources) &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;                  | Some(_, _, data) -&amp;gt;&lt;br /&gt;                         Some(originalid, i, planes, bitcount, data)&lt;br /&gt;                  | _ -&amp;gt; None) |&amp;gt;&lt;br /&gt;   Seq.iter (fun (name, (w, h, colorcount), planes, bitcount, contents) -&amp;gt; &lt;br /&gt;                  writeIcon(name, (w, h, colorcount),&lt;br /&gt;                            bitcount, planes, contents))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The information about the icon is extracted using &lt;code&gt;cursorIconInfo&lt;/code&gt; which works for the cursor and the icon entry:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; cursorIconInfo resourceInfo resourceType infoExtractFunction extension =&lt;br /&gt;     &lt;span class="srckeyw"&gt;match&lt;/span&gt; resourceInfo &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;     | Some(resName,Numeric(rType),data) when rType = resourceType  -&amp;gt; &lt;br /&gt;            &lt;span class="srckeyw"&gt;match&lt;/span&gt; resName,(infoExtractFunction data) &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;            | Numeric(id), Success(t,_) -&amp;gt;&lt;br /&gt;                       Some(sprintf &lt;span class="srctext"&gt;"%s%O.%s"&lt;/span&gt; extension  id extension,t)&lt;br /&gt;            | Name(nameChars), Success(t,_) -&amp;gt; &lt;br /&gt;                       Some(&lt;span class="srckeyw"&gt;new&lt;/span&gt; String(nameChars) + "." + extension,t)&lt;br /&gt;            | _,_ -&amp;gt;&lt;br /&gt;                 printf "WARNING: Skipping resource: %O\n" id&lt;br /&gt;                 None&lt;br /&gt;     | _ -&amp;gt; None&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;With the data returned from this function we can get the id number of the resource file entry that contains the image data (iconCursorId). We can then get the resource entry of the icon and extract the image info from there using the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let &lt;/span&gt;iconResEntry = pBuilder {&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; reserved = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; restype  = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; rescount = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; iconWidth = RByte&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; iconHeight = RByte&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; colorCount = RByte&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; reserved = RByte&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; planes = RShort &lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; bitCount = RShort &lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; bytesInRes = RInt&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; iconCursorId = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;return&lt;/span&gt; (reserved, restype, rescount),&lt;br /&gt;           (iconWidth, iconHeight, colorCount),&lt;br /&gt;           planes, bitCount, bytesInRes, iconCursorId&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; getIconInfo (data : byte array) =&lt;br /&gt;  use str = new MemoryStream(data)&lt;br /&gt;  use bReader = new BinaryReader(str)&lt;br /&gt;  iconResEntry.Function bReader&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Image information stored in the payload section of the resource is almost the same as a .ICO file . So in order to extract the icon what we need to do is to generate part of the header of a valid &lt;a href="http://en.wikipedia.org/wiki/ICO_(file_format)"&gt;ICO file&lt;/a&gt;. The following function does that:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; writeIcon(fileName,&lt;br /&gt;              (width : byte, height : byte, bitcount : byte),&lt;br /&gt;              bpp : int16,&lt;br /&gt;              planes : int16,&lt;br /&gt;              contents : byte array) =&lt;br /&gt;    &lt;span class="srckeyw"&gt;use&lt;/span&gt; writer = &lt;span class="srckeyw"&gt;new&lt;/span&gt; FileStream(fileName, FileMode.Create)&lt;br /&gt;    &lt;span class="srckeyw"&gt;use&lt;/span&gt; bwriter = &lt;span class="srckeyw"&gt;new&lt;/span&gt; BinaryWriter(writer)&lt;br /&gt;    bwriter.Write(0s)&lt;br /&gt;    bwriter.Write(1s)&lt;br /&gt;    bwriter.Write(1s)&lt;br /&gt;    bwriter.Write(byte(width))&lt;br /&gt;    bwriter.Write(byte(height))&lt;br /&gt;    bwriter.Write(byte(bitcount))&lt;br /&gt;    bwriter.Write(byte(0))&lt;br /&gt;    bwriter.Write(planes) &lt;br /&gt;    bwriter.Write(bpp)&lt;br /&gt;    bwriter.Write(contents.Length)&lt;br /&gt;    bwriter.Write(int32(writer.Position) + 4)&lt;br /&gt;    bwriter.Write(contents)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Extracting Cursors&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The process of writing the cursors is almost the same as the process with icons. The following code filters the cursor resources and extract them:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;resources |&amp;gt;&lt;br /&gt;   filterMap (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; current -&amp;gt; cursorIconInfo current 12s getCursorInfo "cur") |&amp;gt;&lt;br /&gt;   filterMap (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; (name, (_, (w, h), _, bitCount, _, cursorId)) -&amp;gt; &lt;br /&gt;                   &lt;span class="srckeyw"&gt;match&lt;/span&gt; List.find (isEntryWithId cursorId) resources &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;                   | Some(_, _, theData) -&amp;gt; Some(name, bitCount, theData)&lt;br /&gt;                   | _ -&amp;gt; None)  |&amp;gt;&lt;br /&gt;   Seq.iter ( &lt;span class="srckeyw"&gt;fun&lt;/span&gt; (name, bitcount, contents) -&amp;gt;&lt;br /&gt;                 writeCursor(name, byte(bitcount),contents))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;getCursorInfo&lt;/code&gt; function extracts data from the cursor specific entry:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let &lt;/span&gt;cursorResEntry = pBuilder {&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; reserved = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; restype  = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; rescount = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; cursorWidth = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; cursorHeight = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; planes = RShort &lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; bitCount = RShort &lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; bytesInRes = RInt&lt;br /&gt;    &lt;span class="srckeyw"&gt;let!&lt;/span&gt; iconCursorId = RShort&lt;br /&gt;    &lt;span class="srckeyw"&gt;return&lt;/span&gt; (reserved, restype, rescount),&lt;br /&gt;           (cursorWidth, cursorHeight),&lt;br /&gt;           planes, bitCount, bytesInRes, iconCursorId&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let &lt;/span&gt;getCursorInfo (data : byte array) =&lt;br /&gt;  &lt;span class="srckeyw"&gt;use&lt;/span&gt; str = &lt;span class="srckeyw"&gt;new&lt;/span&gt; MemoryStream(data)&lt;br /&gt;  &lt;span class="srckeyw"&gt;use&lt;/span&gt; bReader = &lt;span class="srckeyw"&gt;new&lt;/span&gt; BinaryReader(str, System.Text.Encoding.Unicode)&lt;br /&gt;  cursorResEntry.Function bReader&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As with the icon entry, the cursor entry has the data in almost the same format as a &lt;a href="http://en.wikipedia.org/wiki/ICO_(file_format)"&gt;.CUR file&lt;/a&gt; so we need to generate a valid header for this file.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; writeCursor(fileName, bitcount : byte, contents : byte array) =&lt;br /&gt;    use writer = new FileStream(fileName, FileMode.Create)&lt;br /&gt;    use bwriter = new BinaryWriter(writer)&lt;br /&gt;    bwriter.Write(0s)&lt;br /&gt;    bwriter.Write(2s)&lt;br /&gt;    bwriter.Write(1s)&lt;br /&gt;    &lt;span class="srccomment"&gt;//Assume 32x32&lt;/span&gt;&lt;br /&gt;    bwriter.Write(byte(32))&lt;br /&gt;    bwriter.Write(byte(32))&lt;br /&gt;    bwriter.Write(bitcount)&lt;br /&gt;    bwriter.Write(byte(0))&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; v1 = &lt;span class="srckeyw"&gt;uint16&lt;/span&gt;(contents.[0]) ||| (&lt;span class="srckeyw"&gt;uint16&lt;/span&gt;(contents.[1] &amp;lt;&amp;lt;&amp;lt; 16))&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; v2 = &lt;span class="srckeyw"&gt;uint16&lt;/span&gt;(contents.[2]) ||| (&lt;span class="srckeyw"&gt;uint16&lt;/span&gt;(contents.[3] &amp;lt;&amp;lt;&amp;lt; 16))&lt;br /&gt;    bwriter.Write(v1) &lt;br /&gt;    bwriter.Write(v2)&lt;br /&gt;    bwriter.Write(contents.Length - 4)&lt;br /&gt;    bwriter.Write(int32(writer.Position) + 4)&lt;br /&gt;    bwriter.Write(contents,4,contents.Length - 4 )&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you can see from the code I had to assume that the resolution of the cursor is 32x32 . This is because the data didn't seem to have the correct information as specified in &lt;a href="http://msdn.microsoft.com/en-us/library/ms648011(v=VS.85).aspx"&gt;"CURSORDIR Structure"&lt;/a&gt; .&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Extracting Bitmaps&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Finally writing bitmap file entries is very easy. The bitmap data is stored using the &lt;a href="http://en.wikipedia.org/wiki/BMP_file_format#Bitmap_Information_.28DIB_header.29"&gt;DIB format&lt;/a&gt; which is part of the &lt;a href="http://en.wikipedia.org/wiki/BMP_file_format"&gt;BMP file format&lt;/a&gt;. The following fragment shows how we extract these resources.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;resources |&amp;gt; &lt;br /&gt;   filterMap (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; res -&amp;gt; &lt;span class="srckeyw"&gt;match&lt;/span&gt; res &lt;span class="srckeyw"&gt;with&lt;/span&gt; &lt;br /&gt;                         | Some(Numeric id, Numeric 2s, data) -&amp;gt; &lt;br /&gt;                                 Some(sprintf "bmp%O.bmp" id, data) &lt;br /&gt;                         | Some(Name nameChars, Numeric 2s, data) -&amp;gt; &lt;br /&gt;                                 Some(new String(nameChars)+".bmp", data) &lt;br /&gt;                         | _ -&amp;gt; None) |&amp;gt; &lt;br /&gt;   Seq.iter (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; (name, data) -&amp;gt; writeBmp(name, data))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As with the other elements, the &lt;code&gt;writeBmp&lt;/code&gt; function writes the appropriate header according to the &lt;a href="http://en.wikipedia.org/wiki/BMP_file_format"&gt;BMP file format&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; writeBmp(name,data:byte array) =&lt;br /&gt;    &lt;span class="srckeyw"&gt;use&lt;/span&gt; writer = &lt;span class="srckeyw"&gt;new&lt;/span&gt; FileStream(name,FileMode.Create)&lt;br /&gt;    &lt;span class="srckeyw"&gt;use&lt;/span&gt; bwriter = &lt;span class="srckeyw"&gt;new&lt;/span&gt; BinaryWriter(writer)&lt;br /&gt;    bwriter.Write(0x42uy)&lt;br /&gt;    bwriter.Write(0x4Duy)&lt;br /&gt;    bwriter.Write(14  + data.Length)&lt;br /&gt;    bwriter.Write(5s)&lt;br /&gt;    bwriter.Write(5s)&lt;br /&gt;    &lt;span class="srccomment"&gt;// According to the DIB header the image color depth&lt;/span&gt;&lt;br /&gt;    &lt;span class="srccomment"&gt;// is located ad offset 14&lt;/span&gt;&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; paletteSize =&lt;br /&gt;         &lt;span class="srckeyw"&gt;if&lt;/span&gt; data.[14] &amp;lt; 24uy &lt;span class="srckeyw"&gt;then&lt;/span&gt;&lt;br /&gt;            int((2.0 ** float(data.[14])) * 4.0)&lt;br /&gt;         &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;            0         &lt;br /&gt;    bwriter.Write(14 + 40 + paletteSize)&lt;br /&gt;    bwriter.Write(data)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://github.com/ldfallas/fsharpexperiments/tree/master/Win32ResourceExtractor/"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-7809875603887461932?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/7809875603887461932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=7809875603887461932' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7809875603887461932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7809875603887461932'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/08/extracting-elements-from-win32-resource.html' title='Extracting elements from Win32 resource files with F#'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-5289396268186829857</id><published>2010-06-19T07:39:00.000-06:00</published><updated>2010-06-19T07:41:00.496-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>Generating XML with Newspeak</title><content type='html'>While experimenting with &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak&lt;/a&gt; I wrote a small utility class for generating basic XML documents. &lt;br /&gt;&lt;br /&gt;An example of its use looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;w:: getTestingWriter: output .&lt;br /&gt;w element: &lt;span class="srctext"&gt;'foo'&lt;/span&gt; &lt;br /&gt;   attributes: { {&lt;span class="srctext"&gt;'id'&lt;/span&gt;. &lt;span class="srctext"&gt;'goo'&lt;/span&gt;.} }&lt;br /&gt;   with: [&lt;br /&gt;    w element: &lt;span class="srctext"&gt;'foo1'&lt;/span&gt;.&lt;br /&gt;    w element: &lt;span class="srctext"&gt;'foo2'&lt;/span&gt;.&lt;br /&gt;    w element: &lt;span class="srctext"&gt;'foo3'&lt;/span&gt;&lt;br /&gt;        with: [&lt;br /&gt;        w element: &lt;span class="srctext"&gt;'foo4'&lt;/span&gt;&lt;br /&gt;            with: [&lt;br /&gt;              w text: &lt;span class="srctext"&gt;'Hello'&lt;/span&gt;.&lt;br /&gt;           ].&lt;br /&gt;        w cdata: &lt;span class="srctext"&gt;'&lt;loo&gt;'&lt;/span&gt;.&lt;br /&gt;        ].&lt;br /&gt;   ].&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This generates:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;foo id="goo"&amp;gt;&amp;lt;foo1 /&amp;gt;&amp;lt;foo2 /&amp;gt;&amp;lt;foo3&amp;gt;&amp;lt;foo4&amp;gt;Hello&amp;lt;/foo4&amp;gt;&amp;lt;![CDATA[&amp;lt;loo&amp;gt;]]&amp;gt;&amp;lt;/foo3&amp;gt;&amp;lt;/foo&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The code for generating XML this way is based on a &lt;a href="http://langexplr.blogspot.com/2009/02/writing-xml-with-ironpython-xmlwriter.html"&gt;previous experiment&lt;/a&gt; of using Python's &lt;a href="http://www.python.org/dev/peps/pep-0343/"&gt;'with' statement&lt;/a&gt; to wrap the .NET's &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.aspx"&gt;System.Xml.XmlWriter&lt;/a&gt; class to generate XML.&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://github.com/ldfallas/newspeakexperiments/tree/master/xmlparser/"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-5289396268186829857?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/5289396268186829857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=5289396268186829857' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/5289396268186829857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/5289396268186829857'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/06/generating-xml-with-newspeak.html' title='Generating XML with Newspeak'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-433956949570072142</id><published>2010-06-13T08:49:00.004-06:00</published><updated>2010-06-13T08:53:13.192-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>Parsing XML documents with namespaces in Newspeak</title><content type='html'>The &lt;a href="http://langexplr.blogspot.com/2010/05/simple-xml-grammar-in-newspeak.html"&gt;previous post&lt;/a&gt; showed a basic grammar for XML written using &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak&lt;/a&gt; parsing combinators. Although Newspeak already includes XML support, it is a great exercise to explore another interesting parts of the language.  &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The grammar&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The grammar defined in the previous post looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; XmlGrammar = ExecutableGrammar(&lt;br /&gt;&lt;span class="srccomment"&gt;"Xml 1.0 grammar with namespaces according to http://www.w3.org/TR/REC-xml/ "&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   openAB = char: &lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt;.&lt;br /&gt;   closeAB = char: &lt;span class="srctext"&gt;$&amp;gt;&lt;/span&gt;.&lt;br /&gt;   amp = char: &lt;span class="srctext"&gt;$&amp;&lt;/span&gt;.&lt;br /&gt;   semicolon = char: &lt;span class="srctext"&gt;$;&lt;/span&gt; .&lt;br /&gt;   slash = char: &lt;span class="srctext"&gt;$/&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   topenAB = tokenFromChar: &lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt;.&lt;br /&gt;   tcloseAB = tokenFromChar: &lt;span class="srctext"&gt;$&amp;gt;&lt;/span&gt;.&lt;br /&gt;   tslash = tokenFromChar: &lt;span class="srctext"&gt;$/&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;   comment = openAB , (char: &lt;span class="srctext"&gt;$-&lt;/span&gt;),(char: &lt;span class="srctext"&gt;$-&lt;/span&gt;), &lt;br /&gt;                        ((charExceptFor: &lt;span class="srctext"&gt;$-&lt;/span&gt;) | ((char: &lt;span class="srctext"&gt;$-&lt;/span&gt;), (charExceptFor: &lt;span class="srctext"&gt;$-&lt;/span&gt;))) plus,&lt;br /&gt;                       (char: &lt;span class="srctext"&gt;$-&lt;/span&gt;),(char: &lt;span class="srctext"&gt;$-&lt;/span&gt;),closeAB .&lt;br /&gt;&lt;br /&gt;   letter = (charBetween: &lt;span class="srctext"&gt;$a&lt;/span&gt; and: &lt;span class="srctext"&gt;$z&lt;/span&gt;) | (charBetween: &lt;span class="srctext"&gt;$A&lt;/span&gt; and: &lt;span class="srctext"&gt;$Z&lt;/span&gt;).&lt;br /&gt;   digit = charBetween: &lt;span class="srctext"&gt;$0&lt;/span&gt; and: &lt;span class="srctext"&gt;$9&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;   colon = char: &lt;span class="srctext"&gt;$:&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;   quote = (char:&lt;span class="srctext"&gt;$'&lt;/span&gt;) .&lt;br /&gt;   dquote = (char:&lt;span class="srctext"&gt;$"&lt;/span&gt;) .   &lt;br /&gt;&lt;br /&gt;   eq = tokenFromChar: &lt;span class="srctext"&gt;$=&lt;/span&gt; .&lt;br /&gt; &lt;br /&gt;   VersionNum = (char:&lt;span class="srctext"&gt;$1&lt;/span&gt;), (char: &lt;span class="srctext"&gt;$.&lt;/span&gt;) , (charBetween: &lt;span class="srctext"&gt;$0&lt;/span&gt; and: &lt;span class="srctext"&gt;$9&lt;/span&gt;) plus.&lt;br /&gt;&lt;br /&gt;   VersionInfo = (tokenFromSymbol: #version), eq, ((quote, VersionNum,quote) | (dquote, VersionNum, dquote )).&lt;br /&gt;&lt;br /&gt;   EncName = letter, (letter | digit) star.&lt;br /&gt;&lt;br /&gt;   EncodingDecl = (tokenFromSymbol: #enconding) , eq , ((quote, EncName ,quote) | (dquote , EncName , dquote  )).&lt;br /&gt;&lt;br /&gt;   yesNo = (tokenFromSymbol: #yes) | (tokenFromSymbol: #no).&lt;br /&gt;&lt;br /&gt;   SDDecl = (tokenFromSymbol: #standalone), eq, ((quote, yesNo ,quote) | (dquote , yesNo , dquote  )).&lt;br /&gt;&lt;br /&gt;   XMLDecl = (char: &lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt;) , (char: &lt;span class="srctext"&gt;$?&lt;/span&gt;) ,(tokenFromSymbol: #xml), VersionInfo , EncodingDecl opt, SDDecl opt,&lt;br /&gt;                     (tokenFromChar: &lt;span class="srctext"&gt;$?&lt;/span&gt;), (char: &lt;span class="srctext"&gt;$&amp;gt;&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;   dprolog = XMLDecl.&lt;br /&gt; &lt;br /&gt;   NameStartChar = letter | (char: &lt;span class="srctext"&gt;$_&lt;/span&gt;) .&lt;br /&gt;&lt;br /&gt;   NameChar =  NameStartChar | (char: &lt;span class="srctext"&gt;$-&lt;/span&gt;) | (char: &lt;span class="srctext"&gt;$.&lt;/span&gt;) | digit.&lt;br /&gt;&lt;br /&gt;   Name = NameStartChar, NameChar star.&lt;br /&gt;&lt;br /&gt;   NameWithPrefix = Name, colon, Name.&lt;br /&gt;&lt;br /&gt;   QName = NameWithPrefix | Name.&lt;br /&gt;&lt;br /&gt;   TQName = tokenFor: QName.&lt;br /&gt;&lt;br /&gt;   EntityRef = amp, Name ,semicolon .&lt;br /&gt;&lt;br /&gt;   CharRef = amp, (char: &lt;span class="srctext"&gt;$#&lt;/span&gt;), (((char:&lt;span class="srctext"&gt;$x&lt;/span&gt;), (digit | letter) plus) | (digit plus)) ,semicolon .&lt;br /&gt;&lt;br /&gt;   Reference = EntityRef | CharRef.&lt;br /&gt;&lt;br /&gt;   AttributeContent1 = (charExceptForCharIn: {&lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt; . &lt;span class="srctext"&gt;$"&lt;/span&gt;. &lt;span class="srctext"&gt;$&amp;&lt;/span&gt;. }) | Reference.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;   AttributeValue = (dquote, AttributeContent1  star,dquote) | &lt;br /&gt;                              (quote, AttributeContent1 star,quote).&lt;br /&gt;&lt;br /&gt;   Attribute = TQName ,eq, AttributeValue.&lt;br /&gt;&lt;br /&gt;   EmptyElemTag = topenAB ,QName, Attribute star, tslash , closeAB .&lt;br /&gt;   STag = topenAB ,QName, Attribute star, tcloseAB .&lt;br /&gt;   ETag = topenAB ,slash,QName, tcloseAB .&lt;br /&gt;&lt;br /&gt;   CDStart = topenAB ,(char: &lt;span class="srctext"&gt;$!&lt;/span&gt;),(char:&lt;span class="srctext"&gt;$[&lt;/span&gt;),(tokenFromSymbol: #CDATA),(char:&lt;span class="srctext"&gt;$[&lt;/span&gt;).&lt;br /&gt;   CDEnd = (char: &lt;span class="srctext"&gt;$]&lt;/span&gt;),(char: &lt;span class="srctext"&gt;$]&lt;/span&gt;),(char: &lt;span class="srctext"&gt;$&amp;gt;&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;   CDSect = CDStart, (charExceptFor: &lt;span class="srctext"&gt;$]&lt;/span&gt;) star ,   CDEnd.&lt;br /&gt;&lt;br /&gt;   CharData  = tokenFor: ((charExceptForCharIn: {&lt;span class="srctext"&gt;$&amp;&lt;/span&gt;. &lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt;}) plus).&lt;br /&gt;&lt;br /&gt;   content = CharData opt, ((element | Reference | CDSect), CharData opt) star.&lt;br /&gt;&lt;br /&gt;   ComplexElement = STag, content , ETag.&lt;br /&gt;&lt;br /&gt;   element =  EmptyElemTag | ComplexElement  .&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;( &lt;br /&gt;  ... &lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;XML nodes&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The next step was to add support for the creation of data structures representing the XML document. A technique presented in the &lt;a href="http://bracha.org/executableGrammars.pdf"&gt;Executable Grammars[PDF]&lt;/a&gt; paper suggest creating a subclass of the grammar which adds the code for creating the XML node tree.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; XmlParserWithXmlNodes = XmlGrammar (&lt;br /&gt;"Basic XmlParser with XML node AST"&lt;br /&gt;|&lt;br /&gt;   &lt;br /&gt;   &lt;br /&gt;|)&lt;br /&gt;('as yet unclassified'&lt;br /&gt;Attribute = (&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; Attribute wrapper: [:name :eq :value | {name. value.}].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;AttributeValue = (&lt;br /&gt;   |flattenString|&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; AttributeValue &lt;br /&gt;               wrapper: [:q1 :chars :q2 | &lt;br /&gt;                              flattenString:: (chars collect: &lt;br /&gt;                                                 [:c | (c isString) &lt;br /&gt;                                                         ifTrue: [c at: 1] &lt;br /&gt;                                                         ifFalse: [c]]).&lt;br /&gt;                              String withAll:flattenString  ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;CDSect = (&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; CDSect wrapper: [:cs :data :ce | String withAll: data].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;CDStart= (&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; CDStart  wrapper: [:t :e :b1 :cdata :b2 | 'cdatastart'].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;CharData = (&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; CharData wrapper: [:chars | String withAll: (chars token ) ].&lt;br /&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;CharRef = (&lt;br /&gt;   |numberStr|&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; CharRef &lt;br /&gt;               wrapper: [:a1 :p :numberChars :sc | &lt;br /&gt;                         |base| &lt;br /&gt;                         numberStr:: ((numberChars at: 1) = $x) &lt;br /&gt;                                          ifTrue: [base:: 16.&lt;br /&gt;                                                   String withAll: (numberChars at: 2)]&lt;br /&gt;                                          ifFalse: [base:: 10.&lt;br /&gt;                                                    String withAll: numberChars].&lt;br /&gt;&lt;br /&gt;                           (Unicode value: (Number readFrom: numberStr base: base)) asString&lt;br /&gt;                       ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;ComplexElement = (&lt;br /&gt;   |tn attCollection|&lt;br /&gt;   tn:: XmlNodes new.&lt;br /&gt;   attCollection:: tn Attributes new.&lt;br /&gt;&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; ComplexElement &lt;br /&gt;                   wrapper: [:s :childNodes :e | &lt;br /&gt;                                 (e asString = s name asString) &lt;br /&gt;                                       ifFalse: [error: 'Open tag different from closing tag'].&lt;br /&gt;                                 s childNodes: childNodes.&lt;br /&gt;                                 s].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;ETag = (&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; ETag wrapper: [:o :s :name :c | name].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;EmptyElemTag = (&lt;br /&gt;&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; EmptyElemTag &lt;br /&gt;                     wrapper: [:oab :name :atts :s :cab | &lt;br /&gt;                               |tn attCollection|&lt;br /&gt;                               tn:: XmlNodes new.&lt;br /&gt;                               attCollection:: tn Attributes new.&lt;br /&gt;&lt;br /&gt;                               atts do: [:att | attCollection addAttributeWithQName: ((att at: 1) token) value: (att at:2)].&lt;br /&gt;                               tn Element name: name attributes: attCollection childNodes:{} ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;EntityRef = (&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; EntityRef &lt;br /&gt;                   wrapper: [:a :name :sc | &lt;br /&gt;                                 (entities  valueForName: ((name at: 1) at: 1)) asString ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;Name = (&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; Name  wrapper: [:startChar :rest | { { (startChar asString), (String withAll: rest) } } ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;NameWithPrefix = (&lt;br /&gt;   |tn|&lt;br /&gt;   tn:: XmlNodes new.&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; NameWithPrefix &lt;br /&gt;                 wrapper: [ :prefix :c  :name | &lt;br /&gt;                                   {{(prefix at: 1). (name at: 1).}} ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;QName = (&lt;br /&gt;      |tn|&lt;br /&gt;      tn:: XmlNodes new.&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; QName  wrapper: [ :data | ((data size) = 2) &lt;br /&gt;                                        ifTrue:[tn QualifiedName prefix: ((data at:1) at: 1) &lt;br /&gt;                                                                 localPart:((data at: 2) at:1)]&lt;br /&gt;                                        ifFalse:[tn QualifiedName prefix: nil localPart: (data at: 1)]]&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;STag = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; STag &lt;br /&gt;            wrapper: [:oab :name :atts :cab |                                        &lt;br /&gt;                         |tn attCollection|&lt;br /&gt;                         tn:: XmlNodes new.&lt;br /&gt;                         attCollection:: tn Attributes new.&lt;br /&gt;                         "Add attributes"&lt;br /&gt;                         atts do: [:att | attCollection addAttributeWithQName: ((att at: 1) token) &lt;br /&gt;                                                        value: (att at:2)].&lt;br /&gt;                         "Create elements"&lt;br /&gt;                         tn Element name: name attributes: attCollection childNodes:{} ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;VersionInfo = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; VersionInfo &lt;br /&gt;               wrapper: [:v :e :versionTextList | versionTextList at: 2].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;VersionNum = ( &lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; VersionNum  &lt;br /&gt;               wrapper: [:one :dot :num | &lt;br /&gt;                            Number &lt;br /&gt;                                readFrom: (String withAll: {one.dot},(String withAll: num))].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;XMLDecl = (&lt;br /&gt;   |tn|&lt;br /&gt;   tn:: XmlNodes new.&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; XMLDecl &lt;br /&gt;             wrapper: [:c1 :c2 :x :versionInfo :enc :sd :c3 :c4 | &lt;br /&gt;                           tn TAstXmlDecl version: versionInfo &lt;br /&gt;                                          encoding: enc&lt;br /&gt;                                          standalone: sd] .&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;content = (&lt;br /&gt;   |result|&lt;br /&gt;&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; content wrapper: [:chars :cseq |&lt;br /&gt;                   (chars = nil) &lt;br /&gt;                       ifTrue: [result:: {}] &lt;br /&gt;                       ifFalse: [result:: {chars}].&lt;br /&gt;                   cseq inject: result into: [:total :current  |  &lt;br /&gt;                               result::  addCompactingStrings: (current at: 1) to: result  .&lt;br /&gt;                               (current at: 2) ifNotNil: [:c | addCompactingStrings: c to: result   ].&lt;br /&gt;                               result ].&lt;br /&gt;         ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;XML Namespaces&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Support for XML namespace resolution was the next step. As described in the &lt;a href="http://www.w3.org/TR/REC-xml-names/"&gt;Namespaces in XML 1.0&lt;/a&gt; document, XML can have different namespaces for its elements. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;docs:letter docs:xmlns="http://www.foo.com/docs"&lt;br /&gt;             pic:xmlns="http://www.foo.com/docs/links"&amp;gt;&lt;br /&gt;   &amp;lt;docs:paragraph&amp;gt;some text1&amp;lt;/docs:paragraph&amp;gt; &lt;br /&gt;   &amp;lt;pic:pictureRef location="goo/moo/loo"/&amp;gt;&lt;br /&gt;   &amp;lt;docs:paragraph&amp;gt;some text2&amp;lt;/docs:paragraph&amp;gt; &lt;br /&gt;&amp;lt;/docs:letter&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this case the 'docs:xmlns' and 'pic:xmlns' attributes associates the 'docs' and 'pics' prefixes to the specified namespaces. So the namespace of the 'letter' element is 'http://www.foo.com/docs'.&lt;br /&gt;&lt;br /&gt;Also default namespaces could be specified, like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;letter xmlns="http://www.foo.com/docs"&amp;gt;&lt;br /&gt;             &lt;br /&gt;   &amp;lt;paragraph&amp;gt;some text1&amp;lt;/paragraph&amp;gt; &lt;br /&gt;   &amp;lt;pictureRef location="goo/moo/loo" &lt;br /&gt;               xmlns="http://www.foo.com/docs/links"  /&amp;gt;&lt;br /&gt;   &amp;lt;paragraph&amp;gt;some text2&amp;lt;/paragraph&amp;gt; &lt;br /&gt;&amp;lt;/letter&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The basic idea is that &lt;code&gt;xmlns&lt;/code&gt; attributes define an scope where a set of  prefix/namepace associations and a default namespace are valid. For each start tag a new scope with new declarations must be in context and each end tag must remove the last scope.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Extending the parsing context&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In order to do add this functionality, we need to be able to keep a stack with the scopes of namespace declarations that is modified each time we enter or exit from a element declaration. Fortunately, the parser combinator library includes a &lt;code&gt;ParserContext&lt;/code&gt; class which is used for keeping track parsing errors. &lt;br /&gt;&lt;br /&gt;One problem to use &lt;code&gt;ParserContext&lt;/code&gt; was that an instance of it is created inside the &lt;code&gt;CombinatorialParser parse:&lt;/code&gt; method which is part of the parsing library. This instance is configured in certain way to process parsing errors. So in order to create add a extended context we needed to somehow replace the &lt;code&gt;ParserContext&lt;/code&gt; class with a new implementation. &lt;br /&gt;&lt;br /&gt;Luckly, as described in the &lt;a href="http://bracha.org/newspeak-modules.pdf"&gt;Modules as Objects in Newspeak[PDF]&lt;/a&gt; paper in Newspeak you can override inner class definitions just like you override methods in any other OO language. This means that I can extend the parser library and since &lt;code&gt;ParserContext&lt;/code&gt; is defined as an inner class, override its definition to add my own parsing context. The definition of the extended parsing library looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; ParserLibraryWithXmlContext = parserLibraryClass usingLib: platform (&lt;br /&gt;&lt;span class="srccomment"&gt;"A parser library with overwritten parsing context for Xml namespace resolution"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   parserLibContext =  &lt;span class="srckeyw"&gt;super&lt;/span&gt; ParserContext .  &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; ParserContext =  parserLibContext(&lt;br /&gt;&lt;span class="srccomment"&gt;"An Xml parser context that keeps track of namespaces."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   protected prefixes = collections MutableArrayList new:  10.&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;('as yet unclassified'&lt;br /&gt;addPrefix: prefix for: namespace = (&lt;br /&gt;   |lastLevel|&lt;br /&gt;   lastLevel:: prefixes at: (prefixes size).&lt;br /&gt;   lastLevel at: prefix put: namespace.&lt;br /&gt;   &lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;namespaceFor: prefix = (&lt;br /&gt;   |levelIndex|&lt;br /&gt;&lt;br /&gt;   levelIndex:: prefixes findLast: [:lvl | (lvl includesKey: prefix) ].&lt;br /&gt;   ^(levelIndex &amp;gt; 0)&lt;br /&gt;            ifTrue: [(prefixes at: levelIndex) at: prefix]&lt;br /&gt;            ifFalse: [nil].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;popLevel = (&lt;br /&gt;   prefixes pop.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;pushLevel = (&lt;br /&gt;   prefixes push: (collections MutableHashedMap new).&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is pretty nice since it allowed us to &lt;span style="font-style:italic;"&gt;inject&lt;/span&gt; our own implementation of &lt;code&gt;ParsingContext&lt;/code&gt; (which extends the original!). An interesting thing to notice is the definition of the &lt;code&gt;parserLibContext&lt;/code&gt; which is bound to the base definition of the &lt;code&gt;ParserContext&lt;/code&gt; class which we need in order to inherit from it.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Using the extended context&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Now having added the new parsing context the next step is to add the code to manipulate the context. In order to do that, we need to add a some functionality to the &lt;code&gt;STag&lt;/code&gt;, &lt;code&gt;EmptyElement&lt;/code&gt; and &lt;code&gt;ETag&lt;/code&gt; productions of the grammar so we can push and pop namespace scopes for each element. In other to do this without modifying the existing functionality three wrappers were created for each of this productions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; ParserWithNamespaceForStartTag = CombinatorialParser (&lt;br /&gt;&lt;span class="srccomment"&gt;"A parser that takes care of modyfing the parsing context for a start tag"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;    innerparser&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;('as yet un&lt;span class="srckeyw"&gt;class&lt;/span&gt;ified'&lt;br /&gt;forParser: p = (&lt;br /&gt;    innerparser:: p.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;parse: input inContext: context ifError: blk = (&lt;br /&gt;    |result xmlnsAttributes elementName elementNamespace attName|&lt;br /&gt;    result:: innerparser parse: input inContext:context ifError:blk.&lt;br /&gt;    &lt;span class="srccomment"&gt;"First update the context with the newest prefix declarations"&lt;/span&gt;&lt;br /&gt;    context pushLevel.&lt;br /&gt;    xmlnsAttributes:: result attributes allAttributesWithLocalName: 'xmlns'.&lt;br /&gt;    xmlnsAttributes &lt;br /&gt;             do: [:aPair | context addPrefix: ((aPair at: 1) prefix)&lt;br /&gt;                                            for: (aPair at: 2)].&lt;br /&gt;    &lt;span class="srccomment"&gt;"Update the element"&lt;/span&gt;&lt;br /&gt;    elementName:: result name.&lt;br /&gt;    elementNamespace:: context namespaceFor: elementName prefix.&lt;br /&gt;    elementName namespace: elementNamespace.&lt;br /&gt;&lt;br /&gt;    &lt;span class="srccomment"&gt;"Update the attributes"&lt;/span&gt;&lt;br /&gt;    result attributes &lt;br /&gt;             do: [:aPair | &lt;br /&gt;                     attName:: aPair at: 1.&lt;br /&gt;                     attName namespace: &lt;br /&gt;                              (context namespaceFor: attName prefix)&lt;br /&gt;                  ].&lt;br /&gt;&lt;br /&gt;    ^result.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; ParserWithNamespaceForStartEndTag =ParserWithNamespaceForStartTag(&lt;br /&gt;&lt;span class="srccomment"&gt;"Parser that takes care of modifying the parsing context for namespace declarations for self closing tags."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;('as yet unclassified'&lt;br /&gt;parse: input inContext: context ifError: blk = (&lt;br /&gt;    |result|&lt;br /&gt;    result:: super parse: input inContext: context ifError: blk.&lt;br /&gt;    context popLevel.&lt;br /&gt;    ^result&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; ParserWithNamespaceForEndTag = CombinatorialParser (&lt;br /&gt;"A parser that takes care of modyfing the parsing context for a end tag"&lt;br /&gt;|&lt;br /&gt;    protected innerParser = nil.&lt;br /&gt;    &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;('as yet unclassified'&lt;br /&gt;forParser: parser = (&lt;br /&gt;    innerParser:: parser.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;parse: input inContext: context ifError: blk = (&lt;br /&gt;    |result|&lt;br /&gt;    result:: innerParser parse: input inContext: context ifError: blk.&lt;br /&gt;    context popLevel.&lt;br /&gt;    ^result&lt;br /&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As shown here the start tag parser &lt;span style="font-style:italic;"&gt;pushes&lt;/span&gt; a new scope with the new namespace declarations, while the end tag parser &lt;span style="font-style:italic;"&gt;pops&lt;/span&gt; a scope.&lt;br /&gt;&lt;br /&gt;Now to add this wrappers I created a new subclass of the parser with nodes to add this functionality.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; XmlParserWithNodesAndNamespaces = XmlParserWithXmlNodes (&lt;br /&gt;&lt;span class="srccomment"&gt;"An XML Parser that creates a node tree and that resolves the namespaces."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;        &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;('as yet unclassified'&lt;br /&gt;ETag  = (&lt;br /&gt;    |newWrappingParser|&lt;br /&gt;    newWrappingParser:: ParserWithNamespaceForEndTag new.&lt;br /&gt;    newWrappingParser forParser: (&lt;span class="srckeyw"&gt;super&lt;/span&gt; ETag).&lt;br /&gt;    ^newWrappingParser&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;EmptyElemTag = (&lt;br /&gt;    |newWrappingParser|&lt;br /&gt;    newWrappingParser:: ParserWithNamespaceForStartEndTag new.&lt;br /&gt;    newWrappingParser forParser: (&lt;span class="srckeyw"&gt;super&lt;/span&gt; EmptyElemTag).&lt;br /&gt;    ^newWrappingParser&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;STag = (&lt;br /&gt;    |tn attCollection newWrappingParser|&lt;br /&gt;    newWrappingParser:: ParserWithNamespaceForStartTag new.&lt;br /&gt;    newWrappingParser forParser: (&lt;span class="srckeyw"&gt;super&lt;/span&gt; STag).&lt;br /&gt;    ^newWrappingParser&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Code organization&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The code for this experiment is organized as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt;  XmlTools withParserLibClass: parserLibraryClass usingLib: platform = &lt;br /&gt;(&lt;br /&gt;...&lt;br /&gt;) (&lt;br /&gt;   &lt;span class="srckeyw"&gt;class&lt;/span&gt; XmlParsing withParsingLib: parserLibrary = (&lt;br /&gt;   ...&lt;br /&gt;   ) &lt;br /&gt;   (&lt;br /&gt;       &lt;span class="srckeyw"&gt;class&lt;/span&gt; XmlGrammar = ExecutableGrammar  &lt;br /&gt;           ( ...) ( ... )&lt;br /&gt;       &lt;span class="srckeyw"&gt;class&lt;/span&gt; XmlParserWithXmlNodes = XmlGrammar&lt;br /&gt;           ( ... ) ( ... )&lt;br /&gt;       &lt;span class="srckeyw"&gt;class&lt;/span&gt; XmlParserWithNodesAndNamespaces = XmlParserWithXmlNodes &lt;br /&gt;           ( ... ) ( ... )&lt;br /&gt;       ... &lt;br /&gt;   )&lt;br /&gt;&lt;br /&gt;   basicParser = (&lt;br /&gt;       |parsingLib xmlparsing|&lt;br /&gt;       parsingLib:: parserLibraryClass usingLib: platform.&lt;br /&gt;       xmlparsing:: XmlParsing withParsingLib: parsingLib.&lt;br /&gt;       ^xmlparsing XmlParserWithXmlNodes new.&lt;br /&gt;   )&lt;br /&gt;&lt;br /&gt;   parserWithNamespaceSupport = (&lt;br /&gt;       |parsingLib xmlparsing|&lt;br /&gt;       parsingLib:: ParserLibraryWithXmlContext new.&lt;br /&gt;       xmlparsing:: XmlParsing withParsingLib: parsingLib.&lt;br /&gt;       ^xmlparsing XmlParserWithNodesAndNamespaces new.&lt;br /&gt;   )&lt;br /&gt;   ...&lt;br /&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here the &lt;code&gt;XmlTools&lt;/code&gt; class definition will represent a &lt;span style="font-style:italic;"&gt;module&lt;/span&gt; for XML utilities. Its inner definitions include the XmlParsing inner class which defines the grammar along other parsing utilities. The &lt;code&gt;basicParser&lt;/code&gt; &lt;code&gt;parserWithNamespaceSupport&lt;/code&gt; show an example of how the parser is created.&lt;br /&gt;&lt;br /&gt;The following methods show how the &lt;code&gt;XmlTools&lt;/code&gt; class is used to create a concrete parser for a basic XML document:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;getTestingNsParser = (&lt;br /&gt;    |platform|&lt;br /&gt;    platform:: Platform new.&lt;br /&gt;    ^(XmlTools &lt;br /&gt;            withParserLibClass: BlocklessCombinatorialParsing  &lt;br /&gt;            usingLib: platform) parserWithNamespaceSupport.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;testElementWithOneChildWithNamespaces = (&lt;br /&gt;    |parser r ctxt|&lt;br /&gt;    parser:: xmlNsParserWrapper: (getTestingNsParser element) .&lt;br /&gt;    r:: parser parse: (streamFromString: &lt;span class="srctext"&gt;'&lt;myElement xmlns="http://foo"&gt;&lt;childElement1/&gt;&lt;/myElement&gt;'&lt;/span&gt;) .&lt;br /&gt;                     &lt;br /&gt;    assert:[r childNodes size = 1].&lt;br /&gt;    assert:[r name asString = &lt;span class="srctext"&gt;'myElement'&lt;/span&gt;].&lt;br /&gt;    assert:[r name namespace = &lt;span class="srctext"&gt;'http://foo'&lt;/span&gt;].&lt;br /&gt;    assert:[((r childNodes at: 1) name asString) = &lt;span class="srctext"&gt;'childElement1'&lt;/span&gt;].&lt;br /&gt;    assert:[((r childNodes at: 1) name namespace) = &lt;span class="srctext"&gt;'http://foo'&lt;/span&gt;].&lt;br /&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Final words&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The nicest think to notice is that the original class containing the grammar for XML was not modified in order to introduce this feature. In fact the parser with XML nodes without namespaces is also available . Also I really liked the way the &lt;code&gt;ParserContext&lt;/code&gt; class was replaced which automatically allowed me to add this new functionality.&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://github.com/ldfallas/newspeakexperiments/tree/master/xmlparser/"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-433956949570072142?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/433956949570072142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=433956949570072142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/433956949570072142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/433956949570072142'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/06/parsing-xml-documents-with-namespaces.html' title='Parsing XML documents with namespaces in Newspeak'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-7248248151129587319</id><published>2010-05-24T05:29:00.005-06:00</published><updated>2010-05-24T06:22:16.106-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>A simple XML Grammar in Newspeak</title><content type='html'>Recently I've been doing some experiments for parsing XML in using &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak&lt;/a&gt; parser combinators.&lt;br /&gt;&lt;br /&gt;Here's the grammar:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class XmlGrammar = ExecutableGrammar(&lt;br /&gt;&lt;span class="srctext"&gt;"Xml 1.0 grammar with namespaces"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   openAB = char: &lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt;.&lt;br /&gt;   closeAB = char: &lt;span class="srctext"&gt;$&amp;gt;&lt;/span&gt;.&lt;br /&gt;   amp = char: &lt;span class="srctext"&gt;$&amp;amp;&lt;/span&gt;.&lt;br /&gt;   semicolon = char: &lt;span class="srctext"&gt;$;&lt;/span&gt; .&lt;br /&gt;   slash = char: &lt;span class="srctext"&gt;$/&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   topenAB = tokenFromChar: &lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt;.&lt;br /&gt;   tcloseAB = tokenFromChar: &lt;span class="srctext"&gt;$&amp;gt;&lt;/span&gt;.&lt;br /&gt;   tslash = tokenFromChar: &lt;span class="srctext"&gt;$/&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;   comment = openAB , (char: &lt;span class="srctext"&gt;$-&lt;/span&gt;),(char: &lt;span class="srctext"&gt;$-&lt;/span&gt;), &lt;br /&gt;                        ((charExceptFor: &lt;span class="srctext"&gt;$-&lt;/span&gt;) | ((char: &lt;span class="srctext"&gt;$-&lt;/span&gt;), (charExceptFor: &lt;span class="srctext"&gt;$-&lt;/span&gt;))) plus,&lt;br /&gt;                       (char: &lt;span class="srctext"&gt;$-&lt;/span&gt;),(char: &lt;span class="srctext"&gt;$-&lt;/span&gt;),closeAB .&lt;br /&gt;&lt;br /&gt;   letter = (charBetween: &lt;span class="srctext"&gt;$a&lt;/span&gt; and: &lt;span class="srctext"&gt;$z&lt;/span&gt;) | (charBetween: &lt;span class="srctext"&gt;$A&lt;/span&gt; and: &lt;span class="srctext"&gt;$Z&lt;/span&gt;).&lt;br /&gt;   digit = charBetween: &lt;span class="srctext"&gt;$0&lt;/span&gt; and: &lt;span class="srctext"&gt;$9&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;   colon = char: &lt;span class="srctext"&gt;$:&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;   quote = (char:&lt;span class="srctext"&gt;$'&lt;/span&gt;) .&lt;br /&gt;   dquote = (char:&lt;span class="srctext"&gt;$"&lt;/span&gt;) .   &lt;br /&gt;&lt;br /&gt;   eq = tokenFromChar: &lt;span class="srctext"&gt;$=&lt;/span&gt; .&lt;br /&gt; &lt;br /&gt;   VersionNum = (char:&lt;span class="srctext"&gt;$1&lt;/span&gt;), (char: &lt;span class="srctext"&gt;$.&lt;/span&gt;) , (charBetween: &lt;span class="srctext"&gt;$0&lt;/span&gt; and: &lt;span class="srctext"&gt;$9&lt;/span&gt;) plus.&lt;br /&gt;&lt;br /&gt;   VersionInfo = (tokenFromSymbol: #version), eq, ((quote, VersionNum,quote) | (dquote, VersionNum, dquote )).&lt;br /&gt;&lt;br /&gt;   EncName = letter, (letter | digit) star.&lt;br /&gt;&lt;br /&gt;   EncodingDecl = (tokenFromSymbol: #enconding) , eq , ((quote, EncName ,quote) | (dquote , EncName , dquote  )).&lt;br /&gt;&lt;br /&gt;   yesNo = (tokenFromSymbol: #yes) | (tokenFromSymbol: #no).&lt;br /&gt;&lt;br /&gt;   SDDecl = (tokenFromSymbol: #standalone), eq, ((quote, yesNo ,quote) | (dquote , yesNo , dquote  )).&lt;br /&gt;&lt;br /&gt;   XMLDecl = (char: &lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt;) , (char: &lt;span class="srctext"&gt;$?&lt;/span&gt;) ,(tokenFromSymbol: #xml), VersionInfo , EncodingDecl opt, SDDecl opt,&lt;br /&gt;                     (tokenFromChar: &lt;span class="srctext"&gt;$?&lt;/span&gt;), (char: &lt;span class="srctext"&gt;$&amp;gt;&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;   dprolog = XMLDecl.&lt;br /&gt; &lt;br /&gt;   NameStartChar = letter | (char: &lt;span class="srctext"&gt;$_&lt;/span&gt;) .&lt;br /&gt;&lt;br /&gt;   NameChar =  NameStartChar | (char: &lt;span class="srctext"&gt;$-&lt;/span&gt;) | (char: &lt;span class="srctext"&gt;$.&lt;/span&gt;) | digit.&lt;br /&gt;&lt;br /&gt;   Name = NameStartChar, NameChar star.&lt;br /&gt;&lt;br /&gt;   QName = (Name, colon, Name)| Name.&lt;br /&gt;&lt;br /&gt;   TQName = tokenFor: QName.&lt;br /&gt;&lt;br /&gt;   EntityRef = amp, Name ,semicolon .&lt;br /&gt;&lt;br /&gt;   CharRef = amp, (char: &lt;span class="srctext"&gt;$#&lt;/span&gt;), (((char:&lt;span class="srctext"&gt;$x&lt;/span&gt;), (digit | letter) plus) | (digit plus)) ,semicolon .&lt;br /&gt;&lt;br /&gt;   Reference = EntityRef | CharRef.&lt;br /&gt;&lt;br /&gt;   AttributeContent1 = (charExceptForCharIn: {&lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt; . &lt;span class="srctext"&gt;$"&lt;/span&gt;. &lt;span class="srctext"&gt;$&amp;amp;&lt;/span&gt;. }) | Reference.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;   AttributeValue = (dquote, AttributeContent1  star,dquote) | &lt;br /&gt;                              (quote, AttributeContent1 star,quote).&lt;br /&gt;&lt;br /&gt;   Attribute = TQName ,eq, AttributeValue.&lt;br /&gt;&lt;br /&gt;   EmptyElemTag = topenAB ,QName, Attribute star, tslash , closeAB .&lt;br /&gt;   STag = topenAB ,QName, Attribute star, tcloseAB .&lt;br /&gt;   ETag = topenAB ,slash,QName, closeAB .&lt;br /&gt;&lt;br /&gt;   CDStart = topenAB ,(char: &lt;span class="srctext"&gt;$!&lt;/span&gt;),(char:&lt;span class="srctext"&gt;$[&lt;/span&gt;),(tokenFromSymbol: #CDATA),(char:&lt;span class="srctext"&gt;$[&lt;/span&gt;).&lt;br /&gt;   CDEnd = (char: &lt;span class="srctext"&gt;$]&lt;/span&gt;),(char: &lt;span class="srctext"&gt;$]&lt;/span&gt;),(char: &lt;span class="srctext"&gt;$&amp;gt;&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;   CDSect = CDStart, (charExceptFor: &lt;span class="srctext"&gt;$]&lt;/span&gt;) star ,   CDEnd.&lt;br /&gt;&lt;br /&gt;   CharData  = tokenFor: ((charExceptForCharIn: {&lt;span class="srctext"&gt;$&amp;amp;&lt;/span&gt;. &lt;span class="srctext"&gt;$&amp;lt;&lt;/span&gt;}) plus).&lt;br /&gt;&lt;br /&gt;   content = CharData opt, ((element | Reference | CDSect), CharData opt) star.&lt;br /&gt;&lt;br /&gt;   ComplexElement = STag, content , ETag.&lt;br /&gt;&lt;br /&gt;   element =  EmptyElemTag | ComplexElement  .&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Code for this experiment can be found &lt;a href="http://github.com/ldfallas/newspeakexperiments"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-7248248151129587319?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/7248248151129587319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=7248248151129587319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7248248151129587319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7248248151129587319'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/05/simple-xml-grammar-in-newspeak.html' title='A simple XML Grammar in Newspeak'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-51971286456223831</id><published>2010-03-11T06:02:00.002-06:00</published><updated>2010-03-12T05:13:28.895-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Some basic image processing operations with F#</title><content type='html'>The &lt;a href="http://langexplr.blogspot.com/2010/02/using-webcam-with-directshownet-and-f.html"&gt;previous post&lt;/a&gt; presented a way to access the image data from the Webcam using &lt;a href="http://directshownet.sourceforge.net/"&gt;DirectShow.Net&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/fsharp/default.aspx"&gt;F#&lt;/a&gt;. We can manipulate this data to do some basic image processing operations with it.  &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Converting image to gray scale&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Many image processing operations and algorithms are defined for grayscale images.  A simple way to convert the image to grayscale is the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; grayGrabber(transform) = &lt;br /&gt;     &lt;span class="srckeyw"&gt;fun&lt;/span&gt; (width,height) -&amp;gt;&lt;br /&gt;      {  &lt;span class="srckeyw"&gt;new&lt;/span&gt; ISampleGrabberCB &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;             &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.SampleCB(sampleTime:double , pSample:IMediaSample )= 0                     &lt;br /&gt;             &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.BufferCB(sampleTime:double , pBuffer:System.IntPtr , bufferLen:int) =                       &lt;br /&gt;                &lt;span class="srckeyw"&gt;let&lt;/span&gt; grayImage = getGrayImage pBuffer bufferLen&lt;br /&gt;                                &lt;br /&gt;                &lt;span class="srckeyw"&gt;let&lt;/span&gt; resultImage = transform width height grayImage&lt;br /&gt;                &lt;br /&gt;                saveGrayImageToRGBBuffer resultImage  pBuffer bufferLen                                                                   &lt;br /&gt;                0&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Given that we have:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; inline getGrayImage (data:IntPtr) (size:int)  = &lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; grayImage = Array.create (size/3) (byte(0))&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; pixelBuffer = Array.create 3 (byte(0))&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; mutable it = 0&lt;br /&gt;    &lt;span class="srckeyw"&gt;for&lt;/span&gt; i in 0..(size - 3 ) do &lt;br /&gt;       if (i + 1) % 3 = 0 then &lt;br /&gt;          Marshal.Copy(new System.IntPtr(data.ToInt32()+i),pixelBuffer,0,3) |&amp;gt; ignore&lt;br /&gt;          grayImage.[it] &amp;lt;-  byte(float(pixelBuffer.[0])*0.3 + &lt;br /&gt;                                  float(pixelBuffer.[1])*0.59 + &lt;br /&gt;                                  float(pixelBuffer.[2])*0.11)&lt;br /&gt;          it &amp;lt;- it+1&lt;br /&gt;    grayImage&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; inline saveGrayImageToRGBBuffer (grayImage:byte array) (data:IntPtr) (size:int) =&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; mutable targetIndex = 0&lt;br /&gt;    &lt;span class="srckeyw"&gt;for&lt;/span&gt; i in 0..(size/3 - 1) do&lt;br /&gt;      &lt;span class="srckeyw"&gt;let&lt;/span&gt; p = grayImage.[i]&lt;br /&gt;      Marshal.WriteByte(data,targetIndex,p)&lt;br /&gt;      Marshal.WriteByte(data,targetIndex+1,p)&lt;br /&gt;      Marshal.WriteByte(data,targetIndex+2,p)&lt;br /&gt;      targetIndex &amp;lt;- targetIndex+3  &lt;br /&gt;    ()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The technique for converting the image to grayscale was taken from &lt;a href="http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Using this new &lt;span style="font-style:italic;"&gt;grabber&lt;/span&gt; definition we can change the code from the previous post to do this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; mediaControl,filterGraph = createVideoCaptureWithSampleGrabber &lt;br /&gt;                                      device &lt;br /&gt;                                      nullGrayGrabber&lt;br /&gt;                                      None&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Given that &lt;code&gt;nullGrayGrabber&lt;/code&gt; is defined as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; nullGrayGrabber = grayGrabber (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; (_:&lt;span class="srckeyw"&gt;int&lt;/span&gt;) (_:&lt;span class="srckeyw"&gt;int&lt;/span&gt;) image -&amp;gt; image)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The original webcam output looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/S5jZBSpWguI/AAAAAAAAAP8/uZq6M2YfKoI/s1600-h/bimfsnullgrabber.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://2.bp.blogspot.com/_qePSufqunG4/S5jZBSpWguI/AAAAAAAAAP8/uZq6M2YfKoI/s320/bimfsnullgrabber.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5447342365512991458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;By applying this filter the webcam output looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/S5jZImPpFwI/AAAAAAAAAQE/hDtCGzC28wI/s1600-h/bimfsnullgrabbergray.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://2.bp.blogspot.com/_qePSufqunG4/S5jZImPpFwI/AAAAAAAAAQE/hDtCGzC28wI/s320/bimfsnullgrabbergray.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5447342491032950530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Applying templates&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;With this definitions we can do a common operation in image processing called template &lt;a href="http://en.wikipedia.org/wiki/Convolution"&gt;convolution&lt;/a&gt;. Basically, this technique consists in applying an operation to each pixel of an image and its surrounding neighborhood . The operation is represented by a matrix, for example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;0.0  1.0 0.0&lt;br /&gt;1.0 -1.0 1.0&lt;br /&gt;0.0  1.0 0.0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To apply this template to the a pixel of the image at x',y' we write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(0.0*image[x-1,y-1]) + (1.0*image[x,y-1]) + (0.0*image[x+1,y-1]) +&lt;br /&gt;(1.0*image[x-1,y])   + (-1.0*image[x,y]) +  (1.0*image[x+1,y]) +&lt;br /&gt;(0.0*image[x-1,y+1]) + (1.0*image[x,y+1]) + (0.0*image[x+1,y+1]) &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The function to apply this kind of operation looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; convolveGray3 w h (image:byte array) (template:float[,]) hhalf whalf =&lt;br /&gt;      &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; result = Array.create (image.Length) (byte(0))&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; getPixelGray' = getPixelGray w h image&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; setPixelGray' = setPixelGray w h result&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;for&lt;/span&gt; y &lt;span class="srckeyw"&gt;in&lt;/span&gt; (hhalf + 1) .. (h - ((Array2D.length1 template) - hhalf - 1) - 1 ) &lt;span class="srckeyw"&gt;do&lt;/span&gt;&lt;br /&gt;       &lt;span class="srckeyw"&gt;for&lt;/span&gt; x &lt;span class="srckeyw"&gt;in&lt;/span&gt; (whalf + 1) .. (w - ((Array2D.length2 template) - whalf - 1) - 1 ) &lt;span class="srckeyw"&gt;do&lt;/span&gt;&lt;br /&gt;          &lt;br /&gt;          &lt;span class="srckeyw"&gt;let&lt;/span&gt; mutable r = 0.0&lt;br /&gt;          &lt;br /&gt;          &lt;span class="srckeyw"&gt;for&lt;/span&gt; ty &lt;span class="srckeyw"&gt;in&lt;/span&gt; 0 .. (Array2D.length1 template - 1) &lt;span class="srckeyw"&gt;do&lt;/span&gt;&lt;br /&gt;          &lt;span class="srckeyw"&gt;for&lt;/span&gt; tx &lt;span class="srckeyw"&gt;in&lt;/span&gt; 0 .. (Array2D.length2 template - 1) &lt;span class="srckeyw"&gt;do&lt;/span&gt;&lt;br /&gt;             &lt;span class="srckeyw"&gt;let&lt;/span&gt; ir = getPixelGray' ( x + (tx - whalf)) ( y + (ty - hhalf))&lt;br /&gt;             r &amp;lt;- r + template.[ty ,tx ]*float(ir)  &lt;br /&gt;             &lt;br /&gt;          setPixelGray' x y (byte(Math.Abs r))&lt;br /&gt;      &lt;br /&gt;   result&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Given that:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; inline getPixelGray width height (image:byte array) x y  =&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; baseHeightOffset = y*width&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; offset = baseHeightOffset + x&lt;br /&gt;   image.[offset]&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; inline setPixelGray width height (image:byte array) x y value1 =&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; baseHeightOffset = y*width&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; offset = baseHeightOffset + x&lt;br /&gt;   image.[offset] &amp;lt;- value1  &lt;br /&gt;   ()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We can represent operations such as edge detection or smoothing.  &lt;br /&gt;First order &lt;a href="http://en.wikipedia.org/wiki/Edge_detection"&gt;edge detection&lt;/a&gt; can be represented using the following template:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; firstOrderEdgeDetectTemplate = &lt;br /&gt;             (array2D [|[|2.0;-1.0|];&lt;br /&gt;                        [|-1.0;0.0|];|])   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Changing the code of the main program to the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; convGrayGrabber1 = &lt;br /&gt;    grayGrabber (fun width height grayImage -&amp;gt; convolveGray3 width height grayImage firstOrderEdgeDetectTemplate 0 0 ) &lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now the output looks like:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/S5jZSUJOluI/AAAAAAAAAQM/fF2KI4U_Vd4/s1600-h/bimfsnullbasicedge.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://2.bp.blogspot.com/_qePSufqunG4/S5jZSUJOluI/AAAAAAAAAQM/fF2KI4U_Vd4/s320/bimfsnullbasicedge.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5447342657972901602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We can also use a template template to represent averaging. This technique removes detail from the image by calculating the average value of pixel given its neighborhood. The definition of a function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; averagingTemplate (windowSize) =&lt;br /&gt;  Array2D.create windowSize windowSize (1.0/float(windowSize*windowSize))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This function creates a template which looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; averagingTemplate 3;;&lt;br /&gt;val it : float [,] = [[0.1111111111; 0.1111111111; 0.1111111111]&lt;br /&gt;                      [0.1111111111; 0.1111111111; 0.1111111111]&lt;br /&gt;                      [0.1111111111; 0.1111111111; 0.1111111111]]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can change again the main program to use this function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; averagingGrayGrabber = &lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; template = averagingTemplate 3&lt;br /&gt;    grayGrabber (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; width height grayImage -&amp;gt; convolveGray3 width height grayImage template 1 1 )&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; mediaControl,filterGraph = createVideoCaptureWithSampleGrabber &lt;br /&gt;                                      device &lt;br /&gt;                                      averagingGrayGrabber &lt;br /&gt;                                      None&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The result image looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/S5jZfk7LGCI/AAAAAAAAAQU/yEBG0Q_oyxk/s1600-h/bimfsnullaverage.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://4.bp.blogspot.com/_qePSufqunG4/S5jZfk7LGCI/AAAAAAAAAQU/yEBG0Q_oyxk/s320/bimfsnullaverage.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5447342885815654434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Final words&lt;/h4&gt;&lt;br /&gt;As with the previous post I'm using mainly the imperative features of F# . For future posts I'll try change this and also continue the exploration of image processing with F#.&lt;br /&gt;&lt;br /&gt;Most of the techniques described here were taken from the &lt;a href="http://users.ecs.soton.ac.uk/msn/book/"&gt;"Feature Extraction &amp;amp; Image Processing"&lt;/a&gt; book by Mark S. Nixon and Alberto S. Aguado.&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://gist.github.com/329062"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-51971286456223831?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/51971286456223831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=51971286456223831' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/51971286456223831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/51971286456223831'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/03/some-basic-image-processing-operations.html' title='Some basic image processing operations with F#'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_qePSufqunG4/S5jZBSpWguI/AAAAAAAAAP8/uZq6M2YfKoI/s72-c/bimfsnullgrabber.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-7757393670408900293</id><published>2010-02-24T06:00:00.001-06:00</published><updated>2010-02-24T06:14:44.403-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Using a Webcam with DirectShowNET and F#</title><content type='html'>In this post I'm going to show a small F# example of using DirectShowNET to access a webcam and manipulate the image data. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;DirectShow&lt;/h4&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/dd375454%28VS.85%29.aspx"&gt;DirectShow&lt;/a&gt; is a huge Windows API for video playback and capture. Among &lt;a href="http://msdn.microsoft.com/en-us/library/dd375464%28VS.85%29.aspx"&gt;many things&lt;/a&gt; this API allows flexible access to data captured by video input devices such as a webcam. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;DirectShowNET&lt;/h4&gt;&lt;br /&gt;The DirectShow is COM based API. According to &lt;a href="http://msdn.microsoft.com/en-us/library/dd390351%28VS.85%29.aspx"&gt;the documentation&lt;/a&gt;, it's meant to be used from C++.  Luckily there's &lt;a href="http://directshownet.sourceforge.net/about.html"&gt;DirectShowNET&lt;/a&gt; which is a very nice library that exposes the DirectShow interfaces to .NET languages .&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Accessing the webcam&lt;/h4&gt;&lt;br /&gt;What I wanted to do for this example is to have access to the data of the image being captured at a given time. The DirectShow API provides the concept of a &lt;a href="http://msdn.microsoft.com/en-us/library/dd377544%28VS.85%29.aspx"&gt;Sample Grabber&lt;/a&gt; which not only gives you access to the captured data, but also allows its modification . &lt;br /&gt;&lt;br /&gt;The following example shows the use of a couple of functions defined below:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; device = findCaptureDevice&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; mediaControl,filterGraph = createVideoCaptureWithSampleGrabber &lt;br /&gt;                                      device &lt;br /&gt;                                      nullGrabber &lt;br /&gt;                                      None&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; form = &lt;span class="srckeyw"&gt;new&lt;/span&gt; Form(Size = &lt;span class="srckeyw"&gt;new&lt;/span&gt; Size(300,300), Visible = &lt;span class="srckeyw"&gt;true&lt;/span&gt;,Text = &lt;span class="srctext"&gt;"Webcam input"&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; videoWindow = configureVideoWindow (form.Handle) 300 300 filterGraph&lt;br /&gt;&lt;br /&gt;form.Closing.Add (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; _ -&amp;gt; &lt;br /&gt;                      mediaControl.StopWhenReady() &lt;br /&gt;                      Marshal.ReleaseComObject(videoWindow) |&amp;gt; ignore&lt;br /&gt;                      Marshal.ReleaseComObject(mediaControl) |&amp;gt; ignore&lt;br /&gt;                      Marshal.ReleaseComObject(filterGraph) |&amp;gt; ignore)&lt;br /&gt;                      &lt;br /&gt;&lt;br /&gt;mediaControl.Run() |&amp;gt; ignore&lt;br /&gt;&lt;br /&gt;Application.Run(form)   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running this program will show the following window:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/S4UQDiocRuI/AAAAAAAAAPs/XVbsMJKvMzM/s1600-h/wccap1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://2.bp.blogspot.com/_qePSufqunG4/S4UQDiocRuI/AAAAAAAAAPs/XVbsMJKvMzM/s320/wccap1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5441773377769195234" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Notice that we called the &lt;code&gt;createVideoCaptureWithSampleGrabber&lt;/code&gt; function using the &lt;code&gt;nullGrabber&lt;/code&gt; parameter. This parameter specifies a &lt;span style="font-style:italic;"&gt;sample grabber&lt;/span&gt; that does nothing with the current frame. Here's the definition:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; nullGrabber =&lt;br /&gt;    &lt;span class="srckeyw"&gt;fun&lt;/span&gt; (width,height) -&amp;gt;&lt;br /&gt;          {  &lt;span class="srckeyw"&gt;new&lt;/span&gt; ISampleGrabberCB &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;             &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.SampleCB(sampleTime:&lt;span class="srckeyw"&gt;double&lt;/span&gt; , pSample:IMediaSample )= 0                     &lt;br /&gt;             &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.BufferCB(sampleTime:&lt;span class="srckeyw"&gt;double&lt;/span&gt; , pBuffer:System.IntPtr , bufferLen:&lt;span class="srckeyw"&gt;int&lt;/span&gt;) = 0 &lt;br /&gt;          }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can change this &lt;span style="font-style:italic;"&gt;sample grabber&lt;/span&gt; to something more interesting:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; incrementGrabber = &lt;br /&gt;     &lt;span class="srckeyw"&gt;fun&lt;/span&gt; (width,height) -&amp;gt;&lt;br /&gt;      {  &lt;span class="srckeyw"&gt;new&lt;/span&gt; ISampleGrabberCB &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;             &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.SampleCB(sampleTime:&lt;span class="srckeyw"&gt;double&lt;/span&gt; , pSample:IMediaSample )= 0                     &lt;br /&gt;             &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.BufferCB(sampleTime:&lt;span class="srckeyw"&gt;double&lt;/span&gt; , pBuffer:System.IntPtr , bufferLen:&lt;span class="srckeyw"&gt;int&lt;/span&gt;) =                       &lt;br /&gt;                &lt;span class="srckeyw"&gt;for&lt;/span&gt; i = 0 &lt;span class="srckeyw"&gt;to&lt;/span&gt; (bufferLen - 1) &lt;span class="srckeyw"&gt;do&lt;/span&gt;&lt;br /&gt;                   &lt;span class="srckeyw"&gt;let&lt;/span&gt; c = Marshal.ReadByte(pBuffer,i)&lt;br /&gt;                   Marshal.WriteByte(pBuffer,i ,if c &amp;gt; byte(150) then byte(255) else c+byte(100))&lt;br /&gt;                0 }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We can change the program to use:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; mediaControl,filterGraph = createVideoCaptureWithSampleGrabber &lt;br /&gt;                                      device &lt;br /&gt;                                      incrementGrabber &lt;br /&gt;                                      None&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running the program we can see:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/S4USByPJ9BI/AAAAAAAAAP0/agfrJx28A0w/s1600-h/wccap3.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://4.bp.blogspot.com/_qePSufqunG4/S4USByPJ9BI/AAAAAAAAAP0/agfrJx28A0w/s320/wccap3.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5441775546621621266" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This new sample grabber increments each pixel value by 100 or leaves the maximum value to prevent overflow. As presented here the pixel information is provided as an unmanaged pointer. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Using DirectShowNet&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;DirectShow also has the concept of &lt;span style="font-style:italic;"&gt;filters&lt;/span&gt; which are software components that are assembled together to mix various inputs and outputs. For this examples we're going to used only a couple of interfaces. The code for this post is based on the DxLogo sample provided with DirectShowNET.&lt;br /&gt;&lt;br /&gt;First we define the module containing these functions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;module&lt;/span&gt; LangExplrExperiments.DirectShowCapture&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; DirectShowLib&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System.Runtime.InteropServices&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System.Runtime.InteropServices.ComTypes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; &lt;span class="srckeyw"&gt;private&lt;/span&gt; checkResult hresult = DsError.ThrowExceptionForHR( hresult )&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;checkResult&lt;/code&gt; function is an utility function to check for the HRESULT of some of the calls to COM interfaces. Since DirectShowNET is a thin wrapper for these interfaces we need to use this function to check for errors.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;findCaptureDevice&lt;/code&gt; returns the first capture devices detected by DirectShowNET .&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; findCaptureDevice = &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; source : &lt;span class="srckeyw"&gt;obj&lt;/span&gt; &lt;span class="srckeyw"&gt;ref&lt;/span&gt; = &lt;span class="srckeyw"&gt;ref&lt;/span&gt; null&lt;br /&gt;   devices.[0].Mon.BindToObject(null,null,&lt;span class="srckeyw"&gt;ref&lt;/span&gt; typeof&amp;lt;IBaseFilter&amp;gt;.GUID,source)&lt;br /&gt;   devices.[0]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The following functions define the capture filter and sample grabber. The &lt;code&gt;createVideoCaptureWithSampleGrabber&lt;/code&gt; function is the entry point. We can specify a file name as the final parameter to save the captured data to a video file.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; private ConfigureSampleGrabber( sampGrabber:ISampleGrabber,callbackobject:ISampleGrabberCB) =&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; media = &lt;span class="srckeyw"&gt;new&lt;/span&gt; AMMediaType()&lt;br /&gt;        &lt;br /&gt;    media.majorType &amp;lt;- MediaType.Video&lt;br /&gt;    media.subType &amp;lt;- MediaSubType.RGB24&lt;br /&gt;    media.formatType &amp;lt;- FormatType.VideoInfo&lt;br /&gt;    &lt;br /&gt;    sampGrabber.SetMediaType( media ) |&amp;gt; checkResult    &lt;br /&gt;    DsUtils.FreeAMMediaType(media);&lt;br /&gt;            &lt;br /&gt;    sampGrabber.SetCallback( callbackobject, 1 ) |&amp;gt; checkResult&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; getCaptureResolution(capGraph:ICaptureGraphBuilder2 , capFilter:IBaseFilter) =        &lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; o : &lt;span class="srckeyw"&gt;obj&lt;/span&gt; &lt;span class="srckeyw"&gt;ref&lt;/span&gt; = &lt;span class="srckeyw"&gt;ref&lt;/span&gt; &lt;span class="srckeyw"&gt;null&lt;/span&gt;&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; media : AMMediaType &lt;span class="srckeyw"&gt;ref&lt;/span&gt; = &lt;span class="srckeyw"&gt;ref&lt;/span&gt; &lt;span class="srckeyw"&gt;null&lt;/span&gt;            &lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; videoControl = capFilter :?&amp;gt; IAMVideoControl&lt;br /&gt;&lt;br /&gt;    capGraph.FindInterface(&lt;span class="srckeyw"&gt;new&lt;/span&gt; DsGuid( PinCategory.Capture), &lt;br /&gt;                           &lt;span class="srckeyw"&gt;new&lt;/span&gt; DsGuid( MediaType.Video), &lt;br /&gt;                           capFilter, &lt;br /&gt;                           typeof&amp;lt;IAMStreamConfig&amp;gt;.GUID, &lt;br /&gt;                           o ) |&amp;gt; checkResult    &lt;br /&gt;                           &lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; videoStreamConfig = o.Value :?&amp;gt; IAMStreamConfig;&lt;br /&gt;                &lt;br /&gt;    videoStreamConfig.GetFormat(media) |&amp;gt; checkResult    &lt;br /&gt;        &lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; v  = &lt;span class="srckeyw"&gt;new&lt;/span&gt; VideoInfoHeader()&lt;br /&gt;    Marshal.PtrToStructure( media.Value.formatPtr, v )&lt;br /&gt;    DsUtils.FreeAMMediaType(media.Value)&lt;br /&gt;    &lt;br /&gt;    v.BmiHeader.Width,v.BmiHeader.Height&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; createCaptureFilter (captureDevice:DsDevice) &lt;br /&gt;                        (sampleGrabberCBCreator: int*int -&amp;gt; ISampleGrabberCB) = &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; captureGraphBuilder =  box(&lt;span class="srckeyw"&gt;new&lt;/span&gt; CaptureGraphBuilder2()) :?&amp;gt; ICaptureGraphBuilder2&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; sampGrabber = box(&lt;span class="srckeyw"&gt;new&lt;/span&gt; SampleGrabber()) :?&amp;gt; ISampleGrabber;&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; filterGraph = box(&lt;span class="srckeyw"&gt;new&lt;/span&gt; FilterGraph()) :?&amp;gt; IFilterGraph2   &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; capFilter: IBaseFilter &lt;span class="srckeyw"&gt;ref&lt;/span&gt; = &lt;span class="srckeyw"&gt;ref&lt;/span&gt; &lt;span class="srckeyw"&gt;null&lt;/span&gt;&lt;br /&gt;   &lt;br /&gt;   captureGraphBuilder.SetFiltergraph(filterGraph) |&amp;gt; checkResult   &lt;br /&gt;   &lt;br /&gt;   filterGraph.AddSourceFilterForMoniker(&lt;br /&gt;                      captureDevice.Mon,&lt;br /&gt;                      &lt;span class="srckeyw"&gt;null&lt;/span&gt;,&lt;br /&gt;                      captureDevice.Name,&lt;br /&gt;                      capFilter) |&amp;gt; checkResult&lt;br /&gt;                      &lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; resolution = getCaptureResolution(captureGraphBuilder,capFilter.Value)   &lt;br /&gt;   ConfigureSampleGrabber(sampGrabber, sampleGrabberCBCreator(resolution) )&lt;br /&gt;   &lt;br /&gt;   filterGraph.AddFilter(box(sampGrabber) :?&amp;gt; IBaseFilter , "FSGrabberFilter") |&amp;gt; checkResult&lt;br /&gt;                 &lt;br /&gt;           &lt;br /&gt;   captureGraphBuilder,filterGraph,sampGrabber,capFilter.Value&lt;br /&gt;   &lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; getMediaControl (captureGraphBuilder :ICaptureGraphBuilder2)&lt;br /&gt;                    (sampGrabber: ISampleGrabber)&lt;br /&gt;                    (capFilter:IBaseFilter)&lt;br /&gt;                    (filterGraph:IFilterGraph2)&lt;br /&gt;                    (fileNameOpt:string option)=&lt;br /&gt;  &lt;span class="srckeyw"&gt;let&lt;/span&gt; muxFilter: IBaseFilter &lt;span class="srckeyw"&gt;ref&lt;/span&gt; = &lt;span class="srckeyw"&gt;ref&lt;/span&gt; &lt;span class="srckeyw"&gt;null&lt;/span&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;let&lt;/span&gt; fileWriterFilter : IFileSinkFilter &lt;span class="srckeyw"&gt;ref&lt;/span&gt; = &lt;span class="srckeyw"&gt;ref&lt;/span&gt; &lt;span class="srckeyw"&gt;null&lt;/span&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;try&lt;/span&gt;        &lt;br /&gt;      &lt;span class="srckeyw"&gt;match&lt;/span&gt; fileNameOpt &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;        | Some filename -&amp;gt;            &lt;br /&gt;            captureGraphBuilder.SetOutputFileName(&lt;br /&gt;                                                    MediaSubType.Avi, &lt;br /&gt;                                                    filename,                          &lt;br /&gt;                                                    muxFilter,  &lt;br /&gt;                                                    fileWriterFilter) |&amp;gt; checkResult&lt;br /&gt;            &lt;br /&gt;        | None -&amp;gt; ()&lt;br /&gt;        &lt;br /&gt;      captureGraphBuilder.RenderStream(&lt;br /&gt;                                        &lt;span class="srckeyw"&gt;new&lt;/span&gt; DsGuid( PinCategory.Capture),&lt;br /&gt;                                        &lt;span class="srckeyw"&gt;new&lt;/span&gt; DsGuid( MediaType.Video),&lt;br /&gt;                                        capFilter,&lt;br /&gt;                                        sampGrabber :?&amp;gt; IBaseFilter,&lt;br /&gt;                                        muxFilter.Value) |&amp;gt; checkResult&lt;br /&gt;      &lt;br /&gt;  &lt;span class="srckeyw"&gt;finally&lt;/span&gt;&lt;br /&gt;      if fileWriterFilter.Value &amp;lt;&amp;gt; &lt;span class="srckeyw"&gt;null&lt;/span&gt; then&lt;br /&gt;         Marshal.ReleaseComObject(fileWriterFilter.Value) |&amp;gt; ignore&lt;br /&gt;      if muxFilter.Value &amp;lt;&amp;gt; &lt;span class="srckeyw"&gt;null&lt;/span&gt; then&lt;br /&gt;         Marshal.ReleaseComObject(muxFilter.Value) |&amp;gt; ignore     &lt;br /&gt;         &lt;br /&gt;  filterGraph :?&amp;gt;  IMediaControl  &lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; createVideoCaptureWithSampleGrabber (device:DsDevice) &lt;br /&gt;                                        (sampleGrabberCBCreator: int*int -&amp;gt; ISampleGrabberCB) &lt;br /&gt;                                        (outputFileName: string option) =&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; capGraphBuilder,filterGraph,sampGrabber,capFilter = createCaptureFilter device sampleGrabberCBCreator&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; mediaControl = getMediaControl capGraphBuilder sampGrabber capFilter filterGraph outputFileName&lt;br /&gt;   &lt;br /&gt;   Marshal.ReleaseComObject capGraphBuilder |&amp;gt; ignore&lt;br /&gt;   Marshal.ReleaseComObject capFilter |&amp;gt; ignore&lt;br /&gt;   Marshal.ReleaseComObject sampGrabber |&amp;gt; ignore&lt;br /&gt;   &lt;br /&gt;   mediaControl,filterGraph&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Also for the creation of the video window the following function is provided:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; configureVideoWindow windowHandle width height (filterGraph:IFilterGraph2) =&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; videoWindow  = filterGraph :?&amp;gt; IVideoWindow&lt;br /&gt;&lt;br /&gt;   videoWindow.put_Owner(windowHandle) |&amp;gt; checkResult   &lt;br /&gt;   videoWindow.put_WindowStyle(WindowStyle.Child ||| WindowStyle.ClipChildren) |&amp;gt; checkResult   &lt;br /&gt;   videoWindow.SetWindowPosition(0,0,width,height) |&amp;gt; checkResult   &lt;br /&gt;   videoWindow.put_Visible(OABool.True)|&amp;gt; checkResult&lt;br /&gt;   &lt;br /&gt;   videoWindow&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For future posts I'm going to try some experiments with the pixel data provided by the &lt;span style="font-style:italic;"&gt;sample grabber&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-7757393670408900293?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/7757393670408900293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=7757393670408900293' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7757393670408900293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7757393670408900293'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/02/using-webcam-with-directshownet-and-f.html' title='Using a Webcam with DirectShowNET and F#'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_qePSufqunG4/S4UQDiocRuI/AAAAAAAAAPs/XVbsMJKvMzM/s72-c/wccap1.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-2923266521230401938</id><published>2010-02-01T06:42:00.006-06:00</published><updated>2010-02-01T07:09:26.309-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Using a Webcam with WIA and F#</title><content type='html'>In this post I'm going to show a small example of taking a picture using a Webcam with &lt;a href="http://msdn.microsoft.com/en-us/library/ms630368%28VS.85%29.aspx"&gt;Windows Image Adquisition&lt;/a&gt; 1.0 . This API seems to have changed in Vista and above, the following code only applies to XP. &lt;br /&gt;&lt;br /&gt;First step, create the interop assemblies:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;C:\test\&amp;gt; TlbImp c:\WINDOWS\system32\wiascr.dll&lt;br /&gt;Microsoft (R) .NET Framework Type Library to Assembly Converter 3.5.30729.1&lt;br /&gt;Copyright (C) Microsoft Corporation.  All rights reserved.&lt;br /&gt;&lt;br /&gt;Type library imported to WIALib.dll&lt;br /&gt;&lt;br /&gt;C:\test&amp;gt;TlbImp c:\WINDOWS\system32\wiavideo.dll&lt;br /&gt;Microsoft (R) .NET Framework Type Library to Assembly Converter 3.5.30729.1&lt;br /&gt;Copyright (C) Microsoft Corporation.  All rights reserved.&lt;br /&gt;&lt;br /&gt;Type library imported to WIAVIDEOLib.dll&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we launch FSI and load the assemblies:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;C:\test&amp;gt; fsi.exe&lt;br /&gt;&lt;br /&gt;Microsoft F# Interactive, (c) Microsoft Corporation, All Rights Reserved&lt;br /&gt;F# Version 1.9.7.8, compiling for .NET Framework Version v2.0.50727&lt;br /&gt;&lt;br /&gt;For help type #help;;&lt;br /&gt;&lt;br /&gt;&amp;gt;  #r "WIALib.dll";;&lt;br /&gt;&lt;br /&gt;--&amp;gt; Referenced 'C:\development\blog\wiafs\WIALib.dll'&lt;br /&gt;&lt;br /&gt;&amp;gt;  #r "WIAVIDEOLIB.dll";;&lt;br /&gt;&lt;br /&gt;--&amp;gt; Referenced 'C:\development\blog\wiafs\WIAVIDEOLIB.dll'&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we can list the capture devices:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; wia.Devices |&amp;gt; Seq.cast |&amp;gt; Seq.map (fun (x:WIALib.IWiaDeviceInfo) -&amp;gt; x.Name);;&lt;br /&gt;&lt;br /&gt;val it : seq&amp;lt;string&amp;gt; = seq ["My iPod"; "Logitech QuickCam Chat"]&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now I'm going to use the QuickCam to take the picture so we get the information for this device (of type 'StreamingVideo'):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; let devInfo = wia.Devices |&amp;gt; Seq.cast |&amp;gt; Seq.filter (fun (x:WIALib.IWiaDeviceInfo) -&amp;gt; x.Type.Contains("StreamingVideo")) |&amp;gt; Seq.head;;&lt;br /&gt;&lt;br /&gt;val devInfo : WIALib.IWiaDeviceInfo&lt;br /&gt;&lt;br /&gt;&amp;gt; devInfo.Name;;&lt;br /&gt;val it : string = "Logitech QuickCam Chat"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we create an instance of the 'WIAVIDEOLib.WiaVideoClass' which will let us use the Webcam.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; let vid = new WIAVIDEOLib.WiaVideoClass();;&lt;br /&gt;Binding session to 'C:\development\blog\wiafs\WIAVIDEOLib.dll'...&lt;br /&gt;&lt;br /&gt;val vid : WIAVIDEOLib.WiaVideoClass&lt;br /&gt;&lt;br /&gt;&amp;gt;  vid.ImagesDirectory &lt;- "c:\\temp";;&lt;br /&gt;val it : unit = ()&lt;br /&gt;&amp;gt; let h = ref (new WIAVIDEOLib._RemotableHandle());;&lt;br /&gt;&lt;br /&gt;val h : WIAVIDEOLib._RemotableHandle ref =&lt;br /&gt;  {contents = WIAVIDEOLib._RemotableHandle;}&lt;br /&gt;&lt;br /&gt;&amp;gt; vid.CreateVideoByWiaDevID(devInfo.Id,h,0,1);;&lt;br /&gt;val it : unit = ()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The 'ImagesDirectory' property specifies the location for the captured images.&lt;br /&gt;&lt;br /&gt;Now we can take a picture:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; let outFileName = ref "";;&lt;br /&gt;&lt;br /&gt;val outFileName : string ref = {contents = "";}&lt;br /&gt;&lt;br /&gt;&amp;gt; vid.TakePicture( outFileName );;&lt;br /&gt;val it : unit = ()&lt;br /&gt;&amp;gt; outFileName;;&lt;br /&gt;val it : string ref = {contents = "c:\temp\Imagen 009.jpg";}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The 'outFileName' parameter gets the name of the saved image  in the images directory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-2923266521230401938?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/2923266521230401938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=2923266521230401938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2923266521230401938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2923266521230401938'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2010/02/using-webcam-with-wia-and-f.html' title='Using a Webcam with WIA and F#'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-8164506257701673619</id><published>2009-11-23T06:03:00.001-06:00</published><updated>2009-11-23T06:08:57.513-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><title type='text'>Adding automatic semicolon insertion to a Javascript parser</title><content type='html'>A couple of weeks ago I wrote a &lt;a href="http://langexplr.blogspot.com/2009/10/parsing-javascript-using-newspeak.html"&gt;blog post&lt;/a&gt; about a Javascript parser written using the &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak&lt;/a&gt; parsing combinators. As mentioned in that post, no semicolon insertion was supported. This post shows how the feature was added.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Automatic semicolon insertion&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As detailed in section 7.9 of the &lt;a href="http://www.google.co.cr/url?q=http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf&amp;ei=9XYKS9OwGMmztge1zfGuCg&amp;sa=X&amp;oi=nshc&amp;resnum=1&amp;ct=result&amp;cd=1&amp;ved=0CAgQzgQoAA&amp;usg=AFQjCNHo6znh-7fu96Ap1ioZYtIbaPBaMg"&gt;ECMA 262 document[PDF]&lt;/a&gt;, in Javascript you can use newline as statement separator in some scenarios. For example a semicolon is "implicitly inserted" if expression-statements are separated by line terminators:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;if (condition) {&lt;br /&gt;   print("A")&lt;br /&gt;   print("B")&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This code snippet is equivalent to:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;if (condition) {&lt;br /&gt;   print("A");&lt;br /&gt;   print("B");&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In the a &lt;a href="http://langexplr.blogspot.com/2009/10/parsing-javascript-using-newspeak.html"&gt;original post&lt;/a&gt; about the parser, &lt;a href="http://ongiantsshoulders.blogspot.com/"&gt;espin&lt;/a&gt; pointed me out to a &lt;a href="http://www.vpri.org/pdf/tr2007003_ometa.pdf"&gt;paper[PDF]&lt;/a&gt; by &lt;a href="http://www.tinlizzie.org/~awarth/"&gt;A. Warth&lt;/a&gt; that mentions how the semicolon insertion problem was solved in a Javascript parser written in &lt;a href="http://tinlizzie.org/ometa/"&gt;OMeta&lt;/a&gt;. The solution presented is this post is based on the one from the paper.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I wanted to isolate the code that performs this function. So in order to add this functionality I created a subclass that overrides the productions that get involved in this process. This way we can have both a parser with and without the feature. Here's the code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class JSGrammarWithSemicolonInsertion = JSGrammar (&lt;br /&gt;&lt;span class="srccomment"&gt;"Parser features that add automatic semicolon insertion"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt; &lt;br /&gt;    specialStatementTermination = ((( cr | lf ) not &amp;amp; whitespace ) star,&lt;br /&gt;                                       (semicolon | comment | lf | cr | (peek: $})) ) &lt;br /&gt;                                       wrapper: [ :ws :terminator | | t | t:: Token new. t token: $;. t].&lt;br /&gt;&lt;br /&gt;    returnStatement =  return, (specialStatementTermination | &lt;br /&gt;                                (expression ,  specialStatementTermination)).&lt;br /&gt;&lt;br /&gt;    breakStatement = break,  (specialStatementTermination | &lt;br /&gt;                              (identifier ,  specialStatementTermination)). &lt;br /&gt;&lt;br /&gt;    continueStatement = continue,  (specialStatementTermination | &lt;br /&gt;                                    (identifier ,  specialStatementTermination)). &lt;br /&gt;&lt;br /&gt;    whitespaceNoEOL = (( cr | lf ) not &amp;amp; whitespace ) star,&lt;br /&gt;                          (((peek: (Character cr)) | (peek: (Character lf))) not) .&lt;br /&gt;&lt;br /&gt;    throwStatement = throw,  whitespaceNoEOL , expression ,  specialStatementTermination. &lt;br /&gt;&lt;br /&gt;    expressionStatement = (((function | leftbrace) not) &amp;amp; expression), specialStatementTermination.&lt;br /&gt;&lt;br /&gt;    variableStatement = var, variableDeclarationList, specialStatementTermination.&lt;br /&gt;| &lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The result of parsing the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span type="srckeyw"&gt;var&lt;/span&gt; x = 0&lt;br /&gt;&lt;span type="srckeyw"&gt;while&lt;/span&gt; (&lt;span type="srckeyw"&gt;true&lt;/span&gt;) {&lt;br /&gt;   x++&lt;br /&gt;   document.write(x)&lt;br /&gt;   &lt;span type="srckeyw"&gt;if&lt;/span&gt; ( x &amp;gt; 10)&lt;br /&gt;     &lt;span type="srckeyw"&gt;break&lt;/span&gt;&lt;br /&gt;   else &lt;span type="srckeyw"&gt;continue&lt;/span&gt;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;... is presented using the utility created for the previous post:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/Swp2ra6iDGI/AAAAAAAAAPg/EuEP_lKqoUI/s1600/nwsjsparsingsci1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 330px; height: 400px;" src="http://4.bp.blogspot.com/_qePSufqunG4/Swp2ra6iDGI/AAAAAAAAAPg/EuEP_lKqoUI/s400/nwsjsparsingsci1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5407264790942977122" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Code for this post is available &lt;a href="http://github.com/ldfallas/newspeakexperiments/tree/master/jsparser/"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-8164506257701673619?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/8164506257701673619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=8164506257701673619' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/8164506257701673619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/8164506257701673619'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/11/adding-automatic-semicolon-insertion-to.html' title='Adding automatic semicolon insertion to a Javascript parser'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_qePSufqunG4/Swp2ra6iDGI/AAAAAAAAAPg/EuEP_lKqoUI/s72-c/nwsjsparsingsci1.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-3522162764565834734</id><published>2009-10-19T06:22:00.002-06:00</published><updated>2011-04-05T06:13:33.359-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='j'/><category scheme='http://www.blogger.com/atom/ns#' term='apl'/><title type='text'>A quick look at J</title><content type='html'>In this post I'm going to show a small overview of the &lt;a href="http://www.jsoftware.com/"&gt;J programming language&lt;/a&gt;. An example of polynomial multiplication is examined.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;J&lt;/h4&gt;&lt;br /&gt;J is an &lt;a href="http://en.wikipedia.org/wiki/Array_programming"&gt;array programming language&lt;/a&gt; derived from &lt;a href="http://en.wikipedia.org/wiki/APL_(programming_language)"&gt;APL&lt;/a&gt; which means is good for manipulating arrays and matrices. Its syntax and semantics are very different from other languages which makes it an interesting topic for studying.&lt;br /&gt;&lt;br /&gt;There's a lot of documentation and examples available from the &lt;a href="http://www.jsoftware.com/jwiki/Guides"&gt;J software website&lt;/a&gt;. Two complete tutorials are &lt;a href="http://www.jsoftware.com/help/learning/contents.htm"&gt;"Learning J"&lt;/a&gt; by Roger Stokes and &lt;a href="http://www.jsoftware.com/help/jforc/contents.htm"&gt;"J for C programmers"&lt;/a&gt; by Henry Rich.&lt;br /&gt;&lt;br /&gt;The J distribution also includes examples and tutorials. The examples will be presented using  J's REPL called &lt;code&gt;jconsole&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The example&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In order to give an overview of the language I'm going to start from the definition of a function that performs polynomial multiplication and examine how it was constructed.&lt;br /&gt;&lt;br /&gt;The function is defined as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;polymulti =: dyad : '+/ (((_1 * i. #y) (|. "0 1) ((x (*"_ 0) y) (,"1 1) (((#y) - 1) $ 0))) , 0)'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Writing this example helped me understand some of the J's basic concepts (I'm completely sure there's a better/more efficient way to do this!). &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Polynomial multiplication&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The basic technique for &lt;a href="http://www.purplemath.com/modules/polymult.htm"&gt;polynomial multiplication&lt;/a&gt; consists on multiplying each term of one of the polynomials by the order and them simply the result. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1)   *   (2x&lt;sup&gt;2&lt;/sup&gt; - x - 3) &lt;br /&gt;&lt;br /&gt;= ((4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1) * 2x&lt;sup&gt;2&lt;/sup&gt;) + &lt;br /&gt;  ((4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1) * -x) +&lt;br /&gt;  ((4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1) * -3)&lt;br /&gt;&lt;br /&gt;= (8x&lt;sup&gt;5&lt;/sup&gt; - 46x&lt;sup&gt;4&lt;/sup&gt; + 2x&lt;sup&gt;3&lt;/sup&gt; + 2x&lt;sup&gt;2&lt;/sup&gt;) + &lt;br /&gt;  (-4x&lt;sup&gt;4&lt;/sup&gt; + 23x&lt;sup&gt;3&lt;/sup&gt; - x&lt;sup&gt;2&lt;/sup&gt; - x)  +&lt;br /&gt;  (-12x&lt;sup&gt;3&lt;/sup&gt; + 69x&lt;sup&gt;2&lt;/sup&gt; - 3x - 3) &lt;br /&gt;&lt;br /&gt;= (8x&lt;sup&gt;5&lt;/sup&gt; - 50x&lt;sup&gt;4&lt;/sup&gt; + 13x&lt;sup&gt;3&lt;/sup&gt; + 70x&lt;sup&gt;2&lt;/sup&gt; - 4x - 3)  &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now I'll start creating &lt;code&gt;polymulti&lt;/code&gt; from the bottom up to the definition.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;1. Defining polynomials&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As mentioned above J is a nice language for manipulating arrays. We're going to use J arrays to define polynomials. In fact J supports some &lt;a href="http://www.jsoftware.com/help/jforc/applied_mathematics_in_j.htm#_Toc191734506"&gt;operations on arrays as polynomials&lt;/a&gt; which will be described bellow.&lt;br /&gt;&lt;br /&gt;In order to write a new array literal containing 1,1, -23 and 4 in J we write (here using jconsole):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   1 1 _23 4&lt;br /&gt;1 1 _23 4&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see the elements of the array are separated by space. Also negative numbers are prefixed by underscore '_'. This array is going to be used to represent the coefficients of the "(4x&lt;sup&gt;3&lt;/sup&gt; - 23x&lt;sup&gt;2&lt;/sup&gt; + x + 1)" polynomial.&lt;br /&gt;&lt;br /&gt;We're going to define two variables with the polynomials shown above to use them for examples:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   p1 =: 1 1 _23 4&lt;br /&gt;   p2 =: _3 _1 2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here the '=:' operator is used to bind the specified arrays with p1 and p2.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;2. Multiply each element of one of the polynomials&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;We can proceed to apply the first step in the process which is multiply each element of the second operand by the first operand.&lt;br /&gt;&lt;br /&gt;In J we can operate on arrays easily, for example if we want to multiply each element of the above array by a 2 we write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   1 1 _23 4 * 2&lt;br /&gt;2 2 _46 8&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In J the an operation that receives two arguments is called a &lt;a href="http://www.jsoftware.com/help/learning/01.htm#11"&gt;&lt;span style="font-weight:bold;"&gt;dyad&lt;/span&gt;&lt;/a&gt; and a operation that receives only one is called &lt;a href="http://www.jsoftware.com/help/learning/01.htm#11"&gt;&lt;span style="font-weight:bold;"&gt;monad&lt;/span&gt;&lt;/a&gt;. Here we're using the '*' dyad to perform the multiplication.&lt;br /&gt;&lt;br /&gt;We cannot directly go and type "p1 * p2" because we will get the following error:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   p1 * p2&lt;br /&gt;|length error&lt;br /&gt;|   p1    *p2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This happens because the length of the two arrays (4 and 3) could not be used to perform the operation. We can apply '*' to a two same size arrays and J will multiply each element. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   p1 * p1&lt;br /&gt;1 1 529 16&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now what I want is to multiply each element of 'p2' by 'p1'. In order to do this we can change the behavior of the '*' dyad by specifying its rank (more details on how to do this can be found in &lt;a href="http://www.jsoftware.com/help/jforc/loopless_code_i_verbs_have_r.htm#_Toc191734341"&gt;"Verb Execution -- How Rank Is Used (Dyads)"&lt;/a&gt;) .  To change the rank of '*' and say that we want to multiply the complete array on the left for each of the cells of the right array we write &lt;code&gt;(*"_ 0)&lt;/code&gt; .For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   p1 (*"_ 0) p2&lt;br /&gt;_3 _3  69 _12&lt;br /&gt;_1 _1  23  _4&lt;br /&gt; 2  2 _46   8&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By specifying &lt;code&gt;(*"_ 0)&lt;/code&gt; we say that the left operand has "infinite rank" (_) which means it will consider the  array as single unit.We also say that for the right argument we will consider every cell (by using the 0 rank). Notice that in order to modify the rank we use double quote (") which, in J, doesn't have to paired with another double quote as in most programming languages.&lt;br /&gt;&lt;br /&gt;Also you can notice that the result of this operation is an array of arrays, one for each element of the right argument. &lt;br /&gt;&lt;br /&gt;2. Sum each element of one of the polynomials&lt;br /&gt;&lt;br /&gt;Now that we have an array of polynomials with the result of multiplying the coefficients, we need to change the degree of each of the polynomials. First we need to make more space to increment the degree of the polynomials. We're going to use the ',' dyad which lets you concatenate two arrays. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   p1 , 0 0&lt;br /&gt;1 1 _23 4 0 0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We need to append an array that is the size of the second polynomial minus one. In order to create a new array of this size we use '$' which lets you create an array or matrix by specifying the size and the value of the elements of the new array. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   10 $ 0&lt;br /&gt;0 0 0 0 0 0 0 0 0 0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The size of the array can be obtained with the '#' monad. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   # p1&lt;br /&gt;4&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we can combine all these elements to resize each array resulting from the multiplication of the coefficients like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   (p1 (*"_ 0) p2)&lt;br /&gt;_3 _3  69 _12&lt;br /&gt;_1 _1  23  _4&lt;br /&gt; 2  2 _46   8&lt;br /&gt;    (((#p2) - 1 ) $ 0)&lt;br /&gt;0 0&lt;br /&gt;   (p1 (*"_ 0) p2) (,"1 1) ( ((#p2) - 1 ) $ 0)&lt;br /&gt;_3 _3  69 _12 0 0&lt;br /&gt;_1 _1  23  _4 0 0&lt;br /&gt; 2  2 _46   8 0 0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here we use &lt;code&gt;(((#p2) - 1 ) $ 0)&lt;/code&gt; to generate an array of zeros of the desired size. Then we use &lt;code&gt;(,"1 1)&lt;/code&gt; which is the ',' dyad with a modified rank saying that each element of the left matrix (an array) will be concatenated with the second array (since the second argument is a single dimension array we could have said &lt;code&gt;(,"1 _)&lt;/code&gt; ).&lt;br /&gt;&lt;br /&gt;With the arrays resized we can change the degree of our polynomial array. In order to do this we're going to use the &lt;code&gt;'|.'&lt;/code&gt; dyad which let's you rotate  an array an specified amount of positions. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt; &lt;br /&gt;   1 |.  1 2 3&lt;br /&gt;2 3 1&lt;br /&gt;   _1 |.  1 2 3&lt;br /&gt;3 1 2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As shown in the example, by specifying a positive number the array will be rotated to the left and a negative number to the right.&lt;br /&gt;&lt;br /&gt;Now the question is, how to rotate each element of the polynomial array by a different element count? Before showing that we're going to introduce the 'i.' primitive which lets you create an array of with a sequence of numbers for example, to create an array of 10 numbers (starting with 0) we write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   i. 10&lt;br /&gt;0 1 2 3 4 5 6 7 8 9&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can use this primitive in conjunction with the rotate primitive to say &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   m =:    (p1 (*"_ 0) p2) (,"1 1) ( ((#p2) - 1 ) $ 0)&lt;br /&gt;   i. #p2&lt;br /&gt;0 1 2&lt;br /&gt;   _1 * i. #p2&lt;br /&gt;0 _1 _2&lt;br /&gt;   (_1 * i. #p2) (|."0 1) m&lt;br /&gt;_3 _3 69 _12   0 0&lt;br /&gt; 0 _1 _1  23  _4 0&lt;br /&gt; 0  0  2   2 _46 8&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see we use the array generated by  &lt;code&gt;(_1 * i. #p2)&lt;/code&gt; to specify how many positions are we moving. We apply the change the rank of '|.' by saying &lt;code&gt;(|."0 1)&lt;/code&gt; which means apply '|.' for each single cell of the left array to each row of the right array.&lt;br /&gt;&lt;br /&gt;The previous step generated an array polynomials to be summed. So the only thing left is to generate the final polynomial. In order to do this we use the '+/' dyad which let's use sum the contents of an array. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   +/ 5 3 4 1&lt;br /&gt;13&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can apply +/ to any array and J will do the operation as expected.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   +/ (_1 * i. #p2) (|."0 1) m&lt;br /&gt;_3 _4 70 13 _50 8&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As a work around I'm appending a zero row to this matrix, just in case the p2 array is a 0 degree polynomial.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   +/ ((_1 * i. #p2) (|."0 1) m) , 0&lt;br /&gt;_3 _4 70 13 _50 8&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And that's it we have the complete process for multiplying the array.&lt;br /&gt;&lt;br /&gt;3. Create the function&lt;br /&gt;&lt;br /&gt;Now putting all the elements described above we can put together the polynomial multiplication dyad:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;polymulti =: dyad : '+/ (((_1 * i. #y) (|. "0 1) ((x (*"_ 0) y) (,"1 1) (((#y) - 1) $ 0))) , 0)'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The 'x' and 'y' names are the implicit names of the left and right operands. &lt;br /&gt;&lt;br /&gt;We can use it with any pair of polynomials. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   2 34 3 polymulti 4 3&lt;br /&gt;8 142 114 9&lt;br /&gt;   2 34 3 polymulti 4 0 3&lt;br /&gt;8 136 18 102 9&lt;br /&gt;   2 34 3 polymulti 1&lt;br /&gt;2 34 3&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4. Use the polynomials&lt;br /&gt;&lt;br /&gt;J already has support for polynomials inside the library. For example by using the 'p.' we can get an evaluation of a given polynomial.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;   3 4 5 p. 34&lt;br /&gt;5919&lt;br /&gt;   3 + (4*34) + (5*34*34)&lt;br /&gt;5919&lt;br /&gt;   _2 p. 34&lt;br /&gt;_2&lt;br /&gt;   (5 3 _2 polymulti 3 0 0 _2)&lt;br /&gt;15 9 _6 _10 _6 4&lt;br /&gt;   (5 3 _2 polymulti 3 0 0 _2) p. 3&lt;br /&gt;204&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Final words&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;It was very interesting to read about J. It offers a different perspective on programming which is definitely worth studying. I have to admit it was difficult at the beginning because of the number of concepts to learn ( only a couple are presented in this post) and the syntax . For future posts I'm going to try to explore more J features.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-3522162764565834734?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/3522162764565834734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=3522162764565834734' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/3522162764565834734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/3522162764565834734'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/10/quick-look-at-j.html' title='A quick look at J'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-7845811072760700492</id><published>2009-10-06T05:20:00.004-06:00</published><updated>2009-10-06T05:37:50.112-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>AS3 Getter/Setter support in AbcExplorationLib</title><content type='html'>Recently I added initial support for reading and writing &lt;a href="http://en.wikipedia.org/wiki/ActionScript"&gt;AS3/Avm2&lt;/a&gt; getters and setters to &lt;a href="http://abcexplorationlib.codeplex.com"&gt;AbcExplorationLib&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Given the following ActionScript class:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; Complex {&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;var&lt;/span&gt; radius:Number;&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;var&lt;/span&gt; angle:Number;&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; Complex(ar:Number,aa:Number):&lt;span class="srckeyw"&gt;void&lt;/span&gt; {&lt;br /&gt;      radius = ar;&lt;br /&gt;      angle = aa;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; &lt;span class="srckeyw"&gt;set&lt;/span&gt; imaginary(newImaginary:Number):&lt;span class="srckeyw"&gt;void&lt;/span&gt; &lt;br /&gt;   {&lt;br /&gt;      &lt;span class="srckeyw"&gt;var&lt;/span&gt; oldReal = this.real;&lt;br /&gt;      angle = Math.atan(newImaginary/oldReal);&lt;br /&gt;      radius = Math.sqrt(oldReal*oldReal + newImaginary*newImaginary);&lt;br /&gt;   }&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; &lt;span class="srckeyw"&gt;get&lt;/span&gt; imaginary():Number&lt;br /&gt;   {&lt;br /&gt;          return radius*Math.sin(angle);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; &lt;span class="srckeyw"&gt;set&lt;/span&gt; real(newReal:Number):&lt;span class="srckeyw"&gt;void&lt;/span&gt; &lt;br /&gt;   {&lt;br /&gt;      &lt;span class="srckeyw"&gt;var&lt;/span&gt; oldImaginary = this.real;&lt;br /&gt;      angle = Math.atan(oldImaginary/newReal);&lt;br /&gt;      radius = Math.sqrt(newReal*newReal + oldImaginary*oldImaginary);&lt;br /&gt;   }&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; &lt;span class="srckeyw"&gt;get&lt;/span&gt; real():Number&lt;br /&gt;   {&lt;br /&gt;          return radius*Math.cos(angle);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We compile it using the Flex SDK:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;java -jar c:\flexsdk\lib\asc.jar complexclasstest.as&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then we can load it using the library:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Microsoft F# Interactive, (c) Microsoft Corporation, All Rights Reserved&lt;br /&gt;F# Version 1.9.6.16, compiling for .NET Framework Version v2.0.50727&lt;br /&gt;&lt;br /&gt;Please send bug reports to fsbugs@microsoft.com&lt;br /&gt;For help type #help;;&lt;br /&gt;&lt;br /&gt;&amp;gt; #r "abcexplorationlib.dll";;&lt;br /&gt;&lt;br /&gt;--&amp;gt; Referenced 'abcexplorationlib.dll'&lt;br /&gt;&lt;br /&gt;&amp;gt; open System.IO;;&lt;br /&gt;&amp;gt; open Langexplr.Abc;;&lt;br /&gt;&amp;gt; let f = using (new FileStream("complexclasstest.abc",FileMode.Open)) (fun s -&amp;gt; AvmAbcFile.Create(s));;&lt;br /&gt;&lt;br /&gt;val f : AvmAbcFile&lt;br /&gt;&lt;br /&gt;&amp;gt; let complexClass = List.hd f.Classes;;&lt;br /&gt;&lt;br /&gt;val complexClass : AvmClass&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;gt; complexClass.Properties |&amp;gt; List.map (fun p -&amp;gt; p.Name);;&lt;br /&gt;val it : QualifiedName list =&lt;br /&gt;  [CQualifiedName (Ns ("",PackageNamespace),"real");&lt;br /&gt;   CQualifiedName (Ns ("",PackageNamespace),"imaginary")]&lt;br /&gt;&amp;gt; let realGetter =  complexClass.Properties |&amp;gt; List.map (fun p -&amp;gt; p.Getter.Value) |&amp;gt; List.hd;;&lt;br /&gt;&lt;br /&gt;val realGetter : AvmMemberMethod:&lt;br /&gt;&amp;gt; realGetter.Method.Body.Value.Instructions |&amp;gt; Array.map (fun x -&amp;gt; x.Name);;&lt;br /&gt;val it : string array =&lt;br /&gt;  [|"getlocal_0"; "pushscope"; "getlocal_0"; "getproperty";&lt;br /&gt;    "findpropertystrict"; "getproperty"; "getlocal_0"; "getproperty";&lt;br /&gt;    "callprop"; "multiply"; "returnvalue"|]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The library can be found &lt;a href="http://abcexplorationlib.codeplex.com/SourceControl/ListDownloadableCommits.aspx"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-7845811072760700492?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/7845811072760700492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=7845811072760700492' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7845811072760700492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7845811072760700492'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/10/as3-gettersetter-support-in.html' title='AS3 Getter/Setter support in AbcExplorationLib'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-1377771037446369131</id><published>2009-10-01T05:16:00.007-06:00</published><updated>2009-10-01T06:03:48.021-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><title type='text'>Parsing Javascript using Newspeak parsing combinators</title><content type='html'>I've been working on a parser for Javascript/Ecmascript using &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak&lt;/a&gt; parsing combinators. The parser is based on the grammar presented in the &lt;a href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf"&gt;ECMAScript Language Specification [PDF]&lt;/a&gt; document. It is still incomplete, however it can parse simple statements.&lt;br /&gt;&lt;br /&gt;The grammar looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; JSGrammar = ExecutableGrammar (&lt;br /&gt;&lt;span class="srccomment"&gt;"Experiment for JS grammar based on the description from http://www.ecma-international.org/publications/standards/Ecma-262.htm"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;     doubleQuote = (char: &lt;span class="srctext"&gt;$"&lt;/span&gt;).&lt;br /&gt;     backslash = (char: &lt;span class="srctext"&gt;$\&lt;/span&gt;).&lt;br /&gt;     str = doubleQuote,((backslash, ( char: &lt;span class="srctext"&gt;$"&lt;/span&gt; ))   | &lt;br /&gt;                        (backslash, ( char: &lt;span class="srctext"&gt;$/&lt;/span&gt; ))   |&lt;br /&gt;                        (backslash, backslash)      |&lt;br /&gt;                        (backslash, ( char: &lt;span class="srctext"&gt;$r&lt;/span&gt; ))   |&lt;br /&gt;                        (backslash, ( char: &lt;span class="srctext"&gt;$n&lt;/span&gt; ))   |&lt;br /&gt;                        (backslash, ( char: &lt;span class="srctext"&gt;$t&lt;/span&gt; ))   |&lt;br /&gt;                        (charExceptFor: &lt;span class="srctext"&gt;$"&lt;/span&gt;)) star, doubleQuote.&lt;br /&gt;     string = tokenFor: str.&lt;br /&gt;   &lt;br /&gt;     tilde = char: &lt;span class="srctext"&gt;$~&lt;/span&gt;.&lt;br /&gt;     exclamation = char: &lt;span class="srctext"&gt;$!&lt;/span&gt;.&lt;br /&gt;     starChar = char: &lt;span class="srctext"&gt;$*&lt;/span&gt;.&lt;br /&gt;     slash = char: &lt;span class="srctext"&gt;$/&lt;/span&gt;.&lt;br /&gt;     modulo = char: &lt;span class="srctext"&gt;$%&lt;/span&gt;.&lt;br /&gt;     pipe = char: &lt;span class="srctext"&gt;$|&lt;/span&gt;.&lt;br /&gt;     amp = char: &lt;span class="srctext"&gt;$&amp;&lt;/span&gt;.&lt;br /&gt;     cir = char: &lt;span class="srctext"&gt;$^&lt;/span&gt;.&lt;br /&gt;     question = char: &lt;span class="srctext"&gt;$?&lt;/span&gt;.&lt;br /&gt;     colon = char: &lt;span class="srctext"&gt;$:&lt;/span&gt;.&lt;br /&gt;     semicolon = char: &lt;span class="srctext"&gt;$;&lt;/span&gt;.&lt;br /&gt;   &lt;br /&gt;     negSign = (char: &lt;span class="srctext"&gt;$-&lt;/span&gt;).&lt;br /&gt;     plusSign = (char: &lt;span class="srctext"&gt;$+&lt;/span&gt;).&lt;br /&gt;     digit = (charBetween: &lt;span class="srctext"&gt;$0&lt;/span&gt; and: &lt;span class="srctext"&gt;$9&lt;/span&gt;).&lt;br /&gt;     dot = (char: &lt;span class="srctext"&gt;$.&lt;/span&gt; ) .&lt;br /&gt;     lt = char: &lt;span class="srctext"&gt;$&amp;&lt;/span&gt;lt;.&lt;br /&gt;     gt = char: &lt;span class="srctext"&gt;$&amp;&lt;/span&gt;gt;.&lt;br /&gt;     eq = char: &lt;span class="srctext"&gt;$=&lt;/span&gt;.&lt;br /&gt;     num = negSign opt, digit, digit star, dot opt,digit star, ((char: &lt;span class="srctext"&gt;$e&lt;/span&gt;) | (char: &lt;span class="srctext"&gt;$E&lt;/span&gt;)) opt, (plusSign | negSign) opt,digit star.&lt;br /&gt;     number = tokenFor: num.&lt;br /&gt;&lt;br /&gt;     tQuestion = tokenFor: question.&lt;br /&gt;     tColon = tokenFor: colon.&lt;br /&gt;     tplusSign = tokenFor: plusSign.&lt;br /&gt;     tnegSign = tokenFor: negSign.&lt;br /&gt;     tmodulo = tokenFor: modulo.&lt;br /&gt;     tslash = tokenFor: slash.&lt;br /&gt;     tstarChar = tokenFor: starChar.&lt;br /&gt;     texclamation = tokenFor:exclamation.&lt;br /&gt;     tdot = tokenFor:dot.&lt;br /&gt;     tLt = tokenFor: lt.&lt;br /&gt;     tGt = tokenFor: gt.&lt;br /&gt;     tEq = tokenFor: eq.   &lt;br /&gt;     tAmp = tokenFor: amp.&lt;br /&gt;     tPipe = tokenFor: pipe.&lt;br /&gt;     tCir = tokenFor: cir.&lt;br /&gt;     tSlash = tokenFor: slash.&lt;br /&gt;     tSemicolon = tokenFor: semicolon.&lt;br /&gt;&lt;br /&gt;     tStarEq = tstarChar,eq.&lt;br /&gt;     tModEq = tmodulo,eq.&lt;br /&gt;     tSlashEq = tSlash,eq.&lt;br /&gt;     tPlusEq = tplusSign,eq.&lt;br /&gt;     tMinusEq = tnegSign,eq.&lt;br /&gt;     tAmpAmp = tAmp,amp.&lt;br /&gt;     tPipePipe = tPipe,pipe.&lt;br /&gt;     tLtEq = tLt,eq.&lt;br /&gt;     tGtEq = tGt,eq.&lt;br /&gt;     tleftShift = tLt,lt.&lt;br /&gt;     trightShift = tGt,gt.&lt;br /&gt;     tsRightShift = tGt,gt,gt. &lt;br /&gt;     tEqEq = tEq,eq.&lt;br /&gt;     tEqEqEq = tEq,eq,eq.&lt;br /&gt;     tNotEq = texclamation,eq.&lt;br /&gt;     tNotEqEq = texclamation,eq,eq.&lt;br /&gt;     tleftShiftEq = tleftShift,eq.&lt;br /&gt;     trightShiftEq = trightShift,eq.&lt;br /&gt;     tsRightShiftEq = tsRightShift,eq.&lt;br /&gt;     tAmpEq = tAmp,eq.&lt;br /&gt;     tPipeEq = tPipe,eq.&lt;br /&gt;     tCirEq = tCir,eq.&lt;br /&gt;&lt;br /&gt;     lineTerminator = (char: (Character lf)) | (char: (Character cr)).&lt;br /&gt;&lt;br /&gt;     regularExpressionLiteral = &lt;br /&gt;                     tslash, &lt;br /&gt;                     (  ((backslash, ( charExceptForCharIn: { (Character lf).  (Character cr). })) |&lt;br /&gt;                      (charExceptForCharIn: { (Character lf).  (Character cr). &lt;span class="srctext"&gt;$/&lt;/span&gt;.})) plus),&lt;br /&gt;                      slash, (identifierStart star).&lt;br /&gt;&lt;br /&gt;     leftparen = tokenFromChar: &lt;span class="srctext"&gt;$(&lt;/span&gt;.&lt;br /&gt;     rightparen =tokenFromChar: &lt;span class="srctext"&gt;$)&lt;/span&gt;.   &lt;br /&gt;   &lt;br /&gt;     leftbrace = tokenFromChar: &lt;span class="srctext"&gt;${&lt;/span&gt;.&lt;br /&gt;     rightbrace =tokenFromChar: &lt;span class="srctext"&gt;$}&lt;/span&gt;.&lt;br /&gt;     comma = tokenFromChar: &lt;span class="srctext"&gt;$,&lt;/span&gt;.&lt;br /&gt;     propertyName = string | identifier | number.&lt;br /&gt;     propertyNameAndValue = propertyName,tColon,value.&lt;br /&gt;     obj =  leftbrace,  (propertyNameAndValue starSeparatedBy: comma),rightbrace.&lt;br /&gt;     object =  obj.&lt;br /&gt;&lt;br /&gt;     leftbracket = tokenFromChar: &lt;span class="srctext"&gt;$[&lt;/span&gt;.&lt;br /&gt;     rightbracket = tokenFromChar: &lt;span class="srctext"&gt;$]&lt;/span&gt;.&lt;br /&gt;     arr = leftbracket, (value starSeparatedBy: comma), rightbracket.&lt;br /&gt;     array = tokenFor: arr.&lt;br /&gt;&lt;br /&gt;     comment = (slash,starChar,blockCommentBody,starChar,slash) | (slash,slash, lineCommentBody).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;     ttrue = tokenFromSymbol: &lt;span class="srctext"&gt;#true&lt;/span&gt;.&lt;br /&gt;     tfalse = tokenFromSymbol: &lt;span class="srctext"&gt;#false&lt;/span&gt;.&lt;br /&gt;     null = tokenFromSymbol: &lt;span class="srctext"&gt;#null&lt;/span&gt;.&lt;br /&gt;     function = tokenFromSymbol: &lt;span class="srctext"&gt;#function&lt;/span&gt;.&lt;br /&gt;     tnew = tokenFromSymbol: &lt;span class="srctext"&gt;#new&lt;/span&gt;.&lt;br /&gt;     break = tokenFromSymbol: &lt;span class="srctext"&gt;#break&lt;/span&gt;.&lt;br /&gt;     case = tokenFromSymbol: &lt;span class="srctext"&gt;#case&lt;/span&gt;.&lt;br /&gt;     catch = tokenFromSymbol: &lt;span class="srctext"&gt;#catch&lt;/span&gt;.&lt;br /&gt;     continue = tokenFromSymbol: &lt;span class="srctext"&gt;#continue&lt;/span&gt;.&lt;br /&gt;     default = tokenFromSymbol: &lt;span class="srctext"&gt;#default&lt;/span&gt;.&lt;br /&gt;     delete = tokenFromSymbol: &lt;span class="srctext"&gt;#delete&lt;/span&gt;.&lt;br /&gt;     do = tokenFromSymbol: &lt;span class="srctext"&gt;#do&lt;/span&gt;.&lt;br /&gt;     else = tokenFromSymbol: &lt;span class="srctext"&gt;#else&lt;/span&gt;.&lt;br /&gt;     finally = tokenFromSymbol: &lt;span class="srctext"&gt;#finally&lt;/span&gt;.&lt;br /&gt;     for = tokenFromSymbol: &lt;span class="srctext"&gt;#for&lt;/span&gt;.&lt;br /&gt;     if = tokenFromSymbol: &lt;span class="srctext"&gt;#if&lt;/span&gt;.&lt;br /&gt;     in = tokenFromSymbol: &lt;span class="srctext"&gt;#in&lt;/span&gt;.&lt;br /&gt;     instanceof = tokenFromSymbol: &lt;span class="srctext"&gt;#instanceof&lt;/span&gt;.&lt;br /&gt;     return = tokenFromSymbol: &lt;span class="srctext"&gt;#return&lt;/span&gt;.&lt;br /&gt;     switch = tokenFromSymbol: &lt;span class="srctext"&gt;#switch&lt;/span&gt;.&lt;br /&gt;     this = tokenFromSymbol: &lt;span class="srctext"&gt;#this&lt;/span&gt;.&lt;br /&gt;     throw = tokenFromSymbol: &lt;span class="srctext"&gt;#throw&lt;/span&gt;.&lt;br /&gt;     try = tokenFromSymbol: &lt;span class="srctext"&gt;#try&lt;/span&gt;.&lt;br /&gt;     typeof  = tokenFromSymbol: &lt;span class="srctext"&gt;#typeof&lt;/span&gt;.&lt;br /&gt;     var = tokenFromSymbol: &lt;span class="srctext"&gt;#var&lt;/span&gt;.&lt;br /&gt;     void = tokenFromSymbol: &lt;span class="srctext"&gt;#void&lt;/span&gt;.&lt;br /&gt;     while = tokenFromSymbol: &lt;span class="srctext"&gt;#while&lt;/span&gt;.&lt;br /&gt;     with = tokenFromSymbol: &lt;span class="srctext"&gt;#with&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt; &lt;br /&gt;     letter = (charBetween: &lt;span class="srctext"&gt;$a&lt;/span&gt; and: &lt;span class="srctext"&gt;$z&lt;/span&gt;) | (charBetween: &lt;span class="srctext"&gt;$A&lt;/span&gt; and: &lt;span class="srctext"&gt;$Z&lt;/span&gt;).&lt;br /&gt;     identifierStart =  letter | (char: &lt;span class="srctext"&gt;$$&lt;/span&gt;) | (char: &lt;span class="srctext"&gt;$_&lt;/span&gt;).&lt;br /&gt;     identifier = accept: (tokenFor: (identifierStart), (identifierStart | digit) star) ifNotIn: keywords .&lt;br /&gt;&lt;br /&gt;     value =  assignmentExpression .      &lt;br /&gt;  &lt;br /&gt;     literal  = null | ttrue | tfalse | number | string |  regularExpressionLiteral.&lt;br /&gt;&lt;br /&gt;     primaryexpression  = this |  literal | identifier | array | object | parenthesized.&lt;br /&gt;&lt;br /&gt;     parenthesized = leftparen,expression,rightparen.&lt;br /&gt;&lt;br /&gt;     functionexpression = function , identifier opt, &lt;br /&gt;                                       leftparen,formalParameterList , rightparen ,&lt;br /&gt;                                       leftbrace,sourceElements,rightbrace.&lt;br /&gt;     formalParameterList = identifier starSeparatedBy: comma. &lt;br /&gt;&lt;br /&gt;     memberexpression =   (simplememberexpression  ),&lt;br /&gt;                                         (( leftbracket, expression, rightbracket) | ( tdot, identifier)) star.&lt;br /&gt;     &lt;br /&gt;     simplememberexpression = primaryexpression | &lt;br /&gt;                                               functionexpression  |                        &lt;br /&gt;                                                simpleNewExpression.&lt;br /&gt;     simpleNewExpression = tnew,memberexpression, arguments.&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;  &lt;br /&gt;     callExpression =  (simplememberexpression  ),&lt;br /&gt;                       ( arguments |&lt;br /&gt;                         ( leftbracket, expression, rightbracket) | &lt;br /&gt;                         ( tdot, identifier)  ) star.&lt;br /&gt;     simpleCallExpression = memberexpression , arguments.&lt;br /&gt;     arguments = leftparen ,&lt;br /&gt;                 (assignmentExpression, (comma, assignmentExpression) star) opt, &lt;br /&gt;                 rightparen.&lt;br /&gt;&lt;br /&gt;     newExpression = memberexpression | simpleNewMemberExpression.&lt;br /&gt;     simpleNewMemberExpression = tnew, memberexpression.&lt;br /&gt; &lt;br /&gt;     plusPlus = plusSign,plusSign.&lt;br /&gt;     minusMinus = negSign,negSign.&lt;br /&gt;&lt;br /&gt;     leftHandSideExpression = callExpression | newExpression  .&lt;br /&gt;     postfixExpression = leftHandSideExpression , &lt;br /&gt;                          ((plusPlus | minusMinus) star).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;     unaryExpression = postfixExpression | complexUnaryExpression.&lt;br /&gt;&lt;br /&gt;     complexUnaryExpression = &lt;br /&gt;           (typeof, unaryExpression) |&lt;br /&gt;           (delete, unaryExpression) | &lt;br /&gt;           (void, unaryExpression) | &lt;br /&gt;           (plusPlus, unaryExpression) |&lt;br /&gt;           (minusMinus, unaryExpression) |&lt;br /&gt;           ((tokenFor: ( plusSign | negSign | tilde | exclamation )), unaryExpression).&lt;br /&gt;&lt;br /&gt;     multiplicativeExpression = &lt;br /&gt;              unaryExpression, ((tstarChar | tslash | tmodulo), unaryExpression) star.     &lt;br /&gt;&lt;br /&gt;     additiveExpression = &lt;br /&gt;              multiplicativeExpression, ((tplusSign | tnegSign), multiplicativeExpression) star. &lt;br /&gt;&lt;br /&gt;     shiftExpression =  &lt;br /&gt;             additiveExpression,  ((tsRightShift | tleftShift |  trightShift), additiveExpression) star.&lt;br /&gt;      &lt;br /&gt;     relationalExpression =&lt;br /&gt;            shiftExpression, ((  tLtEq | tGtEq | tLt | tGt | instanceof | in) , shiftExpression)  star.&lt;br /&gt;&lt;br /&gt;     relationalExpressionNoIn =&lt;br /&gt;            shiftExpression, ((  tLtEq | tGtEq | tLt | tGt | instanceof ) , shiftExpression)  star. &lt;br /&gt;&lt;br /&gt;     equalityExpression =&lt;br /&gt;            relationalExpression, ((tEqEqEq | tEqEq | tNotEqEq | tNotEq ), relationalExpression) star.&lt;br /&gt;&lt;br /&gt;     equalityExpressionNoIn =&lt;br /&gt;            relationalExpressionNoIn, ((tEqEqEq | tEqEq | tNotEqEq | tNotEq ), relationalExpressionNoIn) star.&lt;br /&gt;&lt;br /&gt;     bitwiseANDExpression =&lt;br /&gt;           equalityExpression,(tAmp, equalityExpression) star.&lt;br /&gt;&lt;br /&gt;     bitwiseANDExpressionNoIn =&lt;br /&gt;           equalityExpressionNoIn,(tAmp, equalityExpressionNoIn) star.&lt;br /&gt;&lt;br /&gt;     bitwiseXORExpression =&lt;br /&gt;           bitwiseANDExpression,(tCir, bitwiseANDExpression) star.&lt;br /&gt;&lt;br /&gt;     bitwiseXORExpressionNoIn =&lt;br /&gt;           bitwiseANDExpressionNoIn,(tCir, bitwiseANDExpressionNoIn) star.&lt;br /&gt;&lt;br /&gt;     bitwiseORExpression =&lt;br /&gt;           bitwiseXORExpression,(tPipe, bitwiseXORExpression) star.&lt;br /&gt;&lt;br /&gt;     bitwiseORExpressionNoIn =&lt;br /&gt;           bitwiseXORExpressionNoIn,(tPipe, bitwiseXORExpressionNoIn) star.&lt;br /&gt;&lt;br /&gt;     logicalAndExpression = &lt;br /&gt;           bitwiseORExpression, (tAmpAmp,bitwiseORExpression) star.&lt;br /&gt;&lt;br /&gt;     logicalAndExpressionNoIn = &lt;br /&gt;           bitwiseORExpressionNoIn, (tAmpAmp,bitwiseORExpressionNoIn) star.&lt;br /&gt;&lt;br /&gt;     logicalOrExpression = &lt;br /&gt;           logicalAndExpression, (tPipePipe,logicalAndExpression) star.&lt;br /&gt;&lt;br /&gt;     logicalOrExpressionNoIn = &lt;br /&gt;           logicalAndExpressionNoIn, (tPipePipe,logicalAndExpressionNoIn) star.&lt;br /&gt;&lt;br /&gt;     assignmentOperator = &lt;br /&gt;              tEq | tStarEq | tSlashEq | tModEq | tPlusEq | tMinusEq |&lt;br /&gt;              tleftShiftEq | tsRightShiftEq | trightShiftEq | tAmpEq | tPipeEq |&lt;br /&gt;              tCirEq.&lt;br /&gt; &lt;br /&gt;     conditionalExpression =&lt;br /&gt;            logicalOrExpression, (tQuestion, assignmentExpression,tColon,assignmentExpression) opt.&lt;br /&gt;&lt;br /&gt;     assignmentExpression =    &lt;br /&gt;           conditionalExpression, (assignmentOperator,conditionalExpression) star.&lt;br /&gt;&lt;br /&gt;     conditionalExpressionNoIn =&lt;br /&gt;            logicalOrExpressionNoIn, (tQuestion, assignmentExpressionNoIn,tColon,assignmentExpressionNoIn) opt.&lt;br /&gt;&lt;br /&gt;     assignmentExpressionNoIn =    &lt;br /&gt;           conditionalExpressionNoIn, (assignmentOperator,conditionalExpressionNoIn) star.&lt;br /&gt;&lt;br /&gt;     expression = assignmentExpression, (comma , assignmentExpression) star.&lt;br /&gt;&lt;br /&gt;     expressionNoIn = assignmentExpressionNoIn, (comma , assignmentExpressionNoIn) star.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;     statement = block | variableStatement | emptyStatement | expressionStatement |&lt;br /&gt;                          ifStatement | iterationStatement | withStatement | switchStatement |&lt;br /&gt;                          labelledStatement | tryStatement | throwStatement | &lt;br /&gt;                          breakStatement | returnStatement.&lt;br /&gt;  &lt;br /&gt;     block = leftbrace, statementList , rightbrace.&lt;br /&gt;&lt;br /&gt;     statementList = statement star.&lt;br /&gt;     variableStatement = var, variableDeclarationList, tSemicolon.&lt;br /&gt;&lt;br /&gt;     variableDeclarationList = (variableDeclaration plusSeparatedBy: comma). &lt;br /&gt;     variableDeclaration = identifier, (tEq,assignmentExpression) opt.&lt;br /&gt;&lt;br /&gt;     variableDeclarationListNoIn = (variableDeclarationNoIn plusSeparatedBy: comma). &lt;br /&gt;     variableDeclarationNoIn = identifier, (tEq,assignmentExpressionNoIn) opt.&lt;br /&gt;       &lt;br /&gt;     emptyStatement = tSemicolon.&lt;br /&gt;&lt;br /&gt;     expressionStatement = (((function | leftbrace) not) &amp; expression), tSemicolon.&lt;br /&gt;&lt;br /&gt;     ifStatement = if, leftparen,expression,rightparen,statement,(else,statement) opt.&lt;br /&gt;&lt;br /&gt;     iterationStatement = doStatement | forStatement | forStatementNoVar |  &lt;br /&gt;                                        whileStatement | forInStatement | forInStatementNoVar.&lt;br /&gt;&lt;br /&gt;     doStatement = do, statement, while, leftparen,expression,rightparen,tSemicolon.&lt;br /&gt;&lt;br /&gt;     forStatement = for, leftparen, &lt;br /&gt;                         var, variableDeclarationListNoIn ,&lt;br /&gt;                         tSemicolon,&lt;br /&gt;                         (expression opt),&lt;br /&gt;                         tSemicolon,&lt;br /&gt;                         (expression opt),&lt;br /&gt;                         rightparen, statement.&lt;br /&gt;&lt;br /&gt;      forStatementNoVar = for, leftparen, &lt;br /&gt;                              (expression opt),&lt;br /&gt;                              tSemicolon,&lt;br /&gt;                              (expression opt),&lt;br /&gt;                              tSemicolon,&lt;br /&gt;                              (expression opt),&lt;br /&gt;                              rightparen, statement.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      forInStatement = for, leftparen, &lt;br /&gt;                                       var, variableDeclarationListNoIn ,&lt;br /&gt;                                       in,&lt;br /&gt;                                       expression ,&lt;br /&gt;                                       rightparen, statement.&lt;br /&gt;&lt;br /&gt;      forInStatementNoVar = for, leftparen, &lt;br /&gt;                                       leftHandSideExpression ,&lt;br /&gt;                                       in,&lt;br /&gt;                                       expression ,&lt;br /&gt;                                       rightparen, statement.&lt;br /&gt;      whileStatement = while,leftparen,expression,rightparen,statement.&lt;br /&gt;&lt;br /&gt;      continueStatement = continue, (identifier opt), tSemicolon.&lt;br /&gt;&lt;br /&gt;      breakStatement = break, (identifier opt), tSemicolon.&lt;br /&gt;&lt;br /&gt;      returnStatement = return, (expression opt), tSemicolon.&lt;br /&gt;&lt;br /&gt;      withStatement = with, leftparen, expression ,rightparen, statement.&lt;br /&gt;  &lt;br /&gt;      switchStatement = switch ,leftparen,expression,rightparen, clauseBlock.&lt;br /&gt;&lt;br /&gt;      clauseBlock = leftbrace,(clause star),(defaultClause opt),rightbrace.&lt;br /&gt;&lt;br /&gt;      clause = case, expression, tColon,statementList.&lt;br /&gt;         &lt;br /&gt;      defaultClause = default,tColon, statementList.&lt;br /&gt;&lt;br /&gt;      labelledStatement = identifier,tColon,statement.&lt;br /&gt;        &lt;br /&gt;      throwStatement = throw,expression,tSemicolon.&lt;br /&gt;&lt;br /&gt;      tryStatement = try, block, (catchBlock opt), (finallyBlock opt).&lt;br /&gt;&lt;br /&gt;      catchBlock = catch, leftparen, identifier,rightparen, block.&lt;br /&gt;&lt;br /&gt;      finallyBlock = finally, block.&lt;br /&gt;&lt;br /&gt;      functionDeclaration = function,identifier,&lt;br /&gt;                                     leftparen,formalParameterList,rightparen,&lt;br /&gt;                                     leftbrace,sourceElements,rightbrace.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;      sourceElements = (statement | functionDeclaration ) star.&lt;br /&gt;&lt;br /&gt;      program = sourceElements.&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I really like the way you can separate the grammar from the AST creation (as described in the &lt;a href="http://bracha.org/executableGrammars.pdf"&gt;Executable Grammars[PDF]&lt;/a&gt; paper). As you can see there's no code specified for this purpose. Along with the source code there's is a 'testing AST' and a parser that inherits from this grammar which is used by the unit tests .&lt;br /&gt;&lt;br /&gt;Almost all the grammar was written using the parser combinators from the library. Only &lt;code&gt;charExceptFor:&lt;/code&gt; and &lt;code&gt;accept: ifNotIn:&lt;/code&gt; were created. &lt;br /&gt;&lt;br /&gt;There are still a lot work to do with this parser:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Clean up the code&lt;/li&gt;&lt;li&gt;Work on performance issues&lt;/li&gt;&lt;li&gt;Find a solution for the "Automatic Semicolon Insertion" feature (see section 7.9) of the Ecma document)&lt;/li&gt;&lt;li&gt;Get rid of some repetition (for example the 'NoVar' productions which are also present in the document) &lt;/li&gt;&lt;li&gt;Better AST creation&lt;/li&gt;&lt;li&gt;See if unicode support is possible&lt;/li&gt;&lt;li&gt;More tests!&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;In order to see the result of using this parser I created a little program to display the 'testing AST'. For example:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/SsSYZEL3KkI/AAAAAAAAAPY/ZPDzgcJnGlw/s1600-h/nspkjsparserastvis1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 275px;" src="http://2.bp.blogspot.com/_qePSufqunG4/SsSYZEL3KkI/AAAAAAAAAPY/ZPDzgcJnGlw/s320/nspkjsparserastvis1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5387598610629601858" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The parser with tests and the other code mentioned can be found &lt;a href="http://github.com/ldfallas/newspeakexperiments"&gt;here&lt;/a&gt; .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-1377771037446369131?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/1377771037446369131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=1377771037446369131' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/1377771037446369131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/1377771037446369131'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/10/parsing-javascript-using-newspeak.html' title='Parsing Javascript using Newspeak parsing combinators'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_qePSufqunG4/SsSYZEL3KkI/AAAAAAAAAPY/ZPDzgcJnGlw/s72-c/nspkjsparserastvis1.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-5047320708104945564</id><published>2009-08-03T05:50:00.001-06:00</published><updated>2009-08-03T05:52:07.220-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ironruby'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='dlr'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Creating Dynamic JSON array finders using the DLR</title><content type='html'>One of the things that really impressed me while reading about Ruby on Rails was the use of &lt;a href="http://ruby-doc.org/core/classes/Kernel.html#M005925"&gt;method_missing&lt;/a&gt; to implement &lt;a href="http://guides.rubyonrails.org/active_record_querying.html#dynamic-finders"&gt;dynamic finders&lt;/a&gt;. The technique is described on the &lt;a href="http://blog.hasmanythrough.com/2006/8/13/how-dynamic-finders-work"&gt;"How dynamic filters work"&lt;/a&gt;. In this post I'm going to show a little experiment of creating a similar technique for querying JSON arrays using the .&lt;a href="http://www.codeplex.com/dlr"&gt;NET's Dynamic Language Runtime&lt;/a&gt; infrastructure. &lt;br /&gt;&lt;br /&gt;Code for this post was created using Visual Studio 2010 Beta 1, &lt;a href="http://blog.jimmy.schementi.com/2009/05/ironruby-ctp-for-net-40-beta-1.html"&gt;IronRuby for .NET 4 beta 1&lt;/a&gt; and &lt;a href="http://ironpython.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=27320"&gt;IronPython 2.6 beta 4 for .NET 4&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;JSON.NET&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;For this post I'm using the &lt;a href="http://james.newtonking.com/pages/json-net.aspx"&gt;JSON.NET&lt;/a&gt; library for loading the &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; data. This library  provides several ways of loading JSON data. Here I'll be using a set of predefined classes: &lt;a href="http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_Linq_JObject.htm"&gt;JObject&lt;/a&gt; for JSON objects, &lt;a href="http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_Linq_JArray.htm"&gt;JArray&lt;/a&gt; for arrays, &lt;a href="http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_Linq_JValue.htm"&gt;JValue&lt;/a&gt; for literal values, etc.  All these classes inherit from &lt;a href="http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_Linq_JToken.htm"&gt;JToken&lt;/a&gt;.&lt;br /&gt;Code in this post use the JSON data returned by the &lt;a href="http://apiwiki.twitter.com/Twitter-API-Documentation"&gt;Twitter REST API&lt;/a&gt;. An example of this data:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;[&lt;br /&gt; {&lt;span class="srctext"&gt;"in_reply_to_screen_name"&lt;/span&gt;:null,&lt;br /&gt;  &lt;span class="srctext"&gt;"text"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;  &lt;span class="srctext"&gt;"user"&lt;/span&gt;: { &lt;span class="srctext"&gt;"following"&lt;/span&gt;:null,&lt;br /&gt;            &lt;span class="srctext"&gt;"description"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"screen_name"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"utc_offset"&lt;/span&gt;:0,&lt;br /&gt;            &lt;span class="srctext"&gt;"followers_count"&lt;/span&gt;:10,&lt;br /&gt;            &lt;span class="srctext"&gt;"time_zone"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"statuses_count"&lt;/span&gt;:155,&lt;br /&gt;            &lt;span class="srctext"&gt;"created_at"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"friends_count"&lt;/span&gt;:1,&lt;br /&gt;            &lt;span class="srctext"&gt;"url"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"name"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"notifications"&lt;/span&gt;:null,&lt;br /&gt;            &lt;span class="srctext"&gt;"protected"&lt;/span&gt;:false,&lt;br /&gt;            &lt;span class="srctext"&gt;"verified"&lt;/span&gt;:false,&lt;br /&gt;            &lt;span class="srctext"&gt;"favourites_count"&lt;/span&gt;:0,&lt;br /&gt;            &lt;span class="srctext"&gt;"location"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"id"&lt;/span&gt;: ...,&lt;br /&gt;            ...&lt;br /&gt;  },&lt;br /&gt;  &lt;span class="srctext"&gt;"truncated"&lt;/span&gt;:false,&lt;br /&gt;  &lt;span class="srctext"&gt;"created_at"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;  &lt;span class="srctext"&gt;"in_reply_to_status_id"&lt;/span&gt;:null,&lt;br /&gt;  &lt;span class="srctext"&gt;"in_reply_to_user_id"&lt;/span&gt;:null,&lt;br /&gt;  &lt;span class="srctext"&gt;"favorited"&lt;/span&gt;:false,&lt;br /&gt;  &lt;span class="srctext"&gt;"id"&lt;/span&gt;:...,&lt;br /&gt;  &lt;span class="srctext"&gt;"source"&lt;/span&gt;:&lt;span class="srctext"&gt;"...."&lt;/span&gt;&lt;br /&gt; },&lt;br /&gt;  ...&lt;br /&gt;]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Dynamic queries on JSON data&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Finders will be implemented for JSON arrays. As with Rail's dynamic finders the names of the required fields will be encoded in the name of the invoked method. &lt;br /&gt;&lt;br /&gt;The following C# 4.0 code shows an example of this wrapper class in conjunction with the &lt;a href="http://www.hanselman.com/blog/C4AndTheDynamicKeywordWhirlwindTourAroundNET4AndVisualStudio2010Beta1.aspx"&gt;dynamic&lt;/a&gt; keyword.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;JsonTextReader reader = &lt;span class="srckeyw"&gt;new&lt;/span&gt; JsonTextReader(rdr);&lt;br /&gt;JsonSerializer serializer = &lt;span class="srckeyw"&gt;new&lt;/span&gt; JsonSerializer();&lt;br /&gt;JArray o = (JArray)serializer.Deserialize(reader);&lt;br /&gt;&lt;span class="srckeyw"&gt;dynamic&lt;/span&gt; dArray = &lt;span class="srckeyw"&gt;new&lt;/span&gt; FSDynArrayWrapper(o);&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;string&lt;/span&gt; name = &lt;span class="srctext"&gt;"ldfallas"&lt;/span&gt;;&lt;br /&gt;&lt;span class="srckeyw"&gt;foreach&lt;/span&gt; (&lt;span class="srckeyw"&gt;var&lt;/span&gt; aJObject in dArray.&lt;span style="font-weight:bold;"&gt;FindAllByFavoritedAlsoByUserWithScreen_Name&lt;/span&gt;("false",name))&lt;br /&gt;{&lt;br /&gt;   &lt;span class="srckeyw"&gt;dynamic&lt;/span&gt; tobj = &lt;span class="srckeyw"&gt;new&lt;/span&gt; FSDynJObjectWrapper(aJObject);&lt;br /&gt;   Console.WriteLine("========");&lt;br /&gt;   Console.WriteLine(tobj.user.screen_name);&lt;br /&gt;   Console.Write(&lt;span class="srctext"&gt;"\t'{0}'"&lt;/span&gt;,tobj.text);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A small definition of the syntax used for names is the following.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;method-name&lt;/span&gt; = "FindAllBy" , &lt;br /&gt;              property-name , ("With", property-name)? ,&lt;br /&gt;             ("AlsoBy" property-name , ("With", property-name)? ) *&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;property-name&lt;/span&gt; = &lt;span style="font-style:italic;"&gt;valid json property name&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In order to be more flexible the following syntax will also be allowed:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;method-name&lt;/span&gt; = "find_all_by_" , &lt;br /&gt;              property-name , ("_with_", property-name)? ,&lt;br /&gt;             ("_also_by" property-name , ("_with_", property-name)? ) *&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;property-name&lt;/span&gt; = &lt;span style="font-style:italic;"&gt;valid json property name&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A sample name for this query methods look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;array.FindAllByFavoritedAlsoByUserWithScreen_Name("true","ldfallas")&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This method will accept two parameters and is going to :&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Find all the object elements from the array that has a 'Favorited' property equal to 'true' and also has an object with a 'User' property associated with an object which has a 'Screen_Name' property which is equal to the 'ldfallas'&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Interoperability&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;One of the nice things of using the DLR infrastructure to create this feature, is that it can be used by other DLR languages. The following example is an IronRuby snippet:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;require&lt;/span&gt; &lt;span class="srctext"&gt;'FsDlrJsonExperiments.dll'&lt;/span&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;include&lt;/span&gt; Langexplr::Experiments&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;while&lt;/span&gt; &lt;span class="srckeyw"&gt;true&lt;/span&gt; &lt;span class="srckeyw"&gt;do&lt;/span&gt;&lt;br /&gt;  print &lt;span class="srctext"&gt;"Another try\n"&lt;/span&gt;&lt;br /&gt;  str = System::Net::WebClient.new().download_string(&lt;span class="srctext"&gt;"http://twitter.com/statuses/public_timeline.json"&lt;/span&gt;)&lt;br /&gt;  json = FSDynArrayWrapper.CreateFromReader(System::IO::StringReader.new(str))&lt;br /&gt;&lt;br /&gt;  &lt;span class="srckeyw"&gt;for&lt;/span&gt; i &lt;span class="srckeyw"&gt;in&lt;/span&gt; json.find_all_by_user_with_time_zone(&lt;span class="srctext"&gt;'Central America'&lt;/span&gt;) &lt;span class="srckeyw"&gt;do&lt;/span&gt;&lt;br /&gt;     print i.to_string()&lt;br /&gt;  &lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;  sleep(5)&lt;br /&gt;&lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The following IronPython code shows a little example of this wrapper class.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;fReader = StreamReader(GetTwitterPublicTimeline())&lt;br /&gt;jReader  = JsonTextReader(fReader)&lt;br /&gt;serializer = JsonSerializer()&lt;br /&gt;&lt;br /&gt;json = FSDynArrayWrapper( serializer.Deserialize(jReader) )&lt;br /&gt;&lt;br /&gt;for i in json.FindAllByFavoritedAlsoByUserWithScreen_Name("false","ldfallas"):&lt;br /&gt;   print i&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Implementation&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In order to implement the functionality presented here, the &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.idynamicmetaobjectprovider%28VS.100%29.aspx"&gt;IDynamicMetaObjectProvider&lt;/a&gt; interface and the &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicmetaobject%28VS.100%29.aspx"&gt;DynamicMetaObject&lt;/a&gt; class were used. By using these we can generate the code for the call site as a &lt;a href="http://msdn.microsoft.com/en-us/library/bb397951.aspx"&gt;expression tree&lt;/a&gt;. For more information on how to use this interface see&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Getting Started with the DLR as a Library Author&lt;/span&gt; document  (available &lt;a href="http://dlr.codeplex.com/Wiki/View.aspx?title=Docs%20and%20specs"&gt;here&lt;/a&gt;) .&lt;br /&gt;&lt;br /&gt;The code generated to do the filtering is an expression which uses the &lt;code&gt;Where&lt;/code&gt; method from &lt;a href="http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx"&gt;System.Linq.Enumerable&lt;br /&gt;&lt;/a&gt;. The generated expression written in source using a pseudo C# looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;{&lt;br /&gt;  object tmp;&lt;br /&gt;  array.Where(c =&gt; (((c Is JObject) &amp;&amp; &lt;br /&gt;                     CompareHelper(&lt;br /&gt;                         GetJObjectPropertyCI(((JObject)c), &lt;span class="srctext"&gt;"Favorited"&lt;/span&gt;), &lt;br /&gt;                         &lt;span class="srctext"&gt;"true"&lt;/span&gt;)) &lt;br /&gt;                    &amp;&amp; &lt;br /&gt;                    ((((tmp = GetJObjectPropertyCI(((JObject)c), &lt;span class="srctext"&gt;"User"&lt;/span&gt;)) As JObject) != null) &amp;&amp; &lt;br /&gt;                     CompareHelper(&lt;br /&gt;                         GetJObjectPropertyCI(((JObject)tmp), &lt;span class="srctext"&gt;"Screen_Name"&lt;/span&gt;), &lt;br /&gt;                         &lt;span class="srctext"&gt;"ldfallas"&lt;/span&gt;))))&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where &lt;code&gt;GetJObjectPropertyCI&lt;/code&gt; is a helper method that gets a property from a &lt;code&gt;JObject&lt;/code&gt; by case-intensive name . And &lt;code&gt;CompareHelper&lt;/code&gt; is a helper method to do the comparison.&lt;br /&gt;&lt;br /&gt;The implementation for &lt;code&gt;FSDynArrayWrapper&lt;/code&gt; was written in F#. Mainly because it's a nice language to implement this kind of features. However there's no easy way to consume this feature using F# since it doesn't use the DLR.&lt;br /&gt;&lt;br /&gt;Here's the definition:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; FSDynArrayWrapper(a:JArray) =   &lt;br /&gt;   &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.array &lt;span class="srckeyw"&gt;with&lt;/span&gt; &lt;span class="srckeyw"&gt;get&lt;/span&gt;() = a&lt;br /&gt;   static &lt;span class="srckeyw"&gt;member&lt;/span&gt; CreateFromReader(stream : System.IO.TextReader) =&lt;br /&gt;     ...&lt;br /&gt;   static &lt;span class="srckeyw"&gt;member&lt;/span&gt; CreateFromFile(fileName:string) =&lt;br /&gt;     ... &lt;br /&gt;   &lt;span class="srckeyw"&gt;interface&lt;/span&gt; IDynamicMetaObjectProvider &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;      &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.GetMetaObject( parameter : Expression) : DynamicMetaObject =&lt;br /&gt;         FSDynArrayWrapperMetaObject(parameter,this)  :&amp;gt; DynamicMetaObject&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the interesting part is in the implementation of &lt;code&gt;FSDynArrayWrapperMetaObject&lt;/code&gt;. The &lt;code&gt;CreateFromReader&lt;/code&gt; and &lt;code&gt;CreateFromFile&lt;/code&gt; methods are only utility methods to load data from a document. &lt;br /&gt;&lt;br /&gt;The implementation of &lt;code&gt;FSDynArrayWrapperMetaObject&lt;/code&gt; looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; FSDynArrayWrapperMetaObject(expression : Expression, value: System.Object) = &lt;br /&gt;   &lt;span class="srckeyw"&gt;inherit&lt;/span&gt; DynamicMetaObject(expression,BindingRestrictions.Empty,value) &lt;br /&gt;   &lt;br /&gt;   ...&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;override&lt;/span&gt; this.BindInvokeMember(binder : InvokeMemberBinder, args: DynamicMetaObject &lt;span class="srckeyw"&gt;array&lt;/span&gt;) =&lt;br /&gt;     &lt;span class="srckeyw"&gt;match&lt;/span&gt; QueryInfo.GetQueryElements(binder.Name) &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;     | Some( elements ) -&amp;gt;&lt;br /&gt;         (&lt;span class="srckeyw"&gt;new&lt;/span&gt; DynamicMetaObject(&lt;br /&gt;             this.GenerateCodeForBinder(&lt;br /&gt;                 elements, &lt;br /&gt;                 Array.map &lt;br /&gt;                   (fun (v:DynamicMetaObject) -&amp;gt; &lt;br /&gt;                      Expression.Constant(v.Value.ToString()) :&amp;gt; Expression) args),&lt;br /&gt;             binder.FallbackInvokeMember(this,args).Restrictions))&lt;br /&gt;     | None -&amp;gt; base.BindInvokeMember(binder,args)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;BindInvokeMember&lt;/code&gt; creates the expression tree for the code that will be executed for a given invocation of a dynamic finder method.  Here the &lt;code&gt;QueryInfo.GetQueryElements&lt;/code&gt; method is called to extract the elements of the name as described above. The value returned by this method is &lt;code&gt;QueryElement list option&lt;/code&gt; where:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;type QueryElement =&lt;br /&gt;  | ElementQuery of string&lt;br /&gt;  | SubElementQuery of string * string&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ElementQuery&lt;/code&gt; specifies the "Favorited" part in &lt;code&gt;FindAllBy&lt;span style="font-weight:bold;"&gt;Favorited&lt;/span&gt;AlsoByUserWithScreen&lt;/code&gt; and the &lt;code&gt;SubElementQuery&lt;/code&gt; belongs to the "ByUserWithScreen" part in &lt;code&gt;FindAllByFavoritedAlsoBy&lt;span style="font-weight:bold;"&gt;UserWithScreen&lt;/span&gt;&lt;/code&gt; .&lt;br /&gt;&lt;br /&gt;If the name of the invoked method corresponds is a supported name for a finder, the &lt;code&gt;GenerateCodeForBinder&lt;/code&gt; is called to generate the expression tree. The last argument of this method is a collection of the arguments provided for this invocation.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;member&lt;/span&gt; this.GenerateCodeForBinder(elements, arguments : Expression &lt;span class="srckeyw"&gt;array&lt;/span&gt;) =&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; whereParameter = Expression.Parameter(typeof&amp;lt;JToken&amp;gt;, &lt;span class="srctext"&gt;"c"&lt;/span&gt;) &lt;span class="srckeyw"&gt;in&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; tmpVar = Expression.Parameter(typeof&amp;lt;JToken&amp;gt;, &lt;span class="srctext"&gt;"tmp"&lt;/span&gt;) &lt;span class="srckeyw"&gt;in&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; whereMethodInfo =&lt;br /&gt;         (typeof&amp;lt;System.Linq.Enumerable&amp;gt;).GetMethods() &lt;br /&gt;                 |&amp;gt; Seq.filter (fun (m:MethodInfo) -&amp;gt; m.Name = &lt;span class="srctext"&gt;"Where"&lt;/span&gt; &amp;amp;&amp;amp; (m.GetParameters().Length = 2))&lt;br /&gt;                 |&amp;gt; Seq.map (fun (m:MethodInfo) -&amp;gt; m.MakeGenericMethod(typeof&amp;lt;JToken&amp;gt;))&lt;br /&gt;                 |&amp;gt; Seq.hd&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; queryElementsConditions =              &lt;br /&gt;        elements &lt;br /&gt;           |&amp;gt; Seq.zip arguments&lt;br /&gt;           |&amp;gt; Seq.map &lt;br /&gt;                  (fun (argument,queryParameter) -&amp;gt;&lt;br /&gt;                       this.GetPropertyExpressionForQueryArgument(queryParameter,argument,whereParameter,tmpVar)) &lt;span class="srckeyw"&gt;in&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; initialCondition =  Expression.TypeIs(whereParameter,typeof&amp;lt;JObject&amp;gt;)  &lt;span class="srckeyw"&gt;in&lt;/span&gt;&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; resultingExpression =&lt;br /&gt;        Expression.Block(&lt;br /&gt;           [tmpVar],&lt;br /&gt;           Expression.Call(&lt;br /&gt;              whereMethodInfo,&lt;br /&gt;              Expression.Property(&lt;br /&gt;                 Expression.Convert(&lt;br /&gt;                    this.Expression,this.LimitType),&lt;span class="srctext"&gt;"&lt;span class="srckeyw"&gt;array&lt;/span&gt;"&lt;/span&gt;),&lt;br /&gt;              Expression.Lambda(                     &lt;br /&gt;                  Seq.fold &lt;br /&gt;                       (fun s c -&amp;gt; Expression.And(s,c) :&amp;gt; Expression) &lt;br /&gt;                       (initialCondition :&amp;gt; Expression) &lt;br /&gt;                       queryElementsConditions,&lt;br /&gt;                   whereParameter))) &lt;span class="srckeyw"&gt;in&lt;/span&gt;&lt;br /&gt;   resultingExpression                &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The most important parts of this method is the definition of &lt;code&gt;queryElementsConditions&lt;/code&gt; and &lt;code&gt;resultingExpression&lt;/code&gt;. The resulting expression specifies the invocation to the &lt;code&gt;Where&lt;/code&gt; method &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;queryElementsConditions&lt;/code&gt; take each argument extracted from the name of the method and tries to generate the necessary conditions for the value provided as an argument. In order to do this the &lt;code&gt;GetPropertyExpressionForQueryArgument&lt;/code&gt; method is used:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;member&lt;/span&gt; this.GetPropertyExpressionForQueryArgument(parameter:QueryElement,argument,cParam,tmpVar) : Expression =&lt;br /&gt;    &lt;span class="srckeyw"&gt;match&lt;/span&gt; parameter &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;    | ElementQuery(propertyName) -&amp;gt; &lt;br /&gt;        this.CompareExpression(     &lt;br /&gt;           this.GetJObjectPropertyExpression(cParam,propertyName) ,&lt;br /&gt;           argument) &lt;br /&gt;    | SubElementQuery(propertyName,subPropertyName) -&amp;gt;&lt;br /&gt;        Expression.And(&lt;br /&gt;          Expression.NotEqual(&lt;br /&gt;              Expression.TypeAs(&lt;br /&gt;                 Expression.Assign(&lt;br /&gt;                     tmpVar,&lt;br /&gt;                     this.GetJObjectPropertyExpression(cParam,propertyName)),&lt;br /&gt;                 typeof&amp;lt;JObject&amp;gt;),  &lt;br /&gt;              Expression.Constant(null)),          &lt;br /&gt;          this.CompareExpression(          &lt;br /&gt;              this.GetJObjectPropertyExpression(&lt;br /&gt;                  tmpVar,&lt;br /&gt;                  subPropertyName),argument)) :&amp;gt; Expression&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This method generates a different expression depending on the kind of query element that is requested.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Considerations for IronPython&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As a curious note, in IronPython the &lt;code&gt;BindInvokeMember&lt;/code&gt; method is not called in the &lt;code&gt;FSDynArrayWrapperMetaObject&lt;/code&gt; when a method is invoked. It seems that IronPython calls the &lt;code&gt;BindGetMember&lt;/code&gt; method and then tries to apply the result of getting the method.  &lt;br /&gt;&lt;br /&gt;So to make this object work with IronPython a implementation of the &lt;code&gt;BindGetMember&lt;/code&gt; method was created that returns a &lt;a href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.lambdaexpression.aspx"&gt;lambda expression tree&lt;/a&gt; with the generated &lt;code&gt;Where&lt;/code&gt; invocation.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;override&lt;/span&gt; this.BindGetMember(binder: GetMemberBinder) =&lt;br /&gt;  &lt;span class="srckeyw"&gt;match&lt;/span&gt; QueryInfo.GetQueryElements(binder.Name) &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;  | Some( elements ) -&amp;gt;&lt;br /&gt;      let parameters =&lt;br /&gt;        List.mapi ( fun i _ -&amp;gt;&lt;br /&gt;                         Expression.Parameter(&lt;br /&gt;                                     &lt;span class="srckeyw"&gt;typeof&lt;/span&gt;&amp;lt;string&amp;gt;,&lt;br /&gt;                                     sprintf &lt;span class="srctext"&gt;"p%d"&lt;/span&gt; i)) elements&lt;br /&gt;      (&lt;span class="srckeyw"&gt;new&lt;/span&gt; DynamicMetaObject(&lt;br /&gt;          Expression.Lambda(&lt;br /&gt;              this.GenerateCodeForBinder(&lt;br /&gt;                  elements, &lt;br /&gt;                  parameters &lt;br /&gt;                  |&amp;gt; List.map (fun p -&amp;gt; p :&amp;gt; Expression)&lt;br /&gt;                  |&amp;gt; List.to_array ),&lt;br /&gt;              parameters),&lt;br /&gt;          binder.FallbackGetMember(this).Restrictions))&lt;br /&gt;  | None -&amp;gt; &lt;span class="srckeyw"&gt;base&lt;/span&gt;.BindGetMember(binder)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Accessing using different names&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;QueryInfo.GetQueryElements&lt;/code&gt; method is used to allow the "FindAllBy..." and "find_all_by..." method names .&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;module&lt;/span&gt; QueryInfo = &lt;span class="srckeyw"&gt;begin&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; GetQueryElements(methodName:&lt;span class="srckeyw"&gt;string&lt;/span&gt;) =&lt;br /&gt;       &lt;span class="srckeyw"&gt;match&lt;/span&gt; methodName &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;       | str &lt;span class="srckeyw"&gt;when&lt;/span&gt; str.StartsWith(&lt;span class="srctext"&gt;"FindAllBy"&lt;/span&gt;) -&amp;gt;&lt;br /&gt;              Some(ExtractQueryElements(str.Substring(&lt;span class="srctext"&gt;"FindAllBy"&lt;/span&gt;.Length),&lt;span class="srctext"&gt;"AlsoBy"&lt;/span&gt;,&lt;span class="srctext"&gt;"With"&lt;/span&gt;)) &lt;br /&gt;       | str &lt;span class="srckeyw"&gt;when&lt;/span&gt; str.StartsWith(&lt;span class="srctext"&gt;"find_all_by_"&lt;/span&gt;) -&amp;gt;&lt;br /&gt;           Some(ExtractQueryElements(str.Substring(&lt;span class="srctext"&gt;"find_all_by_"&lt;/span&gt;.Length),&lt;span class="srctext"&gt;"_also_by_"&lt;/span&gt;,&lt;span class="srctext"&gt;"_with_"&lt;/span&gt;) )&lt;br /&gt;       | _ -&amp;gt; None&lt;br /&gt;&lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Code&lt;/h4&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://github.com/ldfallas/dlrexperiments/tree/master"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-5047320708104945564?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/5047320708104945564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=5047320708104945564' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/5047320708104945564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/5047320708104945564'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/08/creating-dynamic-json-array-finders.html' title='Creating Dynamic JSON array finders using the DLR'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-6007590264234520883</id><published>2009-07-26T19:49:00.003-06:00</published><updated>2009-07-27T19:34:39.530-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='dlr'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Using the DynamicObject class</title><content type='html'>In this post I'm going to show a little example of using the &lt;code&gt;DynamicObject&lt;/code&gt; class from the .NET's &lt;a href="http://www.codeplex.com/dlr"&gt;Dynamic Language Runtime&lt;/a&gt;. This class is an easy way to provide dynamic dispatch to your objects in a DLR language.&lt;br /&gt;&lt;br /&gt;Code samples presented here were created using &lt;span style="font-weight:bold;"&gt;Visual Studio 2010 Beta 1&lt;/span&gt; so there may be differences with the final version.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The experiment&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The example is a class that allows access to the properties of &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; objects using the property syntax of a DLR language. In order to do this, a wrapper to &lt;a href="http://www.codeplex.com/Json"&gt;JSON.NET&lt;/a&gt;'s JObject was created. This wrapper is called &lt;code&gt;FSDynJObjectWrapper&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The following code shows an example of using &lt;code&gt;FSDynJObjectWrapper&lt;/code&gt; with C# 4.0 :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;// Load the document&lt;/span&gt;&lt;br /&gt;JsonTextReader reader = &lt;span class="srckeyw"&gt;new&lt;/span&gt; JsonTextReader(GetTwitterPublicTimeLine());&lt;br /&gt;JsonSerializer serializer = &lt;span class="srckeyw"&gt;new&lt;/span&gt; JsonSerializer();&lt;br /&gt;JArray topArray = (JArray)serializer.Deserialize(reader);&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;// Access the document&lt;/span&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;dynamic&lt;/span&gt; aObj = &lt;span class="srckeyw"&gt;new&lt;/span&gt; FSDynJObjectWrapper((JObject)topArray[0]);&lt;br /&gt;Console.WriteLine(&lt;span class="srctext"&gt;"========"&lt;/span&gt;);&lt;br /&gt;Console.WriteLine(aObj.user.screen_name);&lt;br /&gt;Console.Write(&lt;span class="srctext"&gt;"\t'{0}'"&lt;/span&gt;, aObj.text);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Given that the JSON returned by the Twitter REST api looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; {&lt;span class="srctext"&gt;"in_reply_to_screen_name"&lt;/span&gt;:null,&lt;br /&gt;  &lt;span class="srctext"&gt;"text"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;  &lt;span class="srctext"&gt;"user"&lt;/span&gt;: { &lt;span class="srctext"&gt;"following"&lt;/span&gt;:null,&lt;br /&gt;            &lt;span class="srctext"&gt;"description"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"screen_name"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"utc_offset"&lt;/span&gt;:0,&lt;br /&gt;            &lt;span class="srctext"&gt;"followers_count"&lt;/span&gt;:10,&lt;br /&gt;            &lt;span class="srctext"&gt;"time_zone"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"statuses_count"&lt;/span&gt;:155,&lt;br /&gt;            &lt;span class="srctext"&gt;"created_at"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"friends_count"&lt;/span&gt;:1,&lt;br /&gt;            &lt;span class="srctext"&gt;"url"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"name"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"notifications"&lt;/span&gt;:null,&lt;br /&gt;            &lt;span class="srctext"&gt;"protected"&lt;/span&gt;:false,&lt;br /&gt;            &lt;span class="srctext"&gt;"verified"&lt;/span&gt;:false,&lt;br /&gt;            &lt;span class="srctext"&gt;"favourites_count"&lt;/span&gt;:0,&lt;br /&gt;            &lt;span class="srctext"&gt;"location"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;            &lt;span class="srctext"&gt;"id"&lt;/span&gt;: ...,&lt;br /&gt;            ...&lt;br /&gt;  },&lt;br /&gt;  &lt;span class="srctext"&gt;"truncated"&lt;/span&gt;:false,&lt;br /&gt;  &lt;span class="srctext"&gt;"created_at"&lt;/span&gt;:&lt;span class="srctext"&gt;"..."&lt;/span&gt;,&lt;br /&gt;  &lt;span class="srctext"&gt;"in_reply_to_status_id"&lt;/span&gt;:null,&lt;br /&gt;  &lt;span class="srctext"&gt;"in_reply_to_user_id"&lt;/span&gt;:null,&lt;br /&gt;  &lt;span class="srctext"&gt;"favorited"&lt;/span&gt;:false,&lt;br /&gt;  &lt;span class="srctext"&gt;"id"&lt;/span&gt;:...,&lt;br /&gt;  &lt;span class="srctext"&gt;"source"&lt;/span&gt;:&lt;span class="srctext"&gt;"...."&lt;/span&gt;&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;DLR and DynamicObject&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=dlr"&gt;Dynamic Language Runtime&lt;/a&gt; provides a common infrastructure to build dynamic languages on the CLR. The &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject(VS.100).aspx"&gt;&lt;code&gt;System.Dynamic.DynamicObject&lt;/code&gt;&lt;/a&gt; class is an easy way to override the behavior of access to an object from a dynamic language. A partial definition of this class looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;public&lt;/span&gt; abstract &lt;span class="srckeyw"&gt;class&lt;/span&gt; DynamicObject : IDynamicMetaObjectProvider {&lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;virtual&lt;/span&gt; &lt;span class="srckeyw"&gt;bool&lt;/span&gt; TryGetMember(GetMemberBinder binder,&lt;br /&gt;                                     &lt;span class="srckeyw"&gt;out&lt;/span&gt; &lt;span class="srckeyw"&gt;object&lt;/span&gt; result)&lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;virtual&lt;/span&gt; &lt;span class="srckeyw"&gt;bool&lt;/span&gt; TrySetMember(SetMemberBinder binder,&lt;br /&gt;                                     &lt;span class="srckeyw"&gt;object&lt;/span&gt; value)&lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;virtual&lt;/span&gt; &lt;span class="srckeyw"&gt;bool&lt;/span&gt; TryDeleteMember(DeleteMemberBinder binder)&lt;br /&gt;&lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;virtual&lt;/span&gt; &lt;span class="srckeyw"&gt;bool&lt;/span&gt; TryConvert(ConvertBinder binder,&lt;br /&gt;                                   &lt;span class="srckeyw"&gt;out&lt;/span&gt; &lt;span class="srckeyw"&gt;object&lt;/span&gt; result)        &lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;virtual&lt;/span&gt; &lt;span class="srckeyw"&gt;bool&lt;/span&gt; TryUnaryOperation&lt;br /&gt;        (UnaryOperationBinder binder, &lt;span class="srckeyw"&gt;out&lt;/span&gt; &lt;span class="srckeyw"&gt;object&lt;/span&gt; result)&lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;virtual&lt;/span&gt; &lt;span class="srckeyw"&gt;bool&lt;/span&gt; TryBinaryOperation&lt;br /&gt;        (BinaryOperationBinder binder, &lt;span class="srckeyw"&gt;object&lt;/span&gt; arg,&lt;br /&gt;         &lt;span class="srckeyw"&gt;out&lt;/span&gt; &lt;span class="srckeyw"&gt;object&lt;/span&gt; result)&lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;virtual&lt;/span&gt; &lt;span class="srckeyw"&gt;bool&lt;/span&gt; TryInvoke&lt;br /&gt;        (InvokeBinder binder, &lt;span class="srckeyw"&gt;object&lt;/span&gt;[] args, &lt;span class="srckeyw"&gt;out&lt;/span&gt; &lt;span class="srckeyw"&gt;object&lt;/span&gt; result)&lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;virtual&lt;/span&gt; &lt;span class="srckeyw"&gt;bool&lt;/span&gt; TryInvokeMember&lt;br /&gt;        (InvokeMemberBinder binder, &lt;span class="srckeyw"&gt;object&lt;/span&gt;[] args,&lt;br /&gt;         &lt;span class="srckeyw"&gt;out&lt;/span&gt; &lt;span class="srckeyw"&gt;object&lt;/span&gt; result)&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see this class has methods to override things like what happens when a property is access or a method is invoked.  A detailed description of this class is available from the &lt;a href="http://dlr.codeplex.com/Wiki/View.aspx?title=Docs%20and%20specs"&gt;Getting Started with the DLR as a Library Author&lt;/a&gt; document .&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The &lt;code&gt;FSDynJObjectWrapper&lt;/code&gt; class&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As presented above the &lt;code&gt;FSDynJObjectWrapper&lt;/code&gt; inherits from &lt;code&gt;DynamicObject&lt;/code&gt; and provides the required functionality. For this example the class is implemented using F# (although any .NET language could be used) and looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;open System.Dynamic&lt;br /&gt;open System.Reflection&lt;br /&gt;open System.Linq.Expressions&lt;br /&gt;open Newtonsoft.Json.Linq&lt;br /&gt;open Newtonsoft.Json&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; FSDynJObjectWrapper(theObject:JObject) =&lt;br /&gt;   &lt;span class="srckeyw"&gt;inherit&lt;/span&gt; DynamicObject() &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;override&lt;/span&gt; this.TryGetMember(binder : GetMemberBinder, result : obj &lt;span class="srckeyw"&gt; byref&lt;/span&gt; ) =&lt;br /&gt;      &lt;span class="srckeyw"&gt;match&lt;/span&gt; theObject.[binder.Name] &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;      | &lt;span class="srckeyw"&gt;null&lt;/span&gt; -&amp;gt; &lt;span class="srckeyw"&gt;false&lt;/span&gt;&lt;br /&gt;      | :? JObject as aJObject -&amp;gt; &lt;br /&gt;               result &amp;lt;- FSDynJObjectWrapper(aJObject)&lt;br /&gt;               &lt;span class="srckeyw"&gt;true&lt;/span&gt;&lt;br /&gt;      | theValue -&amp;gt; &lt;br /&gt;               result &amp;lt;- theValue&lt;br /&gt;               &lt;span class="srckeyw"&gt;true&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;TryGetMember&lt;/code&gt; will be called when accessing a property. It tries to lookup the name of the requested property in the &lt;code&gt;JObject&lt;/code&gt; instance. A new instance of the wrapper is created if the property value is another &lt;code&gt;JObject&lt;/code&gt; instance allowing expressions like: &lt;code&gt;aObj.user.screen_name&lt;/code&gt; .&lt;br /&gt;&lt;br /&gt;For the next posts I'm going to show the use of other DLR classes and examples using other DLR languages.&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://github.com/ldfallas/dlrexperiments/tree/master"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-6007590264234520883?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/6007590264234520883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=6007590264234520883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/6007590264234520883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/6007590264234520883'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/07/using-dynamicobject-class.html' title='Using the DynamicObject class'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-1675570919022427981</id><published>2009-06-25T21:53:00.002-06:00</published><updated>2009-06-25T21:55:00.587-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><title type='text'>Creating a calendar using Newspeak and Hopscotch</title><content type='html'>For this post I'm going to show the code for a little calendar UI fragment created using the &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak programming language&lt;/a&gt; and the &lt;a href="http://blog.3plus4.org/2008/06/20/which-is-which-in-newspeak-ui-hopscotch/"&gt;Hopscotch&lt;/a&gt; framework.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Calendar&lt;/h4&gt;&lt;br /&gt;Here's how the calendar looks:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_qePSufqunG4/Sj9ugNYHbzI/AAAAAAAAAPI/z8jUc-Z-QOw/s1600-h/hopscotchcalendartest1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 158px;" src="http://1.bp.blogspot.com/_qePSufqunG4/Sj9ugNYHbzI/AAAAAAAAAPI/z8jUc-Z-QOw/s320/hopscotchcalendartest1.png" border="0" alt="Hopscotch calendar experiment"id="BLOGGER_PHOTO_ID_5350116381965119282" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(As you can see,  I'm focusing on the functionality for the moment).&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The code&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As described in "&lt;a href="http://bracha.org/hopscotch-wasdett.pdf"&gt;Hopscotch: Towards User Interface Composition"&lt;/a&gt; this framework promotes the separation between data (the subject) and the UI elements (presenter) . For this calendar fragment the data part will be the given date and the UI part will be a series of UI elements that represent the days of a month.&lt;br /&gt;&lt;br /&gt;Here's an overview of the definition for the &lt;code&gt;HCalendar&lt;/code&gt; class: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; HCalendar usingLib: platform = NewspeakObject (&lt;br /&gt;|&lt;br /&gt;...&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt; &lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; CalendarSubject for: date = Subject (&lt;br /&gt;|&lt;br /&gt;...&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;...&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; CalendarPresenter = Presenter (&lt;br /&gt;|&lt;br /&gt;...&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;...&lt;br /&gt;))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The subject&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As mentioned above the subject only holds a given date. Some operations are added to make it easy to manipulate it.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; CalendarSubject for: date = Subject (&lt;br /&gt;|&lt;br /&gt;   private date = date.&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;('as yet unclassified'&lt;br /&gt;changeDayTo: newDay &amp;lt;Number&amp;gt; = (&lt;br /&gt;  date:: Date year: year&lt;br /&gt;                       month: (month name)&lt;br /&gt;                       day: newDay.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;createPresenter = (&lt;br /&gt;  ^CalendarPresenter new subject: self.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;day ^ &amp;lt;Number&amp;gt; = (&lt;br /&gt;  ^date dayOfMonth.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;month ^ &amp;lt;Month&amp;gt;= (&lt;br /&gt;  ^date month.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;moveToNextMonth = (&lt;br /&gt;   date:: date addMonths: 1.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;moveToPreviousMonth = (&lt;br /&gt;   date:: date addMonths: -1.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;year ^ &amp;lt;Number&amp;gt; = (&lt;br /&gt;  ^date year.&lt;br /&gt;))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h4&gt;The presenter&lt;/h4&gt;&lt;br /&gt;The presenter class is more interesting. It takes the date from the subject and tries to create a representation of the month using Hopscotch fragments. The following snippet shows an overview of the presenter class.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; CalendarPresenter = Presenter (&lt;br /&gt;"Calendar presenter, shows the days of the a month."&lt;br /&gt;|&lt;br /&gt; &lt;br /&gt;  &lt;span class="srckeyw"&gt;protected&lt;/span&gt; weeksRow&lt;br /&gt;  &lt;span class="srckeyw"&gt;protected&lt;/span&gt; monthHolder&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;span class="srctext"&gt;'as yet unclassified'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;definition = (&lt;br /&gt;    monthHolder::&lt;br /&gt;        holder: [&lt;br /&gt;           row: {&lt;br /&gt;                link: &lt;span class="srctext"&gt;'&amp;lt;'&lt;/span&gt; action: [ subject moveToPreviousMonth.&lt;br /&gt;                                    refreshHolders. ].&lt;br /&gt;                blank: 1.&lt;br /&gt;                column: { header .&lt;br /&gt;                          weeks. }.&lt;br /&gt;                blank: 1.&lt;br /&gt;                link: &lt;span class="srctext"&gt;'&amp;gt;'&lt;/span&gt; action: [ subject moveToNextMonth.&lt;br /&gt;                                    refreshHolders. ].&lt;br /&gt; &lt;br /&gt;       }.].&lt;br /&gt;    ^monthHolder.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;fragmentForDaysNotInCurrentMonth = (&lt;br /&gt;  ^label: &lt;span class="srctext"&gt;' '&lt;/span&gt;.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;header = (&lt;br /&gt;  |headerRow|&lt;br /&gt;  headerRow:: row: {&lt;br /&gt;                    filler.&lt;br /&gt;                    label:: subject month name, &lt;span class="srctext"&gt;' '&lt;/span&gt; , subject year asString.&lt;br /&gt;                    filler.&lt;br /&gt;                   }.&lt;br /&gt;  ^headerRow.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;refreshHolders= (  &lt;br /&gt;      monthHolder refresh.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;weekDayFragmentFor: dayNumber = (&lt;br /&gt;    |dayNumberText|&lt;br /&gt;    dayNumberText:: dayNumber asString.&lt;br /&gt; &lt;br /&gt;    ^link: dayNumberText&lt;br /&gt;        action: [ subject changeDayTo: dayNumber.&lt;br /&gt;                  highlightSelectedDay.&lt;br /&gt;                   ].&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;highlightSelectedDay = (&lt;br /&gt; ... &lt;br /&gt;)&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;weeks = (&lt;br /&gt; ... &lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;addFirstWeekTo: result withDaysFromPreviousMonth: previousMonthDays = (&lt;br /&gt;   ...&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;addLastWeekTo: result weeksToShow: weeksToShow lastDayAdded: lastDayAdded daysInNextMonthToShow: nextMonthDays= (&lt;br /&gt;     ... &lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;addMonthWeeksTo: result weeksToShow: weeksToShow lastDayAdded: lastday= (&lt;br /&gt;    ... &lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;columnSeparator = (&lt;br /&gt;   ... &lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;createColumnsFromWeekArray: weekArray = (&lt;br /&gt;    ... &lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;weeks&lt;/code&gt; method is where most of the work of creating the calendar is done. For space reasons I'm not including it here, see the link at the end of the post for the complete code.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Reusing the calendar&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Now that we have the definition of the calendar presenter and subject we can reuse it to create more interesting fragments. For example the following definition could be used to create a date range picker.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; HDateRange usingLib: platform = (&lt;br /&gt;&lt;span class="srctext"&gt;"Date range selector."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;...&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt; &lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; DateRangePresenter = Presenter (&lt;br /&gt;&lt;span class="srctext"&gt;"Presenter for date range."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   dateRangeTextHolder&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;calendar: dateSubject = (&lt;br /&gt;  |aCalendar|&lt;br /&gt;  aCalendar:: dateSubject createPresenter.&lt;br /&gt;  aCalendar onChange: [ dateRangeTextHolder refresh ].&lt;br /&gt;  ^aCalendar.&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;definition = (&lt;br /&gt;     dateRangeTextHolder::&lt;br /&gt;       holder: [label: subject initialDate selectedDate asString, &lt;span class="srctext"&gt;' - '&lt;/span&gt;,&lt;br /&gt;                              subject finalDate selectedDate asString].&lt;br /&gt;     ^heading: dateRangeTextHolder&lt;br /&gt;       details: [&lt;br /&gt;         row: {&lt;br /&gt;          calendar: subject initialDate .&lt;br /&gt;          blank:49.&lt;br /&gt;          calendar: subject finalDate.&lt;br /&gt;          }]&lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;)&lt;br /&gt; &lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; DateRangeSubject from: initial to: final= Subject (&lt;br /&gt;&lt;span class="srctext"&gt;"Data for the date range."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;     &lt;span class="srckeyw"&gt;private&lt;/span&gt; initialDate = (HCalendar usingLib: platform) CalendarSubject for: initial.&lt;br /&gt;     &lt;span class="srckeyw"&gt;private&lt;/span&gt; finalDate = (HCalendar usingLib: platform) CalendarSubject for: final.&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;createPresenter = (&lt;br /&gt;  ^ (DateRangePresenter new) subject: self.&lt;br /&gt;)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/SkQ_1i8xfYI/AAAAAAAAAPQ/Od4Hmc64VSs/s1600-h/hopscotchcalendartest2range.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 165px;" src="http://2.bp.blogspot.com/_qePSufqunG4/SkQ_1i8xfYI/AAAAAAAAAPQ/Od4Hmc64VSs/s320/hopscotchcalendartest2range.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5351472446370315650" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://github.com/ldfallas/newspeakexperiments/tree/master"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-1675570919022427981?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/1675570919022427981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=1675570919022427981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/1675570919022427981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/1675570919022427981'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/06/creating-calendar-using-newspeak-and.html' title='Creating a calendar using Newspeak and Hopscotch'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_qePSufqunG4/Sj9ugNYHbzI/AAAAAAAAAPI/z8jUc-Z-QOw/s72-c/hopscotchcalendartest1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-964907451235767302</id><published>2009-06-21T07:50:00.001-06:00</published><updated>2009-06-21T07:55:26.541-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><title type='text'>Using libcurl with Newspeak FFI (continued)</title><content type='html'>The &lt;a href="http://langexplr.blogspot.com/2009/06/using-libcurl-with-newspeak-ffi.html"&gt;previous post&lt;/a&gt; presented a small low level interface to &lt;a href="http://curl.haxx.se/"&gt;libcurl&lt;/a&gt; using the &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak programming language&lt;/a&gt;. In this post I'm going to show the &lt;code&gt;HttpServiceClient&lt;/code&gt; class, which was created to give a simple interface to the &lt;code&gt;LibCurlHelper&lt;/code&gt; class.&lt;br /&gt;&lt;br /&gt;The definition for class looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Newsqueak2&lt;br /&gt;&lt;span class="srctext"&gt;'LangexplrExperiments'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; HttpServiceClient usingLib: platform withCurlPath: curlLibraryPath = (&lt;br /&gt;&lt;span class="srctext"&gt;"This class is used to access services provided by the HTTP protocol"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   LibCurlHelper = platform LibCurlHelper.&lt;br /&gt;   ByteString = platform ByteString.&lt;br /&gt;   platform = platform.&lt;br /&gt;   Transcript = platform Transcript .&lt;br /&gt;   private curlLibraryPath  = curlLibraryPath .&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;&lt;br /&gt;class HttpRequestResult curlErrorCode: curlErrorCode httpResponse: httpResponse data: data= (&lt;br /&gt;&lt;b&gt;...&lt;/b&gt;&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;&lt;b&gt;...&lt;/b&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;createNewCurlInstance = (&lt;br /&gt;&lt;b&gt;...&lt;/b&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;get: url &amp;lt;String&amp;gt; ^ &amp;lt;HttpRequestResult&amp;gt; = (&lt;br /&gt; &lt;b&gt;...&lt;/b&gt; &lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;get: url &amp;lt;String&amp;gt; withHeaders: headers &amp;lt;Array&amp;gt; ^ &amp;lt;HttpRequestResult&amp;gt; = (&lt;br /&gt;&lt;b&gt;...&lt;/b&gt; &lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;private isHttpsUrl: url &amp;lt;String&amp;gt; ^ &amp;lt;Boolean&amp;gt; = (&lt;br /&gt;&lt;b&gt;...&lt;/b&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;postForm: formData &amp;lt;Dictionary&amp;gt; to: url &amp;lt;String&amp;gt; ^ &amp;lt;HttpRequestResult&amp;gt; = (&lt;br /&gt;&lt;b&gt;...&lt;/b&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;) : (&lt;br /&gt;&lt;b&gt;...&lt;/b&gt;&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;get:&lt;/code&gt;, &lt;code&gt;get: withHeaders:&lt;/code&gt; and &lt;code&gt;postForm: to:&lt;/code&gt; methods provide the functionally to do very simple GET and POST requests. &lt;br /&gt;&lt;br /&gt;The &lt;code&gt;HttpRequestResult&lt;/code&gt; encapsulates the result of calling these methods which has the result of calling &lt;a href="http://curl.haxx.se/libcurl/c/libcurl-errors.html"&gt;libcurl&lt;/a&gt;, the &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;HTTP response code&lt;/a&gt; and the text of the requested data if successful. &lt;br /&gt;&lt;br /&gt;The code for the GET methods looks like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;get: url &amp;lt;String&amp;gt; ^ &amp;lt;HttpRequestResult&amp;gt; = (&lt;br /&gt;      | curl data tmpBuffer bufferLength response|&lt;br /&gt;      ^ get: url withHeaders: {}.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;get: url &amp;lt;String&amp;gt; withHeaders: headers &amp;lt;Array&amp;gt; ^ &amp;lt;HttpRequestResult&amp;gt; = (&lt;br /&gt;      | curl data tmpBuffer bufferLength curlCallResult response|&lt;br /&gt;      data:: ''.&lt;br /&gt;      curl:: createNewCurlInstance.  &lt;br /&gt;      curl writeCallback: &lt;br /&gt;               [:args :result|&lt;br /&gt;                      bufferLength:: ((args datasize) * (args nmemb)).&lt;br /&gt;                      tmpBuffer:: ByteString new:  bufferLength.&lt;br /&gt;                      args data copyInto: tmpBuffer &lt;br /&gt;                                     from: 1 to: bufferLength&lt;br /&gt;                                     in: (args data) startingAt: 1.&lt;br /&gt;                      data:: data,tmpBuffer.&lt;br /&gt;                      result returnInteger:  bufferLength.&lt;br /&gt;               ]. &lt;br /&gt;&lt;br /&gt;      headers size &amp;gt; 0 ifTrue: [curl headers: headers].&lt;br /&gt;&lt;br /&gt;      (isHttpsUrl: url)  &lt;br /&gt;              ifTrue: [curl noSslVerification.].        &lt;br /&gt;      curl url: url. &lt;br /&gt;&lt;br /&gt;      curlCallResult:: curl performOperation.&lt;br /&gt;&lt;br /&gt;      response:: curl responseCode.&lt;br /&gt;      curl cleanup.&lt;br /&gt;      ^HttpRequestResult &lt;br /&gt;                   curlErrorCode: curlCallResult &lt;br /&gt;                   httpResponse: response&lt;br /&gt;                   data: data.&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The code for the POST operation looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;postForm: formData &amp;lt;Dictionary&amp;gt; to: url = (&lt;br /&gt;      | curl data tmpBuffer bufferLength curlFormData response curlCallResult|&lt;br /&gt;      data:: ''.&lt;br /&gt; curl:: createNewCurlInstance. &lt;br /&gt;&lt;br /&gt;      curl post: formData.&lt;br /&gt;      curl writeCallback: &lt;br /&gt;               [:args :result|&lt;br /&gt;                      bufferLength:: ((args datasize) * (args nmemb)).&lt;br /&gt;                      tmpBuffer:: ByteString new:  bufferLength.&lt;br /&gt;                      args data copyInto: tmpBuffer &lt;br /&gt;                                     from: 1 to: bufferLength&lt;br /&gt;                                     in: (args data) startingAt: 1.&lt;br /&gt;                      data:: data,tmpBuffer.&lt;br /&gt;                      result returnInteger:  bufferLength.&lt;br /&gt;               ].&lt;br /&gt;&lt;br /&gt;      (isHttpsUrl: url)  &lt;br /&gt;              ifTrue: [curl noSslVerification.].        &lt;br /&gt;         &lt;br /&gt;      curl url: url.&lt;br /&gt;      curlCallResult: curl performOperation.&lt;br /&gt;&lt;br /&gt;      response:: curl responseCode.&lt;br /&gt;      curl cleanup.&lt;br /&gt;      ^HttpRequestResult &lt;br /&gt;                   curlErrorCode: curlCallResult &lt;br /&gt;                   httpResponse: response&lt;br /&gt;                   data: data.&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://github.com/ldfallas/newspeakexperiments/tree/master"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-964907451235767302?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/964907451235767302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=964907451235767302' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/964907451235767302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/964907451235767302'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/06/using-libcurl-with-newspeak-ffi_21.html' title='Using libcurl with Newspeak FFI (continued)'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-7461937083713580958</id><published>2009-06-13T07:24:00.000-06:00</published><updated>2009-06-13T07:25:31.470-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><title type='text'>Using libcurl with Newspeak FFI</title><content type='html'>In this post I'm going to show a little example of using &lt;a href="http://curl.haxx.se/libcurl/"&gt;libcurl&lt;/a&gt; from the &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak programming language&lt;/a&gt; .&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Newspeak FFI&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Newspeak provides a nice mechanism to call C code. This mechanism is described in&lt;br /&gt;&lt;a href="http://wiki.squeak.org/squeak/uploads/6100/Alien%20FFI.pdf"&gt;Newspeak Foreign Function Interface User Guide&lt;/a&gt; document. The &lt;code&gt;AlienDemo&lt;/code&gt; example provided with the Newspeak prototype has some nice small examples of the FFI.&lt;br /&gt;&lt;br /&gt;The experiment presented in this post was created using the &lt;a href="http://newspeaklanguage.org/downloads/"&gt;Newspeak prototype from February 2009&lt;/a&gt;. Due to some limitations of this release, this code only works with the Windows version of the prototype. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;libcurl&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://curl.haxx.se/libcurl/"&gt;libcurl&lt;/a&gt; is a C library that provides client access to several networking protocols with a common interface. For this post I'm going to implement a wrapper for very small subset of the functionality provided by libcurl in order to perform simple HTTP/HTTPS GET and POST requests .&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://curl.haxx.se/lxr/source/docs/examples/simple.c"&gt;simple.c&lt;/a&gt; example shows how to do a simple GET request.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;int&lt;/span&gt; main(void)&lt;br /&gt;{&lt;br /&gt;  CURL *curl;&lt;br /&gt;  CURLcode res;&lt;br /&gt;&lt;br /&gt;  curl = curl_easy_init();&lt;br /&gt;  &lt;span class="srckeyw"&gt;if&lt;/span&gt;(curl) {&lt;br /&gt;    curl_easy_setopt(curl, CURLOPT_URL, &lt;span class="srckeyw"&gt;"curl.haxx.se"&lt;/span&gt;);&lt;br /&gt;    res = curl_easy_perform(curl);&lt;br /&gt;    curl_easy_cleanup(curl);&lt;br /&gt;  }&lt;br /&gt;  &lt;span class="srckeyw"&gt;return&lt;/span&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The LibCurlHelper class&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;A class named LibCurlHelper will be used to encapsulate calls to libcurl. As you will notice the interface of this class is pretty low level. For future posts I'll try to create a better interface using more Newspeak features.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; LibCurlHelper &lt;b&gt;usingLib:&lt;/b&gt; platform = (&lt;br /&gt;&lt;span class="srctext"&gt;"This class wraps an implementation of the libcurl library"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;      Transcript = platform Transcript.&lt;br /&gt;      Alien = platform Alien.&lt;br /&gt;      UnsafeAlien = platform UnsafeAlien.&lt;br /&gt;      Callback = platform Callback.&lt;br /&gt;      CurlWriteCallback = platform CurlWriteCallbackNs1.&lt;br /&gt;      CurlDebugCallback = platform CurlDebugCallback.&lt;br /&gt;      ByteString = platform ByteString.&lt;br /&gt;      OrderedCollection = platform OrderedCollection.&lt;br /&gt;      ...&lt;br /&gt;      public libcurlPath = ''.&lt;br /&gt;      public errorBuffer = ''.&lt;br /&gt;      protected CURL_OPT_URL = 10002.&lt;br /&gt;      protected CURLOPT_WRITEFUNCTION = 20011.&lt;br /&gt;      ...&lt;br /&gt;     &lt;br /&gt;      internalDebugCallback = nil.&lt;br /&gt;      internalWriteCallback = nil.&lt;br /&gt;      formPostData = nil.&lt;br /&gt;      private curlInstance = nil.&lt;br /&gt;      private aliensToRelease = nil.  &lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;      CURLFORM_NOTHING = 0 .&lt;br /&gt;      CURLFORM_COPYNAME = 1 .&lt;br /&gt;      CURLFORM_PTRNAME = 2.&lt;br /&gt;      ... &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;libcurl uses a lot of constaints prefixed with  "CURL" this class contains definitions for some of them.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Initialization&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;initializeCurl&lt;/code&gt; method calls the &lt;code&gt;curl_easy_init&lt;/code&gt; (as in the &lt;code&gt;simple.c&lt;/code&gt; example shown above) and stores the returned pointer in a slot called &lt;code&gt;curlInstance&lt;/code&gt; which will be used in further calls.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;initializeCurl = (&lt;br /&gt;     |curl|&lt;br /&gt;     ensureLibrariesLoaded .&lt;br /&gt;     (Alien lookup: &lt;span class="srctext"&gt;'curl_easy_init'&lt;/span&gt; inLibrary: curlLibName )&lt;br /&gt;            primFFICallResult: (curl:: Alien new: 4).  &lt;br /&gt;     curlInstance: curl.&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;ensureLibrariesLoaded&lt;/code&gt; and &lt;code&gt;&lt;/code&gt; methods.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;curlLibName = (&lt;br /&gt;       ^libcurlPath, &lt;span class="srctext"&gt;'libcurl.dll' &lt;/span&gt;&lt;br /&gt;)&lt;br /&gt;ensureLibrariesLoaded = (&lt;br /&gt;      Alien ensureLoaded: libcurlPath, &lt;span class="srctext"&gt;'libidn-11.dll'&lt;/span&gt;.&lt;br /&gt;      Alien ensureLoaded: libcurlPath, &lt;span class="srctext"&gt;'libeay32.dll'&lt;/span&gt;.&lt;br /&gt;      Alien ensureLoaded: libcurlPath, &lt;span class="srctext"&gt;'libssl32.dll'&lt;/span&gt;.&lt;br /&gt;      Alien ensureLoaded: curlLibName. &lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Setting the URL&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In order to set the URL for the request we need to call the &lt;code&gt;curl_easy_setopt&lt;/code&gt; function with the &lt;code&gt;CURL_OPT_URL&lt;/code&gt; with the URL string.&lt;br /&gt;&lt;br /&gt;The code looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;url: url &amp;lt;String&amp;gt; = (&lt;br /&gt;    |result|&lt;br /&gt;    (Alien lookup: &lt;span class="srctext"&gt;'curl_easy_setopt'&lt;/span&gt; inLibrary: curlLibName )&lt;br /&gt;             primFFICallResult: (result:: Alien new:4)&lt;br /&gt;             withArguments: {  curlInstance.&lt;br /&gt;                               CURL_OPT_URL.&lt;br /&gt;                               (addAlienToRelease: (url asAlien)) pointer. }.&lt;br /&gt;    ^result.&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;addAlienToRelease:&lt;/code&gt; method was added to in order to keep track of resources allocated in the C heap that need to be manually released when not needed.  The &lt;code&gt;asAlien&lt;/code&gt; method of the &lt;code&gt;String&lt;/code&gt; class creates a resource of this kind.&lt;br /&gt;&lt;br /&gt;The implementation of this method looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;addAlienToRelease: anAlien = (&lt;br /&gt;   aliensToRelease isNil ifTrue: [ aliensToRelease:: OrderedCollection new. ].&lt;br /&gt;   aliensToRelease add: anAlien.&lt;br /&gt;   ^anAlien.&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Setting the write callback&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Callback functions are used by &lt;span style="font-weight:bold;"&gt;libcurl&lt;/span&gt; to process the data coming from the network. The Newspeak FFI provides a nice way to add this kind of callbacks. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;writeCallback:  callback &amp;lt;Block&amp;gt;= (&lt;br /&gt;      |result|&lt;br /&gt;      internalWriteCallback:: Callback&lt;br /&gt;                                    block: callback &lt;br /&gt;                                    argsClass: CurlWriteCallback. &lt;br /&gt; &lt;br /&gt;      (Alien lookup: &lt;span class="srctext"&gt;'curl_easy_setopt'&lt;/span&gt; inLibrary: curlLibName ) &lt;br /&gt;          primFFICallResult: (result:: Alien new: 4)&lt;br /&gt;          withArguments: {  curlInstance.&lt;br /&gt;                            CURLOPT_WRITEFUNCTION.&lt;br /&gt;                            internalWriteCallback thunk. }.&lt;br /&gt;&lt;br /&gt;     ^result.&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The writeCallback: method sets the block in &lt;code&gt;callback &lt;/code&gt; as the libcurl write callback. In order to do this it creates an instance of the &lt;code&gt;Callback&lt;/code&gt; class with the block and the arguments class. An instance of this class is used to create a function pointer which is passed to the &lt;code&gt;curl_easy_setopt&lt;/code&gt; function.&lt;br /&gt;&lt;br /&gt;The "arguments class" is defined using the NS1 Newspeak syntax as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Newsqueak1&lt;/span&gt;&lt;br /&gt;&lt;span class="srctext"&gt;'LangexplrExperiments'&lt;/span&gt;&lt;br /&gt;CurlWriteCallbackNs1 = Alien (&lt;br /&gt;&lt;span class="srctext"&gt;"Class used to represent arguments of the LibCurl write function."&lt;/span&gt;&lt;br /&gt;&lt;span class="srctext"&gt;'as yet unclassified'&lt;/span&gt;&lt;br /&gt;data = (&lt;br /&gt;    ^Alien forPointer: (self unsignedLongAt: 1)&lt;br /&gt;)&lt;br /&gt;datasize = (&lt;br /&gt;    ^(self unsignedLongAt: 5)&lt;br /&gt;)&lt;br /&gt;nmemb = (&lt;br /&gt;    ^(self unsignedLongAt: 9)&lt;br /&gt;)&lt;br /&gt;writerData = (&lt;br /&gt;    ^Alien forPointer: (self unsignedLongAt: 13)&lt;br /&gt;)&lt;br /&gt;) : (&lt;br /&gt;&lt;span class="srctext"&gt;'as yet unclassified'&lt;/span&gt;&lt;br /&gt;dataSize = (&lt;br /&gt;    ^16&lt;br /&gt;))&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;An instance of this class is used to represent the arguments of a callback call. An example of the use of this function is presented below.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Performing the request&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;curl_easy_perform&lt;/code&gt; function is used to start the operation. The following code shows the call to this function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;performOperation = (&lt;br /&gt;   |r|&lt;br /&gt;    (Alien lookup: &lt;span class="srctext"&gt;'curl_easy_perform'&lt;/span&gt; inLibrary: curlLibName )&lt;br /&gt;          primFFICallResult: (r:: Alien new: 4)&lt;br /&gt;           withArguments: {  curlInstance. }.&lt;br /&gt;   ^r signedLongAt: 1.&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Cleanup&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Finally the following method is used to release the resources allocated by libcurl.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;cleanup = (&lt;br /&gt;      (Alien lookup: &lt;span class="srctext"&gt;'curl_easy_cleanup'&lt;/span&gt; inLibrary: curlLibName )&lt;br /&gt;          primFFICallResult: nil&lt;br /&gt;             withArguments: { curlInstance }   .&lt;br /&gt;&lt;br /&gt;      aliensToRelease do: [:anAlien | anAlien free ].&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Example of using the library&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;As mentioned above, the &lt;code&gt;LibCurlHelper&lt;/code&gt; class provides a low level interface to libcurl, something needs to be created to encapsulate this functionality. &lt;br /&gt;&lt;br /&gt;The following method shows a method that preforms a simple GET request and returns the downloaded data as a string.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srctext"&gt;class&lt;/span&gt; HttpServiceClient usingLib: platform withCurlPath: curlLibraryPath = (&lt;br /&gt;&lt;span class="srctext"&gt;"This class is used to access services provided by the HTTP protocol"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   LibCurlHelper = platform LibCurlHelper.&lt;br /&gt;   ByteString = platform ByteString.&lt;br /&gt;   platform = platform.&lt;br /&gt;   Transcript = platform Transcript .&lt;br /&gt;   private curlLibraryPath  = curlLibraryPath .&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(&lt;br /&gt;simpleGet: url &lt;String&gt; ^ &lt;String&gt; = (&lt;br /&gt;      | curl data tmpBuffer bufferLength response|&lt;br /&gt;      curl:: (LibCurlHelper usingLib: platform).&lt;br /&gt;      curl libcurlPath: curlLibraryPath .&lt;br /&gt;      curl initializeCurl.&lt;br /&gt;&lt;br /&gt;      data:: &lt;span class="srctext"&gt;''&lt;/span&gt;.&lt;br /&gt;      curl:: createNewCurlInstance. &lt;br /&gt;&lt;br /&gt;      curl writeCallback: &lt;br /&gt;               [:args :result|&lt;br /&gt;                      bufferLength:: ((args datasize) * (args nmemb)).&lt;br /&gt;                      tmpBuffer:: ByteString new:  bufferLength.&lt;br /&gt;                      args data copyInto: tmpBuffer &lt;br /&gt;                                     from: 1 to: bufferLength&lt;br /&gt;                                     in: (args data) startingAt: 1.&lt;br /&gt;                      data:: data,tmpBuffer.&lt;br /&gt;                      result returnInteger:  bufferLength.&lt;br /&gt;               ].&lt;br /&gt;      curl url: url.&lt;br /&gt;      curl performOperation.&lt;br /&gt;      curl cleanup.&lt;br /&gt;      ^data&lt;br /&gt;)&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that here the callback function modifies a local variable every time the data arrives. Also notice that &lt;code&gt;args&lt;/code&gt; is an instance of &lt;code&gt;CurlWriteCallbackNs1&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Final words&lt;/h4&gt;&lt;br /&gt;The experiment of using &lt;span style="font-weight:bold;"&gt;libcurl&lt;/span&gt; from Newspeak was a nice way to learn about its foreign function interface. Having access to &lt;code&gt;libcurl&lt;/code&gt; access to useful things such as&lt;a href="http://curl.haxx.se/lxr/source/docs/examples/https.c"&gt; HTTPS requests&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There's already a nice &lt;a href="http://www.squeak.org/"&gt;Squeak&lt;/a&gt; wrapper for libcurl called &lt;a href="http://wiki.squeak.org/squeak/5865"&gt;CurlPlugin&lt;/a&gt; .&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://gist.github.com/125793"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-7461937083713580958?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/7461937083713580958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=7461937083713580958' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7461937083713580958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/7461937083713580958'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/06/using-libcurl-with-newspeak-ffi.html' title='Using libcurl with Newspeak FFI'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-3072718730955024144</id><published>2009-05-17T05:37:00.005-06:00</published><updated>2009-05-17T06:03:12.770-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>Modifying an AS3 class with AbcExplorationLib</title><content type='html'>Recently, I made a couple of changes to &lt;a href="http://abcexplorationlib.codeplex.com/"&gt;AbcExplorationLib&lt;/a&gt; to allow the modification of a compiled &lt;a href="http://en.wikipedia.org/wiki/ActionScript"&gt;ActionScript&lt;/a&gt; 3 (AS3) class.&lt;br /&gt;&lt;br /&gt;The following code will be used to  illustrate this feature:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; Shape {&lt;br /&gt;  &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; foo() {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    print(&lt;span class="srctext"&gt;"Base foo"&lt;/span&gt;);&lt;br /&gt; }&lt;br /&gt; &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; paint():&lt;span class="srckeyw"&gt;void&lt;/span&gt; {&lt;br /&gt;    foo();&lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; Rectangle &lt;span class="srckeyw"&gt;extends&lt;/span&gt; Shape{&lt;br /&gt; &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;override&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; paint():&lt;span class="srckeyw"&gt;void&lt;/span&gt; {&lt;br /&gt;    &lt;span class="srckeyw"&gt;super&lt;/span&gt;.paint();&lt;br /&gt;    print( &lt;span class="srctext"&gt;"Rectangle"&lt;/span&gt;);&lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; Circle &lt;span class="srckeyw"&gt;extends&lt;/span&gt; Shape{&lt;br /&gt; &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;override&lt;/span&gt; &lt;span class="srckeyw"&gt;function&lt;/span&gt; paint():&lt;span class="srckeyw"&gt;void&lt;/span&gt; {&lt;br /&gt;    &lt;span class="srckeyw"&gt;super&lt;/span&gt;.paint();&lt;br /&gt;    print( &lt;span class="srctext"&gt;"Circle"&lt;/span&gt;);&lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;var&lt;/span&gt; shapes = [new Rectangle(),new Circle()];&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;for each&lt;/span&gt;(&lt;span class="srckeyw"&gt;var&lt;/span&gt; s:Shape &lt;span class="srckeyw"&gt;in&lt;/span&gt; shapes) {&lt;br /&gt;  s.paint();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Compiling this program using the &lt;a href="http://www.adobe.com/products/flex/flexdownloads/"&gt;Flex SDK&lt;/a&gt; and running it using the &lt;a href="http://www.mozilla.org/projects/tamarin/"&gt;Tamarin &lt;/a&gt;binaries shows the following output:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ java -jar asc.jar -import builtin.abc Shapes.as&lt;br /&gt;&lt;br /&gt;Shapes.abc, 678 bytes written&lt;br /&gt;$ avmshell Shapes.abc&lt;br /&gt;Base foo&lt;br /&gt;Rectangle&lt;br /&gt;Base foo&lt;br /&gt;Circle&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Say that we want to create a definition of the &lt;code&gt;foo&lt;/code&gt; method in the &lt;code&gt;Rectangle&lt;/code&gt; class that overrides the definition from &lt;code&gt;Shape&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;1. First we load the class file:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; abcFile = &lt;span class="srckeyw"&gt;using&lt;/span&gt; (&lt;span class="srckeyw"&gt;new&lt;/span&gt; FileStream(sourceFile,FileMode.Open)) ( &lt;br /&gt;                      &lt;span class="srckeyw"&gt;fun&lt;/span&gt; stream -&amp;gt; AvmAbcFile.Create(stream))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2. Then we need a definition for the new &lt;code&gt;foo&lt;/code&gt; implementation. The following function creates a &lt;code&gt;foo&lt;/code&gt; override that prints a message to the screen:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; newFooMethod(message:string) = &lt;br /&gt;   AvmMemberMethod( &lt;br /&gt;     CQualifiedName(Ns(&lt;span class="srctext"&gt;""&lt;/span&gt;,NamespaceKind.PackageNamespace),&lt;span class="srctext"&gt;"foo"&lt;/span&gt;),&lt;br /&gt;     AvmMethod(&lt;br /&gt;        &lt;span class="srctext"&gt;""&lt;/span&gt;,&lt;br /&gt;        SQualifiedName(&lt;span class="srctext"&gt;"*"&lt;/span&gt;),&lt;br /&gt;        [||],&lt;br /&gt;        Some &amp;lt;| &lt;br /&gt;          AvmMethodBody(&lt;br /&gt;            2,1,4,5,&lt;br /&gt;            [|&lt;br /&gt;              GetLocal0;&lt;br /&gt;              PushScope;&lt;br /&gt;              FindPropertyStrict(&lt;br /&gt;                   MQualifiedName(&lt;br /&gt;                      [|Ns(&lt;span class="srctext"&gt;""&lt;/span&gt;,&lt;br /&gt;                           NamespaceKind.PackageNamespace)|],&lt;br /&gt;                      &lt;span class="srctext"&gt;"print"&lt;/span&gt;));&lt;br /&gt;              PushString message;&lt;br /&gt;              CallProperty(&lt;br /&gt;                   MQualifiedName(&lt;br /&gt;                      [|Ns(&lt;span class="srctext"&gt;""&lt;/span&gt;,&lt;br /&gt;                           NamespaceKind.PackageNamespace)|],&lt;br /&gt;                      &lt;span class="srctext"&gt;"print"&lt;/span&gt;),&lt;br /&gt;                   1);&lt;br /&gt;              Pop;&lt;br /&gt;              ReturnVoid&lt;br /&gt;              |],[||],[||]             &lt;br /&gt;          )          &lt;br /&gt;     ),&lt;br /&gt;     AbcTraitAttribute.Override&lt;br /&gt;   )&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3. We need a function to add a method to a existing class. Notice that the modification consists in only creating a new instance of the AvmClass with the same values as the original but adding the new method.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; addClassMethod(aClass,newMethod) =&lt;br /&gt;  &lt;span class="srckeyw"&gt;match&lt;/span&gt; aClass &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;  | AvmClass(name,&lt;br /&gt;             superclassname,&lt;br /&gt;             init,&lt;br /&gt;             cinit,&lt;br /&gt;             slots,&lt;br /&gt;             methods,&lt;br /&gt;             pns)  -&amp;gt;&lt;br /&gt;      AvmClass(name,&lt;br /&gt;               superclassname,&lt;br /&gt;               init,cinit,&lt;br /&gt;               slots,&lt;br /&gt;               newMethod::methods,&lt;br /&gt;               pns)&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4. The following method is used to locate the rectangle class and apply the modification:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; modifyFileToAddMethod(f:AvmAbcFile) =&lt;br /&gt; AvmAbcFile(f.Scripts,&lt;br /&gt;            f.Classes |&amp;gt;&lt;br /&gt;               List.map (fun (c:AvmClass) -&amp;gt;&lt;br /&gt;                          &lt;br /&gt;                          &lt;span class="srckeyw"&gt;match&lt;/span&gt; c.Name  &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;                          | CQualifiedName(_,&lt;span class="srctext"&gt;"Rectangle"&lt;/span&gt;) -&amp;gt;&lt;br /&gt;                              addClassMethod(&lt;br /&gt;                                   c,&lt;br /&gt;                                   newFooMethod(&lt;span class="srctext"&gt;"New foo for Rectange!!!"&lt;/span&gt;))&lt;br /&gt;                          | _ -&amp;gt; c))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;5. Finally we write the input file back to disk:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; modifiedAbcFile = modifyFileToAddMethod(abcFile)&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; abcFileCreator = AbcFileCreator()&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; file = modifiedAbcFile.ToLowerIr(abcFileCreator)&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; (new BinaryWriter(new FileStream(targetFileName,FileMode.Create)))&lt;br /&gt;      (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; f -&amp;gt; file.WriteTo(f))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After running this program we can execute the bytecode again to get the new results:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ mono modify.exe Shapes.abc&lt;br /&gt;...&lt;br /&gt;$ avmshell Shapes_t.abc&lt;br /&gt;New foo for Rectange!!!&lt;br /&gt;Rectangle&lt;br /&gt;Base foo&lt;br /&gt;Circle&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;One area that really needs works is name handling. A particular challenge is to find a good way to represent &lt;span style="font-style:italic;"&gt;multinames &lt;/span&gt;( name references in a set of name spaces ).  &lt;br /&gt;&lt;br /&gt;In general the way of defining a method from scratch(for example in &lt;code&gt;newFooMethod&lt;/code&gt;) needs some work since it is requires lots of details that might not be interesting for the developer.&lt;br /&gt;&lt;br /&gt;Finally, another area that really needs improvement is the output file generation. Right now it requires the user to write three instructions to write the file to disc. This will be changed to be similar to the load process.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Code for this program can be found as part of the AbcExplorationLib samples.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-3072718730955024144?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/3072718730955024144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=3072718730955024144' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/3072718730955024144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/3072718730955024144'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/05/modifying-as3-class-with.html' title='Modifying an AS3 class with AbcExplorationLib'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-314790409648896411</id><published>2009-04-14T06:22:00.001-06:00</published><updated>2009-04-14T06:24:09.190-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><title type='text'>Writing a small Twitter client with Newspeak and Hopscotch</title><content type='html'>In this post I'm going to show a small &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; client written using the &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak programming language &lt;/a&gt;and the Hopscotch framework.&lt;br /&gt;&lt;br /&gt;As part of the process of exploring the Newspeak language here I'm going to focus on the Hopscotch UI framework. It will be used to present information from the &lt;a href="http://apiwiki.twitter.com/REST+API+Documentation"&gt;Twitter REST API&lt;/a&gt; which is very easy to use. &lt;br /&gt;&lt;br /&gt;The Hopscotch framework and IDE is described in the &lt;a href="http://bracha.org/hopscotch-wasdett.pdf"&gt;"Hopscotch: Towards User Interface Composition"&lt;/a&gt; paper by &lt;a href="http://blog.3plus4.org/"&gt;Vassili Bykov&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Code for this program was created using the Newspeak prototype from 2009-02-27.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The program&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Here's a screenshot of the program:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/SeRrv-iuoSI/AAAAAAAAAOw/n-HNh_Uh8H0/s1600-h/nspktwitterclient.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 320px;" src="http://4.bp.blogspot.com/_qePSufqunG4/SeRrv-iuoSI/AAAAAAAAAOw/n-HNh_Uh8H0/s320/nspktwitterclient.png" border="0" alt="screenshot fo the twitter client"id="BLOGGER_PHOTO_ID_5324499131445453090" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The program is not a complete client, it just allows to post a new &lt;span style="font-style:italic;"&gt;twit&lt;/span&gt; and to read the current time line of a the user. &lt;br /&gt;&lt;br /&gt;The code from the previous post &lt;a href="http://langexplr.blogspot.com/2009/04/parsing-json-with-newspeak.html"&gt;"Parsing JSON with Newspeak"&lt;/a&gt; is used to access the data provided by the Twitter services.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The code&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The following screenshot shows the definition of the TwitterGUI class&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_qePSufqunG4/SeRvozd7FJI/AAAAAAAAAO4/7WKw-9haZb4/s1600-h/twitterclientmainclass.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 310px; height: 320px;" src="http://1.bp.blogspot.com/_qePSufqunG4/SeRvozd7FJI/AAAAAAAAAO4/7WKw-9haZb4/s320/twitterclientmainclass.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5324503406259934354" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The following nested classes provide the functionality for the client:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;code&gt;TwitterClient&lt;/code&gt;: A class for using the Twitter REST API&lt;/li&gt;&lt;li&gt;&lt;code&gt;TwitPresenter,TwitSubject&lt;/code&gt;: The UI piece and information for a single &lt;span style="font-style:italic;"&gt;twit&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;TwitterMainPresenter,TwitterMainSubject&lt;/code&gt;: The UI piece and information for a the complete client&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;As described in the Hopscotch  &lt;a href="http://bracha.org/hopscotch-wasdett.pdf"&gt;paper&lt;/a&gt; a pair of elements is required to create a UI piece. A &lt;span style="font-weight:bold;"&gt;subject&lt;/span&gt; which contains the information being presented and the &lt;span style="font-weight:bold;"&gt;presenter&lt;/span&gt; which defines the UI that shows it. &lt;br /&gt;&lt;br /&gt;In the case of a single &lt;span style="font-style:italic;"&gt;twit&lt;/span&gt; the data is transmitted from the service as a JSON document. &lt;br /&gt;&lt;br /&gt;The following code shows an example of the JSON response of a single &lt;span style="font-style:italic;"&gt;twit&lt;/span&gt; from the Twitter REST API:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;[{"in_reply_to_screen_name":null,&lt;br /&gt;  "user":{&lt;br /&gt;     "description":"Father, husband, friend, developer and late night programming language enthusiast.",&lt;br /&gt;     "statuses_count":318,&lt;br /&gt;     "utc_offset":-21600,&lt;br /&gt;     "profile_background_tile":false,&lt;br /&gt;     "profile_background_color":"6E8182",&lt;br /&gt;     "following":null,&lt;br /&gt;     "profile_text_color":"000000",&lt;br /&gt;     "url":"http:\/\/langexplr.blogspot.com",&lt;br /&gt;     "name":"Luis Diego Fallas",&lt;br /&gt;     "protected":false,&lt;br /&gt;     "profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/133285952\/ldnach_normal.png",&lt;br /&gt;     "notifications":null,&lt;br /&gt;     "profile_link_color":"0000ff",&lt;br /&gt;     "profile_background_image_url":"http:\/\/static.twitter.com\/images\/themes\/theme1\/bg.gif",&lt;br /&gt;     "created_at":"Mon Jul 28 13:51:55 +0000 2008",&lt;br /&gt;     "screen_name":"ldfallas",&lt;br /&gt;     "profile_sidebar_fill_color":"e0ff92",&lt;br /&gt;     "followers_count":45,&lt;br /&gt;     "time_zone":"Central America",&lt;br /&gt;     "location":"Costa Rica",&lt;br /&gt;     "id":15631932,&lt;br /&gt;     "favourites_count":9,&lt;br /&gt;     "friends_count":43,&lt;br /&gt;     "profile_sidebar_border_color":"87bc44"},&lt;br /&gt;  "text":"Experimenting with Hopscotch in Newspeak",&lt;br /&gt;  "truncated":false,&lt;br /&gt;  "in_reply_to_status_id":null,&lt;br /&gt;  "created_at":"Tue Apr 07 14:21:57 +0000 2009",&lt;br /&gt;  "in_reply_to_user_id":null,&lt;br /&gt;  "id":1469769323,&lt;br /&gt;  "favorited":false,&lt;br /&gt;  "source":"web"}&lt;br /&gt;...]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A &lt;code&gt;TwitSubject&lt;/code&gt; represents one of these pieces of information.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; TwitSubject withTwit: twit images: images= Subject (&lt;br /&gt;&lt;span class="srctext"&gt;"Describe the class in this comment."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   theTwit = twit.&lt;br /&gt;   theImages = images.&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;createPresenter  = (&lt;br /&gt;    ^TwitPresenter new subject: self.&lt;br /&gt;)&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The definition of the TwitPresenter looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srctext"&gt;class&lt;/span&gt; TwitPresenter = Presenter (&lt;br /&gt;&lt;span class="srctext"&gt;"Presenter for a single twit."&lt;/span&gt;&lt;br /&gt;|   &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;definition = (&lt;br /&gt;   ^(padded:( column: {&lt;br /&gt;&lt;br /&gt;        (row: { link: (subject theTwit user screen_name) action: [] . }) color: ( Color veryVeryLightGray).&lt;br /&gt;         row: { image: (subject theImages at: (subject theTwit user profile_image_url)) .&lt;br /&gt;         blank: 4.&lt;br /&gt;         elastic: twitBody}.&lt;br /&gt;&lt;br /&gt;   }) with: {3. 3. 2. 2.}) .&lt;br /&gt;)&lt;br /&gt;...&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The following screenshot shows an example of the previous definition.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/SeR1PRPgGbI/AAAAAAAAAPA/Q4_maYNsAAs/s1600-h/nspktwclientsingletwit.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 42px;" src="http://4.bp.blogspot.com/_qePSufqunG4/SeR1PRPgGbI/AAAAAAAAAPA/Q4_maYNsAAs/s320/nspktwclientsingletwit.png" border="0" alt="Single twit"id="BLOGGER_PHOTO_ID_5324509564645677490" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A special treatment need to be applied to the message since we want to be able to click on links or twitter user id's (not supported right now). The definition of &lt;code&gt;twitBody&lt;/code&gt; shows this.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;twitBody = (&lt;br /&gt;   |  text result |&lt;br /&gt;   text: subject theTwit text.&lt;br /&gt;   ((string: text contains: &lt;span class="srctext"&gt;'@'&lt;/span&gt;) or: [string: text contains: &lt;span class="srctext"&gt;'http'&lt;/span&gt;] )&lt;br /&gt;   ifTrue: [ result:: flow: ((text subStrings: {Character space}) collect: [:t | componentFor: t])]&lt;br /&gt;   ifFalse: [ result:: textDisplay: text ].&lt;br /&gt;   ^result&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;componentFor: s = (&lt;br /&gt;   |result|&lt;br /&gt;   (s includesSubString: &lt;span class="srctext"&gt;'@'&lt;/span&gt;) &lt;br /&gt;   ifTrue: [ result:: link: s action: [] ]&lt;br /&gt;      ifFalse: [&lt;br /&gt;        (string: s contains: &lt;span class="srctext"&gt;'http'&lt;/span&gt;)&lt;br /&gt;      ifTrue: [ result:: link: s action: [openLink: s] ]&lt;br /&gt;      ifFalse:[ result:: label: s]&lt;br /&gt;   ].&lt;br /&gt;   ^result.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;openLink:url  = (&lt;br /&gt;   OSProcess command:  (browser , &lt;span class="srctext"&gt;' '&lt;/span&gt; , url).&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What these methods do is to break the string of the message into words separated by spaces. If a word is an URL  or and '@' character a link is created if not a 'label' is created . For the future this code needs to be improved with a better technique to identify urls.&lt;br /&gt;&lt;br /&gt;The following code shows the definition of TwitterMainSubject:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; TwitterMainSubject user: userName password: pswd  = Subject (&lt;br /&gt;&lt;span class="srctext"&gt;"Main subject."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   &lt;br /&gt;   user = userName.&lt;br /&gt;   password = pswd.&lt;br /&gt;   data&lt;br /&gt;   images = Dictionary new.&lt;br /&gt;   twitterClient = TwitterClient user: userName password:pswd.   &lt;br /&gt;&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;createPresenter ^ &lt;Presenter&gt; = (    &lt;br /&gt;   data:: twitterClient getFriendsTimeline.&lt;br /&gt;   ^TwitterMainPresenter new subject: self&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;twits = (&lt;br /&gt;   data:: twitterClient getFriendsTimeline.&lt;br /&gt;   ^data collect: [:t | TwitSubject withTwit: t images: imagesDictionary].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;updateStatus: statusText = (&lt;br /&gt;   twitterClient updateStatus: statusText.&lt;br /&gt;)&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This class receives the used and password of the Twitter account. The TwitterClient class provides the access to the Twitter services.&lt;br /&gt;&lt;br /&gt;Here's the definition of the TwitterMainPresenter class.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; TwitterMainPresenter = Presenter (&lt;br /&gt;&lt;span class="srctext"&gt;"Presenter for the main section of the GUI client."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   editor&lt;br /&gt;   twitsHolder&lt;br /&gt;   charCountHolder&lt;br /&gt;   &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;(&lt;br /&gt;&lt;br /&gt;definition ^ &amp;lt;Fragment&amp;gt; = (&lt;br /&gt;   ^column: { &lt;br /&gt;        row: { label: &lt;span class="srctext"&gt;'What are you doing?'&lt;/span&gt;.} . &lt;br /&gt;        row: { elastic:twitEditor.} . &lt;br /&gt;        row: { getCharCountHolder.&lt;br /&gt;               filler.&lt;br /&gt;               button: &lt;span class="srctext"&gt;'Update'&lt;/span&gt; action:[updateStatus: (editor editedText asString)].&lt;br /&gt;               blank: 5.&lt;br /&gt;               button: &lt;span class="srctext"&gt;'Refresh'&lt;/span&gt; action:[twitsHolder refresh].&lt;br /&gt;               blank: 5.&lt;br /&gt;             }. &lt;br /&gt;        row: { &lt;br /&gt;               blank: 5.&lt;br /&gt;               elastic:: getTwitsHolder &lt;br /&gt;             }}&lt;br /&gt;))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;getTwitsHolder&lt;/code&gt; method create an instance of an &lt;code&gt;HolderComposer&lt;/code&gt; object that allows the content to be recalculated using the &lt;code&gt;refresh&lt;/code&gt; method. Here's the definition:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;getTwitsHolder = (&lt;br /&gt;   twitsHolder:: holder: [ list:: subject twits collect: [ :i | i presenter  ] ].&lt;br /&gt;   ^twitsHolder.&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice also that here we are requesting the list of &lt;span style="font-style:italic;"&gt;twits&lt;/span&gt; to the subject, which calls the web service again getting new content.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Final words&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The experience of using the Newspeak and the Hopscotch framework to create this program was very nice. &lt;br /&gt;&lt;br /&gt;One thing that I need to find out is how to prevent the application from blocking when requesting the data from the services.&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://langexplr.googlepages.com/nspktwitclient.zip"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-314790409648896411?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/314790409648896411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=314790409648896411' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/314790409648896411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/314790409648896411'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/04/writing-small-twitter-client-with.html' title='Writing a small Twitter client with Newspeak and Hopscotch'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_qePSufqunG4/SeRrv-iuoSI/AAAAAAAAAOw/n-HNh_Uh8H0/s72-c/nspktwitterclient.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-2587741689963170343</id><published>2009-04-02T06:40:00.003-06:00</published><updated>2009-04-02T06:43:44.841-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='newspeak'/><title type='text'>Parsing JSON with Newspeak</title><content type='html'>In this post I'm going to show a JSON parser written using the Newspeak parser combinator library.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Newspeak&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Newspeak is a new programmming language. From its webpage &lt;a href="http://newspeaklanguage.org/"&gt;http://newspeaklanguage.org/&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Newspeak is a new programming language in the tradition of Self and Smalltalk. Newspeak is highly dynamic and reflective  - but designed to support modularity and security. It supports both object-oriented and functional programming.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://bracha.org/newspeak.pdf"&gt;The Newspeak Programming Platform&lt;/a&gt; the authors give a nice introduction to the language and platform.&lt;br /&gt;&lt;br /&gt;The first time I heard about Newspeak was by watching the Lang.NET 2008 symposium presentation video by &lt;a href="http://bracha.org/Site/Home.html"&gt;Gilad Braha&lt;/a&gt; (available &lt;a href="http://www.langnetsymposium.com/2008/talks.aspx"&gt;here&lt;/a&gt;). In this video, a nice parser combinator library is presented . This parser combinator library is described in the  &lt;a href="http://bracha.org/executableGrammars.pdf"&gt;Executable Grammars in Newspeak&lt;/a&gt; paper by Gilad Bracha.&lt;br /&gt;&lt;br /&gt;Code in this post was written using the &lt;a href="http://newspeaklanguage.org/downloads/"&gt;Newspeak prototype&lt;/a&gt; released February 27 2009. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;JSON&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In order to learn about the language and platform I decided to create a little parser for JSON (Javascript Object Notation). &lt;br /&gt;&lt;br /&gt;JSON is a  simple data-interchange format defined in &lt;a href="http://www.json.org/"&gt;http://www.json.org/&lt;/a&gt; .An example of it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;[{ "name": "Wiston Smith",&lt;br /&gt;   "description"  :"Protagonist"},&lt;br /&gt; { "name": "Julia",&lt;br /&gt;   "description"  :"Lover"},&lt;br /&gt; { "name": "O Brien",&lt;br /&gt;   "description"  :"Goverment agent"}]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Parser structure&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The parser is defined as a single class with a couple of nested classes. The following image shows the definition of JSON Parser in the Newspeak environment.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_qePSufqunG4/SdScW2VnXQI/AAAAAAAAAOo/0OtVR5h5fAs/s1600-h/nsjsonparserclass.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 276px;" src="http://1.bp.blogspot.com/_qePSufqunG4/SdScW2VnXQI/AAAAAAAAAOo/0OtVR5h5fAs/s320/nsjsonparserclass.png" border="0" alt="definition of the JSONParser class"id="BLOGGER_PHOTO_ID_5320048976188628226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As described in the "Modularity" section of the  &lt;a href="http://bracha.org/newspeak.pdf"&gt;The Newspeak Programming Platform&lt;/a&gt; paper, top-level classes (in this case JSONParser) doesn't have access to its surrounding scope, it only has access to its own or inherited definitions. This is the reason why the &lt;code&gt;JSONParser&lt;/code&gt; has the following definitions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; JSONParser withParserLib: parserLibrary usingLib: platform =  (&lt;br /&gt;&lt;span class="srctext"&gt;"Experiment for JSON parser based on the description from http://www.json.org/fatfree.html "&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;ExecutableGrammar&lt;/span&gt; = parserLibrary ExecutableGrammar.&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;CharParser&lt;/span&gt; = parserLibrary CharParser.&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;PredicateTokenParser&lt;/span&gt; = parserLibrary PredicateTokenParser.&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Dictionary&lt;/span&gt; = platform Dictionary.&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;OrderedCollection&lt;/span&gt; = platform OrderedCollection.&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Number&lt;/span&gt; = platform Number.&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;The "&lt;code&gt;withParserLib: parserLibrary usingLib: platform&lt;/code&gt;" part defines parameters for the construction of &lt;code&gt;JSONParser&lt;/code&gt;. These parameters are used to 'import' classes defined elsewhere.&lt;br /&gt;&lt;br /&gt;The following code shows a way to create an instance of the JSONParser class:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;    |platform parser|&lt;br /&gt;    platform:: Platform new.&lt;br /&gt;    parser = (JSONParser withParserLib: (BlocklessCombinatorialParsing usingLib: platform) usingLib: platform).&lt;br /&gt;    ... &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The JSONParser nested classes are the following:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;code&gt;CharExceptForParser&lt;/code&gt; which is a parser that accepts any character except for the one specified (this is for internal use)&lt;/li&gt;&lt;li&gt;&lt;code&gt;JSONGrammar&lt;/code&gt; The definition of the JSON grammar&lt;/li&gt;&lt;li&gt;&lt;code&gt;JSONGrammarWithAST&lt;/code&gt; which defines the way the AST is created&lt;/li&gt;&lt;li&gt;&lt;code&gt;JSONObject&lt;/code&gt; which is used in the representation of the JSON AST&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Grammar&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The following code shows the JSON grammar defined using the parsing combinators:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class &lt;b&gt;JSONGrammar&lt;/b&gt; = ExecutableGrammar (&lt;br /&gt;&lt;span class="srctext"&gt;"Experiment for JSON grammar based on the description from http://www.json.org/fatfree.html "&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   &lt;b&gt;doubleQuote&lt;/b&gt; = (char: $").&lt;br /&gt;   &lt;b&gt;backslash&lt;/b&gt; = (char: $\).&lt;br /&gt;   &lt;b&gt;str&lt;/b&gt; = doubleQuote,((backslash, ( char: $" ))   | &lt;br /&gt;                                  (backslash, ( char: $/ ))  |&lt;br /&gt;                                  (backslash, backslash)    |&lt;br /&gt;                                  (backslash, ( char: $r ))   |&lt;br /&gt;                                  (backslash, ( char: $n ))   |&lt;br /&gt;                                  (backslash, ( char: $t ))   |&lt;br /&gt;                                  (charExceptFor: $")) star, doubleQuote.&lt;br /&gt;   &lt;b&gt;string&lt;/b&gt; = tokenFor: str.&lt;br /&gt;   &lt;br /&gt;   &lt;b&gt;negSign&lt;/b&gt; = (char: $-).&lt;br /&gt;   &lt;b&gt;plusSign&lt;/b&gt; = (char: $+).&lt;br /&gt;   &lt;b&gt;digit&lt;/b&gt; = (charBetween: $0 and: $9).&lt;br /&gt;   &lt;b&gt;dot&lt;/b&gt; = (char: $. ) .&lt;br /&gt;   &lt;b&gt;num&lt;/b&gt; = negSign opt, digit, digit star, dot opt,digit star, ((char: $e) | (char: $E)) opt, (plusSign | negSign) opt,digit star.&lt;br /&gt;   &lt;b&gt;number&lt;/b&gt; = tokenFor: num.&lt;br /&gt;   &lt;br /&gt;   &lt;b&gt;leftbrace&lt;/b&gt; = tokenFromChar: ${.&lt;br /&gt;   &lt;b&gt;rightbrace&lt;/b&gt; =tokenFromChar: $}.&lt;br /&gt;   &lt;b&gt;colon&lt;/b&gt; = tokenFromChar: $:.&lt;br /&gt;   &lt;b&gt;comma&lt;/b&gt; = tokenFromChar: $,.&lt;br /&gt;   &lt;b&gt;definition&lt;/b&gt; = string,colon,value.&lt;br /&gt;   &lt;b&gt;obj&lt;/b&gt; =  leftbrace,  (definition starSeparatedBy: comma),rightbrace.&lt;br /&gt;   &lt;b&gt;object&lt;/b&gt; = tokenFor: obj.&lt;br /&gt;&lt;br /&gt;   &lt;b&gt;leftbracket&lt;/b&gt; = tokenFromChar: $[.&lt;br /&gt;   &lt;b&gt;rightbracket&lt;/b&gt; = tokenFromChar: $].&lt;br /&gt;   &lt;b&gt;arr&lt;/b&gt; = leftbracket, (value starSeparatedBy: comma), rightbracket.&lt;br /&gt;   &lt;b&gt;array&lt;/b&gt; = tokenFor: arr.&lt;br /&gt;&lt;br /&gt;   &lt;b&gt;ttrue&lt;/b&gt; = tokenFromSymbol: #true.&lt;br /&gt;   &lt;b&gt;tfalse&lt;/b&gt; = tokenFromSymbol: #false.&lt;br /&gt;   &lt;b&gt;null&lt;/b&gt; = tokenFromSymbol: #null.&lt;br /&gt;&lt;br /&gt;   &lt;b&gt;value&lt;/b&gt; = string | number | object | array | ttrue | tfalse | null. &lt;br /&gt;   &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For more information on the how this library works, check the &lt;a href="http://bracha.org/executableGrammars.pdf"&gt;Executable Grammars in Newspeak&lt;/a&gt; paper.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;AST construction&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;We need to define a way to represent the tree structure(AST) parsed by JSONGrammar. As described in the "Executable Grammars is Newspeak" paper, one of the nice things about Newspeak is that we don't have the modify the grammar definition to add AST construction code. We can do that by inheriting from the original grammar:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; JSONGrammarWithAST = JSONGrammar(&lt;br /&gt;&lt;span class="srctext"&gt;"Parses a JSON File and generates and Ast"&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   &lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;('as yet unclassified'&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;array&lt;/span&gt; = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; array wrapper: [:a | (a token at: 2)  ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;null&lt;/span&gt; = (&lt;br /&gt;   ^ &lt;span class="srckeyw"&gt;super&lt;/span&gt; null wrapper: [:o | nil].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;number&lt;/span&gt; = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; number wrapper: [:o | Number readFrom: (flattenCharCollectionToString: (o token)) ].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;object&lt;/span&gt;  = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; object wrapper: &lt;br /&gt;         [:obj | JSONObject withContent: &lt;br /&gt;                     (Dictionary newFrom: ((obj token at: 2) collect: [:e | (e at: 1) -&gt; (e at: 3)]))].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;parse: input  = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; value parse: input.&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;string&lt;/span&gt;  = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; string wrapper: &lt;br /&gt;          [:t | flattenCollectedString: (t token at: 2)].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;tfalse&lt;/span&gt;  = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; tfalse wrapper: [:o | false].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ttrue&lt;/span&gt; = (&lt;br /&gt;   ^&lt;span class="srckeyw"&gt;super&lt;/span&gt; ttrue wrapper: [:o | true].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As shown here (omitting  some method definitions) the arrays are converted to Ordered collections, the numbers,strings,booleans to its equivalents and JSON objects to instances of JSONObject(described below).&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;JSONObject&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In order to make it easy to use  a JSON object in Newspeak the JSONParser class was defined:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; JSONObject withContent: dContent =  (&lt;br /&gt;&lt;span class="srctext"&gt;"Instances of this class represent JSON objects."&lt;/span&gt;&lt;br /&gt;|&lt;br /&gt;   content = dContent.&lt;br /&gt;|&lt;br /&gt;)&lt;br /&gt;('as yet unclassified'&lt;br /&gt;doesNotUnderstand: message = (&lt;br /&gt;      | fieldName |&lt;br /&gt;      fieldName:: message selector string.&lt;br /&gt;      (fieldName beginsWith: 'json_')  &lt;br /&gt;             ifTrue: [fieldName:: fieldName allButFirst: 5].&lt;br /&gt;      ^content  at: fieldName ifAbsent: [nil].&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This class receives a &lt;code&gt;Dicionary&lt;/code&gt; as parameter. This dictionary contains all the name/value pairs of the JSON object definition. We create a definition of the &lt;code&gt;doesNotUnderstand&lt;/code&gt; method which  as in Smalltalk is called when a message sent to an object doesn't have a explicit way to respond it. We take the name of the message being called and check it against the dictionary.&lt;br /&gt;&lt;br /&gt;If the message is prefixed by 'json_', the string after it is used as the key in the dictionary. This is defined this way because JSONObject has definitions inherited from Object (such as 'name').&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;...&lt;br /&gt;| parsed |&lt;br /&gt;parsed:: parserWithAST &lt;br /&gt;                     parse: (streamFromString: &lt;span class="srctext"&gt;'[{ "name": "Wiston Smith",&lt;br /&gt;                                                   "description"  :"Protagonist"},&lt;br /&gt;                                                 { "name": "Julia",&lt;br /&gt;                                                   "description"  :"Lover"},&lt;br /&gt;                                                 { "name": "O Brien",&lt;br /&gt;                                                   "description"  :"Goverment agent"}]'&lt;/span&gt;).&lt;br /&gt;assert:[((parsed at: 2) description)  = &lt;span class="srctext"&gt;'Lover'&lt;/span&gt;].&lt;br /&gt;assert:[((parsed at: 3) json_name)  = &lt;span class="srctext"&gt;'O Brien'&lt;/span&gt;].&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the following post I'm going to use this parser to explore the GUI library provided with Newspeak.&lt;br /&gt;&lt;br /&gt;Code for this post can be found &lt;a href="http://langexplr.googlepages.com/jsonparserns.tgz"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-2587741689963170343?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/2587741689963170343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=2587741689963170343' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2587741689963170343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2587741689963170343'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/04/parsing-json-with-newspeak.html' title='Parsing JSON with Newspeak'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_qePSufqunG4/SdScW2VnXQI/AAAAAAAAAOo/0OtVR5h5fAs/s72-c/nsjsonparserclass.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-2512903804330536928</id><published>2009-03-15T07:55:00.001-06:00</published><updated>2009-03-15T07:57:09.386-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='abcexplorationlib'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>Support for the LookupSwitch opcode in AbcExplorationLib</title><content type='html'>The LookupSwitch &lt;a href="http://www.adobe.com/devnet/actionscript/articles/avm2overview.pdf"&gt;AVM2&lt;/a&gt; opcode is used to represent the ActionScript &lt;a href="http://livedocs.adobe.com/specs/actionscript/3/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=as3_specification157.html"&gt;&lt;code&gt;switch&lt;/code&gt; statement&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;This is an interesting branch instruction because it has multiple targets. It is almost a direct translation of the switch statement because it has two parameters, a default case and an array of possible targets.&lt;br /&gt;&lt;br /&gt;Recently support for this opcode was added to &lt;a href="http://abcexplorationlib.codeplex.com"&gt;AbcExplorationLib&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Given the following ActionScript code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;var&lt;/span&gt; x;&lt;br /&gt;&lt;span class="srckeyw"&gt;for&lt;/span&gt;(x = 1;x &lt; 5;x++) {&lt;br /&gt;   &lt;span class="srckeyw"&gt;switch&lt;/span&gt;(x) {&lt;br /&gt;      &lt;span class="srckeyw"&gt;case&lt;/span&gt; 1:&lt;br /&gt;        print(&lt;span class="srctext"&gt;"one"&lt;/span&gt;);&lt;br /&gt;        &lt;span class="srckeyw"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span class="srckeyw"&gt;case&lt;/span&gt; 2:&lt;br /&gt;        print(&lt;span class="srctext"&gt;"two"&lt;/span&gt;);&lt;br /&gt;        &lt;span class="srckeyw"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span class="srckeyw"&gt;case&lt;/span&gt; 3:&lt;br /&gt;        print(&lt;span class="srctext"&gt;"three"&lt;/span&gt;);&lt;br /&gt;        &lt;span class="srckeyw"&gt;break&lt;/span&gt;;&lt;br /&gt;      &lt;span class="srckeyw"&gt;case&lt;/span&gt; 4:&lt;br /&gt;        print(&lt;span class="srctext"&gt;"four"&lt;/span&gt;);&lt;br /&gt;        &lt;span class="srckeyw"&gt;break&lt;/span&gt;;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We compile this file to a .abc file using the following command:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ java -jar /opt/flex3sdk/lib/asc.jar  testswitch.as &lt;br /&gt;&lt;br /&gt;testswitch.abc, 280 bytes written&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By using a little &lt;a href="http://abcexplorationlib.codeplex.com/SourceControl/changeset/view/25973#495988"&gt;IronPython example&lt;/a&gt; included with AbcExplorationLib we can see how this library interprets the LookupSwitch opcode:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ mono /opt/IronPython-2.0/ipy.exe  ../ipyexample/abccontents.py testswitch.abc &lt;br /&gt;...&lt;br /&gt;Instructions:&lt;br /&gt;   getlocal_0 &lt;br /&gt;   pushscope &lt;br /&gt;   pushbyte 1&lt;br /&gt;   getglobalscope &lt;br /&gt;   swap &lt;br /&gt;   setslot 1&lt;br /&gt;   jump dest177&lt;br /&gt;dest12:&lt;br /&gt;   label &lt;br /&gt;   jump dest74&lt;br /&gt;dest17:&lt;br /&gt;   label &lt;br /&gt;   findpropertystrict M.print&lt;br /&gt;   pushstring "one"&lt;br /&gt;   callprop M.print&lt;br /&gt;   pop &lt;br /&gt;   jump dest165&lt;br /&gt;dest30:&lt;br /&gt;   label &lt;br /&gt;   findpropertystrict M.print&lt;br /&gt;   pushstring "two"&lt;br /&gt;   callprop M.print&lt;br /&gt;   pop &lt;br /&gt;   jump dest165&lt;br /&gt;dest43:&lt;br /&gt;   label &lt;br /&gt;   findpropertystrict M.print&lt;br /&gt;   pushstring "three"&lt;br /&gt;   callprop M.print&lt;br /&gt;   pop &lt;br /&gt;   jump dest165&lt;br /&gt;dest56:&lt;br /&gt;   label &lt;br /&gt;   findpropertystrict M.print&lt;br /&gt;   pushstring "four"&lt;br /&gt;   callprop M.print&lt;br /&gt;   pop &lt;br /&gt;   jump dest165&lt;br /&gt;dest69:&lt;br /&gt;   label &lt;br /&gt;   jump dest165&lt;br /&gt;dest74:&lt;br /&gt;   getglobalscope &lt;br /&gt;   getslot 1&lt;br /&gt;   setlocal_1 &lt;br /&gt;   pushbyte 1&lt;br /&gt;   getlocal_1 &lt;br /&gt;   ifstrictneq dest91&lt;br /&gt;   pushshort 0&lt;br /&gt;   jump dest143&lt;br /&gt;dest91:&lt;br /&gt;   pushbyte 2&lt;br /&gt;   getlocal_1 &lt;br /&gt;   ifstrictneq dest104&lt;br /&gt;   pushshort 1&lt;br /&gt;   jump dest143&lt;br /&gt;dest104:&lt;br /&gt;   pushbyte 3&lt;br /&gt;   getlocal_1 &lt;br /&gt;   ifstrictneq dest117&lt;br /&gt;   pushshort 2&lt;br /&gt;   jump dest143&lt;br /&gt;dest117:&lt;br /&gt;   pushbyte 4&lt;br /&gt;   getlocal_1 &lt;br /&gt;   ifstrictneq dest130&lt;br /&gt;   pushshort 3&lt;br /&gt;   jump dest143&lt;br /&gt;dest130:&lt;br /&gt;   pushfalse &lt;br /&gt;   iffalse SolvedReference dest141&lt;br /&gt;   pushshort 4&lt;br /&gt;   jump dest143&lt;br /&gt;dest141:&lt;br /&gt;   pushshort 4&lt;br /&gt;dest143:&lt;br /&gt;   kill &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;   lookupswitch dest69 dest17,dest30,dest43,dest56,dest69&lt;/span&gt;&lt;br /&gt;dest165:&lt;br /&gt;   getglobalscope &lt;br /&gt;   getslot 1&lt;br /&gt;   increment &lt;br /&gt;   setlocal_1 &lt;br /&gt;   getlocal_1 &lt;br /&gt;   getglobalscope &lt;br /&gt;   swap &lt;br /&gt;   setslot 1&lt;br /&gt;   kill &lt;br /&gt;dest177:&lt;br /&gt;   getglobalscope &lt;br /&gt;   getslot 1&lt;br /&gt;   pushbyte 5&lt;br /&gt;   iflt dest12&lt;br /&gt;   returnvoid &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As described in the documentation the parameters of the LookupSwitch instruction are specified as relative byte  offsets that specify the target. In order to give a higher level representation of the code, these relative offsets are converted to symbolic references. This process is detailed in the &lt;a href="http://langexplr.blogspot.com/2008/10/using-f-active-patterns-to-encapsulate.html"&gt;"Using F# Active Patterns to encapsulate complex conditions"&lt;/a&gt; post.&lt;br /&gt;&lt;br /&gt;This process starts in the following functions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;member&lt;/span&gt; ReadAndProcessInstructions(aInput:BinaryReader,&lt;br /&gt;                                         count,&lt;br /&gt;                                         constantPool:ConstantPoolInfo) = &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; instructionsAndOffsets = &lt;br /&gt;               (AvmMethodBody.ReadingInstructions([],&lt;br /&gt;                                                  aInput,&lt;br /&gt;                                                  count,&lt;br /&gt;                                                  constantPool)) &lt;span class="srckeyw"&gt;in&lt;/span&gt;        &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; destinations = &lt;br /&gt;               AvmMethodBody.CollectDestinations(instructionsAndOffsets,&lt;br /&gt;                                                 Map.empty,&lt;br /&gt;                                                 instructionsAndOffsets)&lt;br /&gt;   &lt;span class="srckeyw"&gt;in&lt;/span&gt;&lt;br /&gt;      AvmMethodBody.UpdateCodeWithDestinations(&lt;br /&gt;                                    destinations,&lt;br /&gt;                                    instructionsAndOffsets,[]) |&gt; List.to_array&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;CollectDestinations&lt;/code&gt; method collects all the absolute offsets used by branch instructions and stores them in a dictionary with a generated label. The &lt;code&gt;UpdateCodeWithDestinations&lt;/code&gt; method modifies the instruction list use the generated labels.&lt;br /&gt;&lt;br /&gt;For example to add support in &lt;code&gt;CollectDestinations&lt;/code&gt; the following code was added:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;member&lt;/span&gt; CheckLookupSwitchCase  baseOffset&lt;br /&gt;                                      (totalInstructions:(int64*AbcFileInstruction)&lt;br /&gt;                                      list) =&lt;br /&gt;    &lt;span class="srckeyw"&gt;fun&lt;/span&gt; (destinations:Map&amp;lt;int64,string&amp;gt;) target  -&amp;gt;&lt;br /&gt;       &lt;span class="srckeyw"&gt;match&lt;/span&gt; target &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;       | UnSolvedReference(relativeOffset) when&lt;br /&gt;           (AvmMethodBody.IsDestinationDefined(int(baseOffset+relativeOffset),&lt;br /&gt;                                               totalInstructions)) -&amp;gt;&lt;br /&gt;                 destinations.Add(int64(baseOffset+relativeOffset),&lt;br /&gt;                                  sprintf &lt;span class="srctext"&gt;"dest%d"&lt;/span&gt; (baseOffset+relativeOffset))&lt;br /&gt;       | _ -&amp;gt; destinations&lt;br /&gt;&lt;br /&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;member&lt;/span&gt;  CollectDestinations(instructions:(int64*AbcFileInstruction) list, &lt;br /&gt;                                    destinations:Map&amp;lt;int64,string&amp;gt;,&lt;br /&gt;                                    totalInstructions:(int64*AbcFileInstruction) list) =&lt;br /&gt;    &lt;span class="srckeyw"&gt;match&lt;/span&gt; instructions &lt;span class="srckeyw"&gt;with&lt;/span&gt; &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;    ...&lt;/span&gt;&lt;br /&gt;    | ((offset,(LookupSwitch(defaultBranch,cases)))::rest) -&amp;gt;&lt;br /&gt;           let baseOffset = int(offset) in&lt;br /&gt;            AvmMethodBody.CollectDestinations(rest,&lt;br /&gt;                                    Seq.append [defaultBranch] cases |&amp;gt;                                        &lt;br /&gt;                                    Seq.fold (AvmMethodBody.CheckLookupSwitchCase baseOffset totalInstructions ) destinations,&lt;br /&gt;                                    totalInstructions)&lt;br /&gt;  &lt;span style="font-weight:bold;"&gt; ...&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then the code is modified in the &lt;code&gt;UpdateCodeWithDestinations&lt;/code&gt; method to use the generated labels.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; &lt;span class="srckeyw"&gt;static&lt;/span&gt; &lt;span class="srckeyw"&gt;member&lt;/span&gt; UpdateCodeWithDestinations(destinations:Map&amp;lt;int64,string&amp;gt;,&lt;br /&gt;                                          instructions,&lt;br /&gt;                                          resultingInstructions) =&lt;br /&gt;    &lt;span class="srckeyw"&gt;let&lt;/span&gt; processedInstructions = &lt;br /&gt;          &lt;span class="srckeyw"&gt;match&lt;/span&gt; instructions &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;   ...&lt;/span&gt;&lt;br /&gt;          | ((offset,LookupSwitch(defaultCase,cases))::rest) -&amp;gt;                 &lt;br /&gt;             (offset,&lt;br /&gt;                LookupSwitch(AvmMethodBody.SolveSwitchCase defaultCase offset destinations,&lt;br /&gt;                             Array.map (fun c-&amp;gt;AvmMethodBody.SolveSwitchCase c offset destinations) cases))::rest&lt;br /&gt;          | _ -&amp;gt; instructions&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;   ...&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-2512903804330536928?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/2512903804330536928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=2512903804330536928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2512903804330536928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2512903804330536928'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/03/support-for-lookupswitch-opcode-in.html' title='Support for the LookupSwitch opcode in AbcExplorationLib'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-4787709424168283391</id><published>2009-03-03T07:20:00.002-06:00</published><updated>2009-03-03T07:28:53.906-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='abcexplorationlib'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>Manipulating AVM2 byte code with F#</title><content type='html'>In this post I'm going to show an example of using &lt;a href="http://www.codeplex.com/AbcExplorationLib"&gt;AbcExplorationLib&lt;/a&gt; to manipulate simple AVM2 byte code (&lt;a href="http://en.wikipedia.org/wiki/Actionscript"&gt;ActionScript&lt;/a&gt;). This example show how load a .ABC file and write it back to disk.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.codeplex.com/AbcExplorationLib"&gt;AbcExplorationLib&lt;/a&gt; is a library that will allow the manipulation of AVM2 Byte Code(described &lt;a href="http://www.adobe.com/devnet/actionscript/articles/avm2overview.pdf"&gt;here&lt;/a&gt;). Although it's still incomplete, some basic examples work as the ones presented in this post .&lt;br /&gt;&lt;br /&gt;The following ActionScript code will be compiled to byte code .&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;var&lt;/span&gt; i = 0;&lt;br /&gt;&lt;span class="srckeyw"&gt;for&lt;/span&gt;( i = 0;i &amp;lt; 10;i++) {&lt;br /&gt;   print(&lt;span class="srctext"&gt;"inside loop"&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;print(&lt;span class="srctext"&gt;"Done"&lt;/span&gt;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To generate the ".abc" file we type:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;c:\test\&amp;gt; java -jar c:\flexsdk\lib\asc.jar test.as&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Loading the compiled file&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;We're going to use the F# REPL(fsi.exe) to manipulate the file. We start by referencing the library.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; #r "abcexplorationlib.dll";;&lt;br /&gt;&lt;br /&gt;--&amp;gt; Referenced 'C:\test\abcexplorationlib.dll'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;gt;  open Langexplr.Abc;;&lt;br /&gt;&lt;br /&gt;Now we load the file:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt;   let abcFile = using (new System.IO.FileStream("test.abc",System.IO.FileMode.Open)) ( &lt;br /&gt;                    fun s -&gt; AvmAbcFile.Create(s));;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now &lt;code&gt;abcFile&lt;/code&gt; contains the code of the compiled program.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; abcFile;;&lt;br /&gt;val it : AvmAbcFile&lt;br /&gt;= Langexplr.Abc.AvmAbcFile {Classes = [];&lt;br /&gt;                            Scripts = [Langexplr.Abc.AvmScript];}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Inspecting the instructions&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;We're interested in the instructions of the top-level script for this .abc file. By typing the following expression we can get to this section:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; abcFile.Scripts.[0].InitMethod.Body.Value.Instructions;;&lt;br /&gt;val it : AbcFileInstruction array&lt;br /&gt;= [|GetLocal0; PushScope; PushByte 0uy; GetGlobalScope; Swap; SetSlot 1;&lt;br /&gt;    PushByte 0uy; GetGlobalScope; Swap; SetSlot 1;&lt;br /&gt;    Jump (SolvedReference "dest39"); ArtificialCodeBranchLabel "dest18"; Label&lt;br /&gt;    FindPropertyStrict&lt;br /&gt;      (MQualifiedName&lt;br /&gt;         ([|Ns ("",CONSTANT_Namespace); Ns ("test.as$0",CONSTANT_PrivateNs)|],&lt;br /&gt;          "print")); PushString "inside loop";&lt;br /&gt;    CallProperty&lt;br /&gt;      (MQualifiedName&lt;br /&gt;         ([|Ns ("",CONSTANT_Namespace); Ns ("test.as$0",CONSTANT_PrivateNs)|],&lt;br /&gt;          "print"),1); Pop; GetGlobalScope; GetSlot 1; Increment; SetLocal_2;&lt;br /&gt;    GetLocal2; GetGlobalScope; Swap; SetSlot 1; Kill 2;&lt;br /&gt;    ArtificialCodeBranchLabel "dest39"; GetGlobalScope; GetSlot 1;&lt;br /&gt;    PushByte 10uy; IfLt (SolvedReference "dest18");&lt;br /&gt;    FindPropertyStrict&lt;br /&gt;      (MQualifiedName&lt;br /&gt;         ([|Ns ("",CONSTANT_Namespace); Ns ("test.as$0",CONSTANT_PrivateNs)|],&lt;br /&gt;          "print")); PushString "Done";&lt;br /&gt;    CallProperty&lt;br /&gt;      (MQualifiedName&lt;br /&gt;         ([|Ns ("",CONSTANT_Namespace); Ns ("test.as$0",CONSTANT_PrivateNs)|],&lt;br /&gt;          "print"),1); CoerceA; SetLocal_1; GetLocal1; ReturnValue; Kill 1|]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We're going to define the following function to assist in the presentation of instruction listings.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; open Langexplr.Abc.InstructionPatterns;;&lt;br /&gt;&amp;gt; let pr (i:AbcFileInstruction) =&lt;br /&gt;-            match i with&lt;br /&gt;-            | ArtificialCodeBranchLabel t -&amp;gt; printf "%s:\n" &amp;lt;| t.ToString()&lt;br /&gt;-            | i &amp; UnsolvedSingleBranchInstruction(d,_) -&amp;gt; printf " %s %d\n" i.Name d&lt;br /&gt;-            | i &amp; SolvedSingleBranchInstruction(l,_) -&amp;gt; printf " %s %s\n" i.Name l&lt;br /&gt;-            | _ -&amp;gt; printf " %s\n" i.Name;;&lt;br /&gt;&lt;br /&gt;val pr : AbcFileInstruction -&amp;gt; unit&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we can type:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; abcFile.Scripts.[0].InitMethod.Body.Value.Instructions |&amp;gt; Array.iter pr;;&lt;br /&gt; getlocal_0&lt;br /&gt; pushscope&lt;br /&gt; pushbyte&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt; pushbyte&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt; jump dest39&lt;br /&gt;dest18:&lt;br /&gt; label&lt;br /&gt; findpropertystrict&lt;br /&gt; pushstring&lt;br /&gt; callprop&lt;br /&gt; pop&lt;br /&gt; getglobalscope&lt;br /&gt; getslot&lt;br /&gt; increment&lt;br /&gt; setlocal_2&lt;br /&gt; getlocal_2&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt; kill&lt;br /&gt;dest39:&lt;br /&gt; getglobalscope&lt;br /&gt; getslot&lt;br /&gt; pushbyte&lt;br /&gt; iflt dest18&lt;br /&gt; findpropertystrict&lt;br /&gt; pushstring&lt;br /&gt; callprop&lt;br /&gt; coerce_a&lt;br /&gt; setlocal_1&lt;br /&gt; getlocal_1&lt;br /&gt; returnvalue&lt;br /&gt; kill&lt;br /&gt;val it : unit = ()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;A note on branch instructions&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;In order to make it easy to manipulate and analyze the code AbcExplorationLib adds a non-existing instruction called &lt;code&gt;ArtificialCodeBranchLabel&lt;/code&gt; to mark the position where a branch instruction will jump.  When these labels are generated the branch instructions are modified to point to the label's name instead of a relative byte offset. Details on how this process is briefly described in &lt;a href="http://langexplr.blogspot.com/2008/10/using-f-active-patterns-to-encapsulate.html"&gt;"Using F# Active Patterns to encapsulate complex conditions"&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Converting from label references to byte offsets is also necessary to write code back to an  &lt;code&gt;.abc&lt;/code&gt; file. This process is performed by a function called &lt;code&gt;ConvertSymbolicLabelsToByteReferences&lt;/code&gt;, for example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; let c = AbcFileCreator();;&lt;br /&gt;&lt;br /&gt;val c : AbcFileCreator&lt;br /&gt;&lt;br /&gt;&amp;gt; abcFile.Scripts.[0].InitMethod.Body.Value.Instructions |&amp;gt;&lt;br /&gt;-      InstructionManipulation.ConvertSymbolicLabelsToByteReferences c |&amp;gt;&lt;br /&gt;-      Array.iter pr;;&lt;br /&gt; getlocal_0&lt;br /&gt; pushscope&lt;br /&gt; pushbyte&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt; pushbyte&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt;&lt;span style="font-weight:bold;"&gt; jump 21&lt;/span&gt;&lt;br /&gt;dest18:&lt;br /&gt; label&lt;br /&gt; findpropertystrict&lt;br /&gt; pushstring&lt;br /&gt; callprop&lt;br /&gt; pop&lt;br /&gt; getglobalscope&lt;br /&gt; getslot&lt;br /&gt; increment&lt;br /&gt; setlocal_2&lt;br /&gt; getlocal_2&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt; kill&lt;br /&gt;dest39:&lt;br /&gt; getglobalscope&lt;br /&gt; getslot&lt;br /&gt; pushbyte&lt;br /&gt;&lt;span style="font-weight:bold;"&gt; iflt -30&lt;/span&gt;&lt;br /&gt; findpropertystrict&lt;br /&gt; pushstring&lt;br /&gt; callprop&lt;br /&gt; coerce_a&lt;br /&gt; setlocal_1&lt;br /&gt; getlocal_1&lt;br /&gt; returnvalue&lt;br /&gt; kill&lt;br /&gt;val it : unit = ()&lt;br /&gt;&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Modifying the code&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Values for branch instruction targets are adjusted if new code added, for example, lets add some code to print "Hola!" inside the loop.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; let printName = CQualifiedName(Ns("",NamespaceKind.CONSTANT_Namespace),"print"&lt;br /&gt;- ) ;;&lt;br /&gt;&lt;br /&gt;val printName : QualifiedName&lt;br /&gt;&lt;br /&gt;&amp;gt; let printCode = [| FindPropertyStrict printName ;&lt;br /&gt;-                    PushString "Hola!" ;&lt;br /&gt;-                    CallProperty(printName,1);&lt;br /&gt;-                    Pop |] ;;&lt;br /&gt;&lt;br /&gt;val printCode : AbcFileInstruction array&lt;br /&gt;&lt;br /&gt;&amp;gt; Seq.append instr.[0..16] &amp;lt;| Seq.append printCode instr.[17..] |&amp;gt;&lt;br /&gt;-  Seq.to_array |&amp;gt;&lt;br /&gt;-  InstructionManipulation.ConvertSymbolicLabelsToByteReferences c |&amp;gt;&lt;br /&gt;-  Array.iter pr;;&lt;br /&gt; getlocal_0&lt;br /&gt; pushscope&lt;br /&gt; pushbyte&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt; pushbyte&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt;&lt;span style="font-weight:bold;"&gt; jump 29&lt;/span&gt;&lt;br /&gt;dest18:&lt;br /&gt; label&lt;br /&gt; findpropertystrict&lt;br /&gt; pushstring&lt;br /&gt; callprop&lt;br /&gt; pop&lt;br /&gt;&lt;span style="font-weight:bold;"&gt; findpropertystrict&lt;br /&gt; pushstring&lt;br /&gt; callprop&lt;br /&gt; pop&lt;/span&gt;&lt;br /&gt; getglobalscope&lt;br /&gt; getslot&lt;br /&gt; increment&lt;br /&gt; setlocal_2&lt;br /&gt; getlocal_2&lt;br /&gt; getglobalscope&lt;br /&gt; swap&lt;br /&gt; setslot&lt;br /&gt; kill&lt;br /&gt;dest39:&lt;br /&gt; getglobalscope&lt;br /&gt; getslot&lt;br /&gt; pushbyte&lt;br /&gt;&lt;span style="font-weight:bold;"&gt; iflt -38&lt;/span&gt;&lt;br /&gt; findpropertystrict&lt;br /&gt; pushstring&lt;br /&gt; callprop&lt;br /&gt; coerce_a&lt;br /&gt; setlocal_1&lt;br /&gt; getlocal_1&lt;br /&gt; returnvalue&lt;br /&gt; kill&lt;br /&gt;val it : unit = ()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Writing the new file&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;We can write this code back to a .abc file by doing this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt; let newCode =  Seq.append instr.[0..16] &amp;lt;| Seq.append printCode instr.[17..] |&lt;br /&gt;- &amp;gt; Seq.to_array;;&lt;br /&gt;&lt;br /&gt;val newCode : AbcFileInstruction array&lt;br /&gt;&lt;br /&gt;&amp;gt; let newBody = AvmMethodBody(oldbody.Method,&lt;br /&gt;-                    oldbody.MaxStack,&lt;br /&gt;-                    oldbody.LocalCount,&lt;br /&gt;-                    oldbody.InitScopeDepth,&lt;br /&gt;-                    oldbody.MaxScopeDepth,&lt;br /&gt;-                    newCode,&lt;br /&gt;-                    oldbody.Exceptions,&lt;br /&gt;-                    oldbody.Traits);;&lt;br /&gt;&lt;br /&gt;val newBody : AvmMethodBody&lt;br /&gt;&lt;br /&gt;&amp;gt; let newFile = AvmAbcFile( [AvmScript( abcFile.Scripts.[0].InitMethod.CloneWithBody(newBody), abcFile.Scripts.[0].Members)], []);;&lt;br /&gt;&lt;br /&gt;val newFile : AvmAbcFile&lt;br /&gt;&amp;gt; open System.IO;;&lt;br /&gt;&amp;gt; let c = AbcFileCreator();;&lt;br /&gt;&lt;br /&gt;val c : AbcFileCreator&lt;br /&gt;&lt;br /&gt;&amp;gt;&lt;br /&gt;- using (new BinaryWriter(new FileStream("test_modified.abc",FileMode.Create)))&lt;br /&gt;-&lt;br /&gt;-       (fun f -&amp;gt; let file = newFile.ToLowerIr(c) in file.WriteTo(f));;&lt;br /&gt;val it : unit = ()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running this program using Tamarin shows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;c:\test\&amp;gt;avmplus_sd.exe test_modified.abc&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;inside loop&lt;br /&gt;Hola!&lt;br /&gt;Done&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The AbcExplorationLib library is still pretty incomplete. Also there's a lot to improve, for example name handling and instruction modification. Future posts will present new features/experiments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-4787709424168283391?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/4787709424168283391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=4787709424168283391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/4787709424168283391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/4787709424168283391'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/03/manipulating-avm2-byte-code-with-f.html' title='Manipulating AVM2 byte code with F#'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-6940452630257718813</id><published>2009-02-12T05:23:00.002-06:00</published><updated>2009-02-12T05:52:52.399-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><title type='text'>Writing Xml with IronPython, XmlWriter and the 'with' statement</title><content type='html'>This post shows a little example of wrapping calls to &lt;code&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.aspx"&gt;System.Xml.XmlWriter&lt;/a&gt;&lt;/code&gt; inside a Python's &lt;a href="http://docs.python.org/reference/compound_stmts.html#the-with-statement"&gt;'with' statement&lt;/a&gt; using &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Writing Xml&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;While reading some code &lt;a href="http://www.livinglogic.de/Python/xist/Examples.html"&gt;examples&lt;/a&gt; from the &lt;a href="http://www.livinglogic.de/Python/xist/"&gt;XIST&lt;/a&gt; HTML/XML generation library I noticed the nice use of Python's &lt;code&gt;'with'&lt;/code&gt; statement to represent the target HTML or XML. &lt;br /&gt;&lt;br /&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.aspx"&gt;System.Xml.XmlWriter&lt;/a&gt; class provided with .NET already gives you a way to write well formed Xml documents. In this post I'm going to show how to use an XmlWriter instance in conjunction with Python's 'with' statement.&lt;br /&gt;&lt;br /&gt;We want to write the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; __future__ &lt;span class="srckeyw"&gt;import&lt;/span&gt; with_statement&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;w = XmlWriter.Create(System.Console.Out,XmlWriterSettings(Indent=True))&lt;br /&gt;x = XWriter(w)&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;with&lt;/span&gt; x.element(&lt;span class="srctext"&gt;'tableofcontents'&lt;/span&gt;):&lt;br /&gt;    &lt;span class="srckeyw"&gt;with&lt;/span&gt; x.element(&lt;span class="srctext"&gt;'section'&lt;/span&gt;,{&lt;span class="srctext"&gt;'page'&lt;/span&gt; : &lt;span class="srctext"&gt;'10'&lt;/span&gt;}):&lt;br /&gt;       x.text(&lt;span class="srctext"&gt;'Introduction'&lt;/span&gt;)&lt;br /&gt;    &lt;span class="srckeyw"&gt;with&lt;/span&gt; x.element(&lt;span class="srctext"&gt;'section'&lt;/span&gt;,{&lt;span class="srctext"&gt;'page'&lt;/span&gt; : &lt;span class="srctext"&gt;'12'&lt;/span&gt;}):&lt;br /&gt;       x.text(&lt;span class="srctext"&gt;'Main topic'&lt;/span&gt;)&lt;br /&gt;    &lt;span class="srckeyw"&gt;with&lt;/span&gt; x.element(&lt;span class="srctext"&gt;'section'&lt;/span&gt;,{&lt;span class="srctext"&gt;'page'&lt;/span&gt; : &lt;span class="srctext"&gt;'14'&lt;/span&gt;}):&lt;br /&gt;       x.text(&lt;span class="srctext"&gt;'Extra topic'&lt;/span&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To generate the following Xml file:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;tableofcontents&amp;gt;&lt;br /&gt;  &amp;lt;section page="10"&amp;gt;Introduction&amp;lt;/section&amp;gt;&lt;br /&gt;  &amp;lt;section page="12"&amp;gt;Main topic&amp;lt;/section&amp;gt;&lt;br /&gt;  &amp;lt;section page="14"&amp;gt;Extra topic&amp;lt;/section&amp;gt;&lt;br /&gt;&amp;lt;/tableofcontents&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The 'with' statement&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://docs.python.org/reference/compound_stmts.html#the-with-statement"&gt;'with' statement&lt;/a&gt; was introduced in Python 2.5 . This statement is used wrap the execution of a series of statements with some special code. For example it is used to implement the &lt;code&gt;try...except...finally &lt;/code&gt; pattern. &lt;br /&gt;&lt;br /&gt;As described in the &lt;a href="http://docs.python.org/reference/compound_stmts.html#the-with-statement"&gt;documentation &lt;/a&gt; the following statement:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;with &lt;i&gt;&lt;b&gt;context expression&lt;/b&gt;&lt;/i&gt;:&lt;br /&gt;   &lt;i&gt;&lt;b&gt;statements...&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Will be executed as follows:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Evaluate the context expression to obtain the context manager&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Invoke the context manager's &lt;code&gt;__enter__()&lt;/code&gt; method&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Execute the statements&lt;/li&gt;&lt;br /&gt;&lt;li&gt;When the execution of the statements finishes(even with an exception), the context manager's &lt;code&gt;__exit()__&lt;/code&gt; method is called.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Given these steps we're going to implement a context manager that assist in the creation of Xml documents using the &lt;code&gt;System.Xml.XmlWriter&lt;/code&gt; .NET class.&lt;br /&gt;&lt;br /&gt;The following code shows a class that wraps the XmlWriter instance and helps with the creation of context managers:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; XWriter(object):&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,writer):&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.writer = writer&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; element(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,name,atts = {}):&lt;br /&gt;       &lt;span class="srckeyw"&gt;return&lt;/span&gt; ElementCtxt(name,atts,&lt;span class="srckeyw"&gt;self&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; nselement(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,prefix,name,namespace,atts = {}):&lt;br /&gt;       &lt;span class="srckeyw"&gt;return&lt;/span&gt; NamespaceElementCtxt(prefix,name,namespace,atts,&lt;span class="srckeyw"&gt;self&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; text(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,text):&lt;br /&gt;       &lt;span class="srckeyw"&gt;self&lt;/span&gt;.writer.WriteString(text)&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; cdata(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,text):&lt;br /&gt;       &lt;span class="srckeyw"&gt;self&lt;/span&gt;.writer.WriteCData(text)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Notice that the &lt;code&gt;element&lt;/code&gt; method creates an instance of the &lt;code&gt;ElementCtxt&lt;/code&gt; class using the element name and an optional dictionary with the attributes. As the following listing shows this class performs the calls to &lt;a href="http://msdn.microsoft.com/en-us/library/t8t5yhhk.aspx"&gt;WriteStartElement&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.writeendelement.aspx"&gt;WriteEndElement&lt;/a&gt; in the &lt;code&gt;__enter__&lt;/code&gt; and &lt;code&gt;__exit__&lt;/code&gt; methods.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; ElementCtxt(object):&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,elementName,atts,writer):&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.elementName = elementName&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.atts = atts&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.writer = writer&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; processAttributes(&lt;span class="srckeyw"&gt;self&lt;/span&gt;):&lt;br /&gt;      &lt;span class="srckeyw"&gt;for&lt;/span&gt; att &lt;span class="srckeyw"&gt;in&lt;/span&gt; &lt;span class="srckeyw"&gt;self&lt;/span&gt;.atts:&lt;br /&gt;         &lt;span class="srckeyw"&gt;self&lt;/span&gt;.writer.writer.WriteAttributeString(att,&lt;span class="srckeyw"&gt;self&lt;/span&gt;.atts[att].__str__())&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; processStartTag(&lt;span class="srckeyw"&gt;self&lt;/span&gt;):&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.writer.writer.WriteStartElement(&lt;span class="srckeyw"&gt;self&lt;/span&gt;.elementName)&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.processAttributes()&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __enter__(&lt;span class="srckeyw"&gt;self&lt;/span&gt;):&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.processStartTag()&lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; &lt;span class="srckeyw"&gt;self&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __exit__(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,t,v,tr):&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.writer.writer.WriteEndElement()&lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; t == &lt;span class="srckeyw"&gt;None&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;XWriter.nselement&lt;/code&gt; method is used to write elements with namespace and prefix. This call generates an instance of the following context manager:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;class&lt;/span&gt; NamespaceElementCtxt(ElementCtxt):&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; __init__(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,prefix,elementName,namespace,atts,writer):&lt;br /&gt;      ElementCtxt.__init__(&lt;span class="srckeyw"&gt;self&lt;/span&gt;,elementName,atts,writer)&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.namespace = namespace&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.prefix = prefix&lt;br /&gt;   &lt;span class="srckeyw"&gt;def&lt;/span&gt; processStartTag(&lt;span class="srckeyw"&gt;self&lt;/span&gt;):&lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.writer.writer.WriteStartElement(&lt;span class="srckeyw"&gt;self&lt;/span&gt;.prefix,&lt;span class="srckeyw"&gt;self&lt;/span&gt;.elementName,&lt;span class="srckeyw"&gt;self&lt;/span&gt;.namespace)     &lt;br /&gt;      &lt;span class="srckeyw"&gt;self&lt;/span&gt;.processAttributes()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Final example&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The following code shows how to create a little &lt;a href="https://developer.mozilla.org/en/SVG_In_HTML_Introduction"&gt;SVG file&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; __future__ &lt;span class="srckeyw"&gt;import&lt;/span&gt; with_statement&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; xmlwriterw &lt;span class="srckeyw"&gt;import&lt;/span&gt; XWriter&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clr&lt;br /&gt;&lt;br /&gt;clr.AddReference(&lt;span class="srctext"&gt;'System.Xml'&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;from&lt;/span&gt; System.Xml &lt;span class="srckeyw"&gt;import&lt;/span&gt; *&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; System&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;w = XmlWriter.Create(System.Console.Out,\&lt;br /&gt;                     XmlWriterSettings(Indent=True))&lt;br /&gt;x = XWriter(w)&lt;br /&gt;&lt;br /&gt;svgNs = &lt;span class="srctext"&gt;'http://www.w3.org/2000/svg'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;with&lt;/span&gt; x.nselement(&lt;span class="srctext"&gt;'s'&lt;/span&gt;,&lt;span class="srctext"&gt;'svg'&lt;/span&gt;,svgNs,{&lt;span class="srctext"&gt;'version'&lt;/span&gt;: &lt;span class="srctext"&gt;'1.1'&lt;/span&gt;,&lt;br /&gt;                                  &lt;span class="srctext"&gt;'viewBox'&lt;/span&gt;: &lt;span class="srctext"&gt;'0 0 100 100'&lt;/span&gt;,&lt;br /&gt;                                  &lt;span class="srctext"&gt;'style'&lt;/span&gt;:&lt;span class="srctext"&gt;'width:100%; height:100%; position:absolute; top:0; left:0; z-index:-1;'&lt;/span&gt;}):&lt;br /&gt;   &lt;span class="srckeyw"&gt;with&lt;/span&gt; x.nselement(&lt;span class="srctext"&gt;'s'&lt;/span&gt;,&lt;span class="srctext"&gt;'linearGradient'&lt;/span&gt;,svgNs, { &lt;span class="srctext"&gt;'id'&lt;/span&gt; : &lt;span class="srctext"&gt;'gradient'&lt;/span&gt; }):&lt;br /&gt;       &lt;span class="srckeyw"&gt;with&lt;/span&gt; x.nselement(&lt;span class="srctext"&gt;'s'&lt;/span&gt;,&lt;span class="srctext"&gt;'stop'&lt;/span&gt;,svgNs, {&lt;span class="srctext"&gt;'class'&lt;/span&gt; : &lt;span class="srctext"&gt;'begin'&lt;/span&gt;,&lt;br /&gt;                                           &lt;span class="srctext"&gt;'offset'&lt;/span&gt; : &lt;span class="srctext"&gt;'0%'&lt;/span&gt;,&lt;br /&gt;                                           &lt;span class="srctext"&gt;'stop-color'&lt;/span&gt;:&lt;span class="srctext"&gt;'red'&lt;/span&gt;}): &lt;br /&gt;          &lt;span class="srckeyw"&gt;pass&lt;/span&gt;&lt;br /&gt;       &lt;span class="srckeyw"&gt;with&lt;/span&gt; x.nselement(&lt;span class="srctext"&gt;'s'&lt;/span&gt;,&lt;span class="srctext"&gt;'stop'&lt;/span&gt;,svgNs, {&lt;span class="srctext"&gt;'class'&lt;/span&gt; : &lt;span class="srctext"&gt;'end'&lt;/span&gt;,&lt;br /&gt;                                           &lt;span class="srctext"&gt;'offset'&lt;/span&gt; : &lt;span class="srctext"&gt;'100%'&lt;/span&gt;}): &lt;br /&gt;          &lt;span class="srckeyw"&gt;pass&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;with&lt;/span&gt; x.nselement(&lt;span class="srctext"&gt;'s'&lt;/span&gt;,&lt;span class="srctext"&gt;'rect'&lt;/span&gt;,svgNs, { &lt;span class="srctext"&gt;'x'&lt;/span&gt;:0,&lt;br /&gt;                                        &lt;span class="srctext"&gt;'y'&lt;/span&gt;:0,&lt;br /&gt;                                        &lt;span class="srctext"&gt;'width'&lt;/span&gt;:100,&lt;br /&gt;                                        &lt;span class="srctext"&gt;'height'&lt;/span&gt;:100,&lt;br /&gt;                                        &lt;span class="srctext"&gt;'style'&lt;/span&gt;:&lt;span class="srctext"&gt;'fill:url(#gradient)'&lt;/span&gt;} ):&lt;br /&gt;         &lt;span class="srckeyw"&gt;pass&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;for&lt;/span&gt; i &lt;span class="srckeyw"&gt;in&lt;/span&gt; range(1,5):&lt;br /&gt;      &lt;span class="srckeyw"&gt;with&lt;/span&gt; x.nselement(&lt;span class="srctext"&gt;'s'&lt;/span&gt;,&lt;span class="srctext"&gt;'circle'&lt;/span&gt;,svgNs, { &lt;span class="srctext"&gt;'cx'&lt;/span&gt;: 50,&lt;br /&gt;                                             &lt;span class="srctext"&gt;'cy'&lt;/span&gt;: 50,&lt;br /&gt;                                             &lt;span class="srctext"&gt;'r'&lt;/span&gt;: 30 - i*3,&lt;br /&gt;                                             &lt;span class="srctext"&gt;'style'&lt;/span&gt;:&lt;span class="srctext"&gt;'fill:url(#gradient)'&lt;/span&gt;} ):&lt;br /&gt;          &lt;span class="srckeyw"&gt;pass&lt;/span&gt;&lt;br /&gt;   &lt;br /&gt;w.Close()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running this program shows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;s:svg viewBox=&lt;span class="srctext"&gt;"0 0 100 100"&lt;/span&gt; style=&lt;span class="srctext"&gt;"width:100%; height:100%; position:absolute; top:0; left:0; z-index:-1;"&lt;/span&gt; version=&lt;span class="srctext"&gt;"1.1"&lt;/span&gt; xmlns:s=&lt;span class="srctext"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;&amp;gt;&lt;br /&gt;  &amp;lt;s:linearGradient id=&lt;span class="srctext"&gt;"gradient"&lt;/span&gt;&amp;gt;&lt;br /&gt;    &amp;lt;s:stop offset=&lt;span class="srctext"&gt;"0%"&lt;/span&gt; class=&lt;span class="srctext"&gt;"begin"&lt;/span&gt; stop-color=&lt;span class="srctext"&gt;"red"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;s:stop offset=&lt;span class="srctext"&gt;"100%"&lt;/span&gt; class=&lt;span class="srctext"&gt;"end"&lt;/span&gt; /&amp;gt;&lt;br /&gt;  &amp;lt;/s:linearGradient&amp;gt;&lt;br /&gt;  &amp;lt;s:rect x=&lt;span class="srctext"&gt;"0"&lt;/span&gt; height=&lt;span class="srctext"&gt;"100"&lt;/span&gt; width=&lt;span class="srctext"&gt;"100"&lt;/span&gt; style=&lt;span class="srctext"&gt;"fill:url(#gradient)"&lt;/span&gt; y=&lt;span class="srctext"&gt;"0"&lt;/span&gt; /&amp;gt;&lt;br /&gt;  &amp;lt;s:circle cx=&lt;span class="srctext"&gt;"50"&lt;/span&gt; cy=&lt;span class="srctext"&gt;"50"&lt;/span&gt; style=&lt;span class="srctext"&gt;"fill:url(#gradient)"&lt;/span&gt; r=&lt;span class="srctext"&gt;"27"&lt;/span&gt; /&amp;gt;&lt;br /&gt;  &amp;lt;s:circle cx=&lt;span class="srctext"&gt;"50"&lt;/span&gt; cy=&lt;span class="srctext"&gt;"50"&lt;/span&gt; style=&lt;span class="srctext"&gt;"fill:url(#gradient)"&lt;/span&gt; r=&lt;span class="srctext"&gt;"24"&lt;/span&gt; /&amp;gt;&lt;br /&gt;  &amp;lt;s:circle cx=&lt;span class="srctext"&gt;"50"&lt;/span&gt; cy=&lt;span class="srctext"&gt;"50"&lt;/span&gt; style=&lt;span class="srctext"&gt;"fill:url(#gradient)"&lt;/span&gt; r=&lt;span class="srctext"&gt;"21"&lt;/span&gt; /&amp;gt;&lt;br /&gt;  &amp;lt;s:circle cx=&lt;span class="srctext"&gt;"50"&lt;/span&gt; cy=&lt;span class="srctext"&gt;"50"&lt;/span&gt; style=&lt;span class="srctext"&gt;"fill:url(#gradient)"&lt;/span&gt; r=&lt;span class="srctext"&gt;"18"&lt;/span&gt; /&amp;gt;&lt;br /&gt;&amp;lt;/s:svg&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-6940452630257718813?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/6940452630257718813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=6940452630257718813' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/6940452630257718813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/6940452630257718813'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/02/writing-xml-with-ironpython-xmlwriter.html' title='Writing Xml with IronPython, XmlWriter and the &apos;with&apos; statement'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-6626805147292748823</id><published>2009-01-21T06:29:00.001-06:00</published><updated>2009-01-21T06:29:28.136-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ironpython'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Some notes on using F# code from IronPython</title><content type='html'>This post presents a couple of things I learned about the interaction between  &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/fsharp/default.aspx"&gt;F#&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Most information about this topic can be found by looking at the code generated by the F# compiler, using tools like &lt;a href="http://msdn.microsoft.com/en-us/library/f7dy01k1(VS.80).aspx"&gt;ILDASM&lt;/a&gt; or &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Reflector&lt;/a&gt;. Also the &lt;a href="http://stuff.mit.edu/afs/athena/software/fsharp_v1.1.12/FSharp-1.1.12.3/manual/export-interop.html"&gt;F# from C# section of the F# 1.1.12&lt;/a&gt; documentation is very helpful.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;FSharp.Code library&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;In order to call some F# basic functionality we need to add a reference to &lt;code&gt;FSharp.Core&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;import&lt;/span&gt; clr&lt;br /&gt;clr.AddReference(&lt;span class="srctext"&gt;'FSharp.Core'&lt;/span&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Type parameters&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;IronPython provides a way to specify type parameters to methods and classes by using square brackets followed by the names of the types to be used. This mechanism can be used to create F# constructs that require them. &lt;br /&gt;&lt;br /&gt;The following example shows how to create an F# list:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; import clr&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; clr.AddReference('FSharp.Core')&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; from Microsoft.FSharp.Collections import List&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; l1 = List[str].Cons('World',List[str].Empty)&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; l2 = List[str].Cons('Hello',l1)&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; " ".join(l2)&lt;br /&gt;'Hello World'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Type parameters, for methods that require them, also can be specified using the same syntax. For example the following code shows the use of &lt;a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/FSharp.Core/Microsoft.FSharp.Collections.Seq.html"&gt;&lt;code&gt;Seq.length&lt;/code&gt;&lt;/a&gt; with an Python sequence.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;print Seq.length[int]([45,234,52,345,2,346,657])&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Tuples&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Tuples in F# are instances of the &lt;code&gt;Microsoft.FSharp.Core.Tuple&lt;/code&gt; class (with several definitions with depending on the number of arguments). A tuple instance contains properties &lt;code&gt;Item#&lt;/code&gt; where # is the position of the element.&lt;br /&gt;&lt;br /&gt;The following example shows how to use a tuple created in F# from IronPython.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;F#&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;module&lt;/span&gt; MyFunctions = &lt;span class="srckeyw"&gt;begin&lt;/span&gt;&lt;br /&gt;  ...&lt;br /&gt;  &lt;span class="srckeyw"&gt;let&lt;/span&gt; numberEvenTest x = x,x % 2 = 0&lt;br /&gt;  ...&lt;br /&gt;&lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;print MyFunctions.numberEvenTest(46)&lt;br /&gt;print MyFunctions.numberEvenTest(46).Item1&lt;br /&gt;print MyFunctions.numberEvenTest(46).Item2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This program will print:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(46,True)&lt;br /&gt;46&lt;br /&gt;True&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To create a tuple inside IronPython the &lt;code&gt;Tuple[&lt;span style="font-style:italic;"&gt;type1,type2,...&lt;/span&gt;](&lt;span style="font-style:italic;"&gt;value1,value2,...&lt;/span&gt;)&lt;/code&gt; constructor must be used. &lt;br /&gt;&lt;br /&gt;For example to given the following definition:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;F#&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;module&lt;/span&gt; MyFunctions = &lt;span class="srckeyw"&gt;begin&lt;/span&gt;&lt;br /&gt;...&lt;br /&gt;  &lt;span class="srckeyw"&gt;let&lt;/span&gt; movePoints points xdistance ydistance =&lt;br /&gt;     Seq.map (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; (x,y) -&amp;gt; (x+xdistance,y+ydistance)) points&lt;br /&gt;...&lt;br /&gt;&lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can used from IronPython like this:&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;from Microsoft.FSharp.Core import Tuple &lt;br /&gt;...&lt;br /&gt;points = [ Tuple[int,int](1,2), Tuple[int,int](5,3) ]&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;for&lt;/span&gt; p &lt;span class="srckeyw"&gt;in&lt;/span&gt; MyFunctions.movePoints(points,20,40):&lt;br /&gt;   print p&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It is tempting to use the Python &lt;a href="http://docs.python.org/reference/simple_stmts.html#assignment-statements"&gt;syntax for assigning a list of variables&lt;/a&gt; to the values of the tuples. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;x,y,z = 2,3,5&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;However this is not possible since F# tuples are not compatible with IronPython sequences. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Operators&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;F# operators are created using the same conventions as the C# operators. Thus they can be used directly in IronPython.&lt;br /&gt;&lt;br /&gt;For example the following F# definition:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; Complex(real:&lt;span class="srckeyw"&gt;double&lt;/span&gt;,img:&lt;span class="srckeyw"&gt;double&lt;/span&gt;) = &lt;span class="srckeyw"&gt;class&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.real &lt;span class="srckeyw"&gt;with get&lt;/span&gt;() = real&lt;br /&gt;   &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.img &lt;span class="srckeyw"&gt;with get&lt;/span&gt;() = img&lt;br /&gt;   &lt;span class="srckeyw"&gt;static member&lt;/span&gt; (+) (c1:Complex,c2:Complex) = &lt;br /&gt;        Complex(c1.real+c2.real,c1.img+c2.img)&lt;br /&gt;   &lt;span class="srckeyw"&gt;override&lt;/span&gt; this.ToString() = sprintf "%f + %fi" real img&lt;br /&gt;&lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Can be used in IronPython:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;c1 = Complex(20,234)&lt;br /&gt;c2 = Complex(34.35,32.2)&lt;br /&gt;c3 = (c1+c2)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Discriminated unions&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Discriminated unions in F# provide a compact way to define data structures. The following example shows the definition of simple math expressions that include addition, subtraction and numeric literals.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;F#&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; MathExpr =&lt;br /&gt;  | Addition &lt;span class="srckeyw"&gt;of&lt;/span&gt; MathExpr * MathExpr&lt;br /&gt;  | Subtraction &lt;span class="srckeyw"&gt;of&lt;/span&gt; MathExpr * MathExpr&lt;br /&gt;  | Literal &lt;span class="srckeyw"&gt;of double&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The following code snippet shows how to create instance of these math expression elements from IronPython.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Python&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;expr = MathExpr.Addition(MathExpr.Literal(10),\&lt;br /&gt;                         MathExpr.Subtraction(\&lt;br /&gt;                                   MathExpr.Literal(40), \&lt;br /&gt;                                   MathExpr.Literal(24)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A instance of the discriminated union has methods IsXXXX to verify the kind. Also properties a generated with the name of the constructor followed by a number (for example Addition1) to access values given to the constructor.&lt;br /&gt;&lt;br /&gt;The following example shows how to evaluate a math expression.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-weight:bold;"&gt;Python&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;def&lt;/span&gt; evalExpr(expr):&lt;br /&gt;  &lt;span class="srckeyw"&gt;if&lt;/span&gt; expr.IsAddition():&lt;br /&gt;     &lt;span class="srckeyw"&gt;return&lt;/span&gt; evalExpr(expr.Addition1) + evalExpr(expr.Addition2)&lt;br /&gt;  &lt;span class="srckeyw"&gt;elif&lt;/span&gt; expr.IsSubtraction():&lt;br /&gt;     &lt;span class="srckeyw"&gt;return&lt;/span&gt; evalExpr(expr.Subtraction1) - evalExpr(expr.Subtraction2)&lt;br /&gt;  &lt;span class="srckeyw"&gt;else&lt;/span&gt;:&lt;br /&gt;     &lt;span class="srckeyw"&gt;return&lt;/span&gt; expr.Literal1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Functions&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Functions passed as parameters need to be converted to a special F# element that represent them. In order to do this the &lt;a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/fsharp.core/microsoft.fsharp.core.type_funcconvert.html"&gt;FuncConvert.ToFastFunc&lt;/a&gt; function is used. &lt;br /&gt;&lt;br /&gt;For example the following code shows how to call &lt;code&gt;Seq.iter&lt;/code&gt; to print all the elements of a Python list.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;from Microsoft.FSharp.Core import FuncConvert &lt;br /&gt;...&lt;br /&gt;aList = [5,3,42,6]&lt;br /&gt;&lt;br /&gt;def foo(x):&lt;br /&gt;   print(x)&lt;br /&gt;&lt;br /&gt;Seq.iter[int](FuncConvert.ToFastFunc[int]( foo),aList)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Since IronPython and F# use IEnumerable&amp;lt;T&amp;gt; types to represent collections and sequences we can use F# functions to manipulate IronPython collections.&lt;br /&gt;&lt;br /&gt;For example given the following definition of a Python generator for &lt;a href="http://en.wikipedia.org/wiki/Fibonacci_number"&gt;Fibonacci numbers&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;def&lt;/span&gt; fibo():&lt;br /&gt;  last1 = 0&lt;br /&gt;  last2 = 1&lt;br /&gt;  &lt;span class="srckeyw"&gt;while&lt;/span&gt; &lt;span class="srckeyw"&gt;True&lt;/span&gt;:    &lt;br /&gt;    &lt;span class="srckeyw"&gt;yield&lt;/span&gt; last1&lt;br /&gt;    next = last1+last2&lt;br /&gt;    last2 = last1&lt;br /&gt;    last1 = next&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can call F# functions to process values generated by &lt;code&gt;fibo&lt;/code&gt;. For example the following IronPython code prints the first 15 squared Fibonacci numbers.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;for n in Seq.map[int,int]( FuncConvert.ToFastFunc[int,int](lambda x: x*x)  ,\&lt;br /&gt;                           Seq.take[int](15,fibo())):&lt;br /&gt;   print n&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Code for this post was created using IronPython 2.0 and F# 1.9.6.2 .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-6626805147292748823?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/6626805147292748823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=6626805147292748823' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/6626805147292748823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/6626805147292748823'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2009/01/some-notes-on-using-f-code-from.html' title='Some notes on using F# code from IronPython'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-2813583110292576462</id><published>2008-12-01T05:39:00.001-06:00</published><updated>2008-12-01T05:39:17.982-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mef'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>A quick look at MEF with F#</title><content type='html'>In this post I'm going to show a little example of using the Managed Extensibility Framework (MEF) from &lt;a href="http://research.microsoft.com/fsharp/"&gt;F#&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.codeplex.com/MEF"&gt;Managed Extensibility Framework (MEF)&lt;/a&gt; is a very interesting framework for building extensible applications. It is &lt;a href="http://www.infoq.com/news/2008/11/VS2010-Roadmap"&gt;planned to be used&lt;/a&gt; in products such as &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=922B4655-93D0-4476-BDA4-94CF5F8D4814"&gt;Visual Studio 2010&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Episode &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=398"&gt;.NET Rocks #398: Glenn Block on MEF&lt;/a&gt; is a nice source of information the  project.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.codeplex.com/MEF/Wiki/View.aspx?title=Guide&amp;referringTitle=Home"&gt;MEF Codeplex&lt;/a&gt; page has documentation on how to start using it. Also the &lt;a href="http://www.codethinked.com/post/2008/11/26/Addicted-To-MEF-Part-1.aspx"&gt;Addicted to MEF&lt;/a&gt; series is a nice source of information on how to start using it.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The example&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;For this example I want to define a little program F# program that plots math functions. Function definitions will be represented as classes that implement the &lt;code&gt;IFunction&lt;/code&gt; interface. These definitions will be taken from DLLs stored in a "extensions" directory.&lt;br /&gt;&lt;br /&gt;Here's the definition of the &lt;code&gt;IFunction&lt;/code&gt; interface:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; IFunction = &lt;span class="srckeyw"&gt;interface&lt;/span&gt;&lt;br /&gt;    &lt;span class="srckeyw"&gt;abstract&lt;/span&gt; Apply : &lt;span class="srckeyw"&gt;double&lt;/span&gt; -&amp;gt; &lt;span class="srckeyw"&gt;double&lt;/span&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The following code shows the definition of the Winforms Form that is used to display the function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System.Windows.Forms&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System.Drawing&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; FunctionDefinitions&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System.ComponentModel.Composition&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System.Collections.Generic&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; MyForm() &lt;span class="srckeyw"&gt;as&lt;/span&gt; this = &lt;span class="srckeyw"&gt;class&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;inherit&lt;/span&gt; System.Windows.Forms.Form()&lt;br /&gt;              &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; &lt;span class="srckeyw"&gt;mutable&lt;/span&gt; functions : IEnumerable&amp;lt;IFunction&amp;gt; = Seq.empty&lt;br /&gt;                         &lt;br /&gt;   &lt;span class="srckeyw"&gt;do&lt;/span&gt; this.Size &amp;lt;- &lt;span class="srckeyw"&gt;new&lt;/span&gt; System.Drawing.Size(300,300)&lt;br /&gt;   &lt;span class="srckeyw"&gt;do&lt;/span&gt; this.BackColor &amp;lt;- Color.White&lt;br /&gt;   &lt;span class="srckeyw"&gt;do&lt;/span&gt; this.Text &amp;lt;- &lt;span class="srctext"&gt;"Functions"&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;do&lt;/span&gt; this.Paint.Add(&lt;br /&gt;          &lt;span class="srckeyw"&gt;fun&lt;/span&gt; (pargs:PaintEventArgs) -&amp;gt;&lt;br /&gt;                      using(&lt;span class="srckeyw"&gt;new&lt;/span&gt; Pen(Brushes.Black))&lt;br /&gt;                           (&lt;span class="srckeyw"&gt;fun&lt;/span&gt;(p) -&amp;gt; pargs.Graphics.DrawLine(p,&lt;br /&gt;                                                         &lt;span class="srckeyw"&gt;new&lt;/span&gt; Point(this.Size.Width/2,0),&lt;br /&gt;                                                         &lt;span class="srckeyw"&gt;new&lt;/span&gt; Point(this.Size.Width/2,this.Size.Height))&lt;br /&gt;&lt;br /&gt;                                      pargs.Graphics.DrawLine(p,&lt;br /&gt;                                                         &lt;span class="srckeyw"&gt;new&lt;/span&gt; Point(0,this.Size.Height/2),&lt;br /&gt;                                                         &lt;span class="srckeyw"&gt;new&lt;/span&gt; Point(this.Size.Width,this.Size.Height/2))&lt;br /&gt;                                      Seq.iter (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; func -&amp;gt; pargs.Graphics.DrawLines(p,this.CalcPoints(func))) functions&lt;br /&gt;                           ))&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.CalcPoints(func:IFunction) : Point array =&lt;br /&gt;       { 0..300} |&amp;gt; Seq.map (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; x -&amp;gt; -1.0/30.0 * double(x) + 5.0) |&amp;gt;&lt;br /&gt;                    Seq.map (&lt;span class="srckeyw"&gt;fun&lt;/span&gt; x -&amp;gt; x,func.Apply(x)) |&amp;gt;&lt;br /&gt;                    Seq.map (&lt;span class="srckeyw"&gt;fun&lt;/span&gt;(x,y) -&amp;gt; &lt;span class="srckeyw"&gt;new&lt;/span&gt; Point(int32(x*30.0+150.0),&lt;br /&gt;                                                   int32(y*(-30.0)+150.0)))  |&amp;gt;&lt;br /&gt;                    Seq.to_array&lt;br /&gt;&lt;b&gt;&lt;br /&gt;   [&amp;lt;Import&amp;gt;]&lt;br /&gt;   &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.Functions &lt;br /&gt;       &lt;span class="srckeyw"&gt;with&lt;/span&gt; &lt;span class="srckeyw"&gt;get&lt;/span&gt;() : IEnumerable&amp;lt;IFunction&amp;gt; = functions&lt;br /&gt;       &lt;span class="srckeyw"&gt;and&lt;/span&gt;  &lt;span class="srckeyw"&gt;set&lt;/span&gt; (f : IEnumerable&amp;lt;IFunction&amp;gt;) = functions &amp;lt;- f&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In order to say that we want all available functions(IFunction) identified by MEF we declare the &lt;code&gt;Functions&lt;/code&gt; property with type &lt;code&gt;IEnumerable&amp;lt;IFunction&amp;gt;&lt;/code&gt; and decorated with the &lt;code&gt;Import&lt;/code&gt; attribute.&lt;br /&gt;&lt;br /&gt;The following code shows the how we use MEF to compose the application and run the winforms app:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; f = &lt;span class="srckeyw"&gt;new&lt;/span&gt; MyForm()&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; catalog = &lt;span class="srckeyw"&gt;new&lt;/span&gt; DirectoryPartCatalog(&lt;span class="srctext"&gt;"c:\\temp\\Extensions"&lt;/span&gt;)&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; container = &lt;span class="srckeyw"&gt;new&lt;/span&gt; CompositionContainer(catalog,[||])&lt;br /&gt;&lt;br /&gt;container.AddPart(f)&lt;br /&gt;container.Compose()&lt;br /&gt;&lt;br /&gt;System.Windows.Forms.Application.Run(f)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that by using &lt;code&gt;DirectoryPartCatalog&lt;/code&gt; we say that we want to take all extensions(math function definitions) stored in &lt;code&gt;c:\temp\Extensions&lt;/code&gt;. &lt;br /&gt;&lt;br /&gt;It is important to notice that the program that has the Winforms application is stored in a different assembly from where &lt;code&gt;IFunction&lt;/code&gt; is defined.  The reason is that the extension DLLs need a reference to it.&lt;br /&gt;&lt;br /&gt;Running this program without extensions shows the following form:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/STKh8PafgSI/AAAAAAAAAKI/ggWB5R-sEpo/s1600-h/meffunctions1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://4.bp.blogspot.com/_qePSufqunG4/STKh8PafgSI/AAAAAAAAAKI/ggWB5R-sEpo/s320/meffunctions1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5274456169906143522" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The following code shows an extension written in F#:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;#light &lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;namespace&lt;/span&gt; MoreFunctions&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; FunctionDefinitions&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System.ComponentModel.Composition&lt;br /&gt;&lt;br /&gt;[&amp;lt;Export(typeof&amp;lt;IFunction&amp;gt;)&amp;gt;]&lt;br /&gt;&lt;span class="srckeyw"&gt;type&lt;/span&gt; AFunction() = &lt;span class="srckeyw"&gt;class&lt;/span&gt;&lt;br /&gt;    &lt;span class="srckeyw"&gt;interface&lt;/span&gt; IFunction &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;       &lt;span class="srckeyw"&gt;member&lt;/span&gt; this.Apply(x:double) = System.Math.Sin(x) &lt;br /&gt;&lt;span class="srckeyw"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We compile this file and copy the result to the extensions directory.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;fsc.exe other.fs -r FunctionDefinitions.dll -r System.ComponentModel.Composition.dll  -a&lt;br /&gt;copy other.dll c:\temp\Extensions&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By running the program again the following form is shown&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/STKiNP1T9uI/AAAAAAAAAKQ/_TCGjYI0aNw/s1600-h/meffunctions2.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://4.bp.blogspot.com/_qePSufqunG4/STKiNP1T9uI/AAAAAAAAAKQ/_TCGjYI0aNw/s320/meffunctions2.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5274456462076409570" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Since we're working with common .NET assemblies we can write a function definition using C#, for example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; FunctionDefinitions;&lt;br /&gt;&lt;span class="srckeyw"&gt;using&lt;/span&gt; System.ComponentModel.Composition;&lt;br /&gt;&lt;span class="srckeyw"&gt;namespace&lt;/span&gt; Test2 {&lt;br /&gt;   [Export(&lt;span class="srckeyw"&gt;typeof&lt;/span&gt;(IFunction))]&lt;br /&gt;   &lt;span class="srckeyw"&gt;public&lt;/span&gt; &lt;span class="srckeyw"&gt;class&lt;/span&gt; AFunction : IFunction&lt;br /&gt;   {&lt;br /&gt;    &lt;span class="srckeyw"&gt;public&lt;/span&gt; double Apply(double d) &lt;br /&gt;    {&lt;br /&gt;     &lt;span class="srckeyw"&gt;return&lt;/span&gt; d*d;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We compile this file and copy it to the extensions directory:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;csc /reference:FunctionDefinitions.dll;System.ComponentModel.Composition.dll  /t:library AFunc.cs&lt;br /&gt;copy AFunc.dll c:\temp\Extensions&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Running this program shows the following form:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_qePSufqunG4/STKjNru_ydI/AAAAAAAAAKY/P31VSOynyaY/s1600-h/meffunctions3.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://2.bp.blogspot.com/_qePSufqunG4/STKjNru_ydI/AAAAAAAAAKY/P31VSOynyaY/s320/meffunctions3.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5274457569077742034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Final words&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;MEF provides a nice/simple way to add extensions to .NET applications. I was really impressed by how simple it is to define Exports and Imports and how little MEF-specific code you have to write in order to make it work. &lt;br /&gt;&lt;br /&gt;One thing that will be interesting to see is how this framework is going to interact with things such as the DLR. A nice example of this is &lt;a href="http://ironpython-urls.blogspot.com/2008/10/oslos-intellipad-scripted-with.html"&gt;Intellipad&lt;/a&gt; which, as mentioned in the .NET Rocks interview, is used to allow IronPython extensions.&lt;br /&gt;&lt;br /&gt;Code for this post uses &lt;a href="http://www.codeplex.com/MEF/Release/ProjectReleases.aspx?ReleaseId=19836#ReleaseFiles"&gt;MEF Preview 3 release&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-2813583110292576462?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/2813583110292576462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=2813583110292576462' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2813583110292576462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/2813583110292576462'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2008/12/quick-look-at-mef-with-f.html' title='A quick look at MEF with F#'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_qePSufqunG4/STKh8PafgSI/AAAAAAAAAKI/ggWB5R-sEpo/s72-c/meffunctions1.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-9039175284264859602</id><published>2008-11-21T05:27:00.001-06:00</published><updated>2008-11-21T05:28:12.026-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Using the Canvas Html element</title><content type='html'>In this post I'm going to show a little example of using the &lt;a href="http://en.wikipedia.org/wiki/Canvas_(HTML_element)"&gt;HTML 5 Canvas element&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The Canvas element provides a way to draw graphics using &lt;a href="http://en.wikipedia.org/wiki/Javascript"&gt;Javascript&lt;/a&gt;. It is currently supported in browsers such as &lt;a href="http://developer.apple.com/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/Canvas.html"&gt;Safari&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en/Drawing_Graphics_with_Canvas"&gt;Firefox&lt;/a&gt;, &lt;a href="http://www.opera.com/docs/specs/opera9/canvas/"&gt;Opera&lt;/a&gt; and Chrome. Sadly it is not supported in &lt;a href="http://www.microsoft.com/windows/products/winfamily/ie/default.mspx"&gt;IE&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There's a lot of documentation on how to use this element. The Mozilla Developer Center provides a nice tutorial: &lt;a href="https://developer.mozilla.org/en/Canvas_tutorial"&gt;Canvas tutorial&lt;/a&gt;. Also the HTML 5 specification document provides a detailed description of the element in &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/#the-canvas-element"&gt;The canvas element&lt;/a&gt; section.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Example&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;In order to play learn about this element I decided to create a toy program that takes an image and creates a little Jigsaw Puzzle of it. &lt;br /&gt;&lt;br /&gt;Here's how the page looks:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_qePSufqunG4/SSVV1D3I_eI/AAAAAAAAAKA/Qp63yj1dR6Q/s1600-h/jscnvsjpuzzle.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 280px;" src="http://4.bp.blogspot.com/_qePSufqunG4/SSVV1D3I_eI/AAAAAAAAAKA/Qp63yj1dR6Q/s320/jscnvsjpuzzle.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5270713308965043682" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The running version of this program can be found &lt;a href="http://langexplr.googlepages.com/htmlcanvaspuzzle"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Code&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The code to create this little program is very simple. First the canvas element is specified as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;body onload=&lt;span class="srctext"&gt;"init();"&lt;/span&gt; &amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;Canvas Object Tests&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;canvas id=&lt;span class="srctext"&gt;"myCanvas"&lt;/span&gt; width=&lt;span class="srctext"&gt;"700"&lt;/span&gt; height=&lt;span class="srctext"&gt;"600"&lt;/span&gt;&lt;br /&gt;        onmousemove=&lt;span class="srctext"&gt;"moveHandler(event);"&lt;/span&gt;&lt;br /&gt;        onmousedown=&lt;span class="srctext"&gt;"mouseDownHandler(event);"&lt;/span&gt;&lt;br /&gt;        onmouseup=&lt;span class="srctext"&gt;"mouseUpHandler(event);"&lt;/span&gt;&lt;br /&gt;        onmouseout=&lt;span class="srctext"&gt;"mouseUpHandler(event);"&lt;/span&gt;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;br /&gt;&amp;lt;hr/&amp;gt;&lt;br /&gt;&amp;lt;div id=&lt;span class="srctext"&gt;"notSup"&lt;/span&gt; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;Four event handlers are added to the canvas element to handle mouse interactions to move the pieces of the puzzle.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;init&lt;/code&gt; function is called in the "load" event of the body element. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;var&lt;/span&gt; imageName = &lt;span class="srctext"&gt;'http://farm3.static.flickr.com/2161/2543461722_a68f3d1e2e_m.jpg'&lt;/span&gt;;&lt;br /&gt;...&lt;br /&gt;&lt;span class="srckeyw"&gt;function&lt;/span&gt; init() {&lt;br /&gt;   img = &lt;span class="srckeyw"&gt;new&lt;/span&gt; Image();&lt;br /&gt;        &lt;br /&gt;   img.onload = &lt;span class="srckeyw"&gt;function&lt;/span&gt;() {&lt;br /&gt;      imageLoaded = true;&lt;br /&gt;      draw();&lt;br /&gt;   }&lt;br /&gt;   img.src = imageName;&lt;br /&gt;       &lt;br /&gt;   theObjects = createImageSegments(3,3,{width:240,height:180},{x:5,y:10});&lt;br /&gt;        &lt;br /&gt;   draw();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The createImageSegments function creates the pieces of the puzzle.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;function&lt;/span&gt; createImageSegments(lines,cols,imageSize,basePosition)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="srckeyw"&gt;var&lt;/span&gt; incrY = imageSize.height/lines;&lt;br /&gt;    &lt;span class="srckeyw"&gt;var&lt;/span&gt; incrX = imageSize.width/cols;&lt;br /&gt;    &lt;span class="srckeyw"&gt;var&lt;/span&gt; theX = basePosition.x;&lt;br /&gt;    &lt;span class="srckeyw"&gt;var&lt;/span&gt; theY = basePosition.y;&lt;br /&gt;    &lt;span class="srckeyw"&gt;var&lt;/span&gt; result = &lt;span class="srckeyw"&gt;new&lt;/span&gt; Array();&lt;br /&gt;    &lt;span class="srckeyw"&gt;for&lt;/span&gt;(&lt;span class="srckeyw"&gt;var&lt;/span&gt; i = 0;i &amp;lt; lines;i++) {&lt;br /&gt;        &lt;span class="srckeyw"&gt;for&lt;/span&gt;(&lt;span class="srckeyw"&gt;var&lt;/span&gt; j = 0;j &amp;lt; cols;j++) {&lt;br /&gt;            result.push(&lt;span class="srckeyw"&gt;new&lt;/span&gt; ImageSegment(this.img,&lt;br /&gt;                              {x:theX,y:theY},&lt;br /&gt;                              {width:incrX,height:incrY},&lt;br /&gt;                              {x:(j*incrX),y:(i*incrY)},&lt;br /&gt;                              {width:incrX,height:incrY}));                &lt;br /&gt;            theY += 2 + incrY;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    return shuffleArray(result);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;ImageSegment&lt;/code&gt; objects are defined by the following function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;function&lt;/span&gt; ImageSegment(image,position,size,insidePoint,insideSize){&lt;br /&gt;   &lt;span class="srckeyw"&gt;this&lt;/span&gt;.image = image;&lt;br /&gt;   &lt;span class="srckeyw"&gt;this&lt;/span&gt;.position = position;&lt;br /&gt;   &lt;span class="srckeyw"&gt;this&lt;/span&gt;.size = size;&lt;br /&gt;   &lt;span class="srckeyw"&gt;this&lt;/span&gt;.insidePoint = insidePoint;&lt;br /&gt;   &lt;span class="srckeyw"&gt;this&lt;/span&gt;.insideSize = insideSize;&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;this&lt;/span&gt;.draw = &lt;span class="srckeyw"&gt;function&lt;/span&gt;(context) {&lt;br /&gt;      context.drawImage(&lt;br /&gt;               &lt;span class="srckeyw"&gt;this&lt;/span&gt;.image,&lt;br /&gt;               &lt;span class="srckeyw"&gt;this&lt;/span&gt;.insidePoint.x,&lt;br /&gt;               &lt;span class="srckeyw"&gt;this&lt;/span&gt;.insidePoint.y,&lt;br /&gt;               &lt;span class="srckeyw"&gt;this&lt;/span&gt;.insideSize.width,&lt;br /&gt;               &lt;span class="srckeyw"&gt;this&lt;/span&gt;.insideSize.height,&lt;br /&gt;               &lt;span class="srckeyw"&gt;this&lt;/span&gt;.position.x,&lt;br /&gt;               &lt;span class="srckeyw"&gt;this&lt;/span&gt;.position.y,&lt;br /&gt;               &lt;span class="srckeyw"&gt;this&lt;/span&gt;.size.width,&lt;span class="srckeyw"&gt;this&lt;/span&gt;.size.height);           &lt;br /&gt;   };&lt;br /&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;this&lt;/span&gt;.isInside = &lt;span class="srckeyw"&gt;function&lt;/span&gt;(point) {&lt;br /&gt;      &lt;span class="srckeyw"&gt;return&lt;/span&gt; (&lt;span class="srckeyw"&gt;this&lt;/span&gt;.position.x &amp;lt;= point.x &amp;&amp;&lt;br /&gt;          &lt;span class="srckeyw"&gt;this&lt;/span&gt;.position.y &amp;lt;= point.y &amp;&amp;&lt;br /&gt;          &lt;span class="srckeyw"&gt;this&lt;/span&gt;.position.x + &lt;span class="srckeyw"&gt;this&lt;/span&gt;.size.width &amp;gt;= point.x &amp;&amp;&lt;br /&gt;          &lt;span class="srckeyw"&gt;this&lt;/span&gt;.position.y + &lt;span class="srckeyw"&gt;this&lt;/span&gt;.size.height &amp;gt;= point.y);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Two methods are defined: one to draw the section of the image and one to determine of  a given point hits the current object.&lt;br /&gt;&lt;br /&gt;In order to draw the image the following function is defined:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;function&lt;/span&gt; draw() {&lt;br /&gt;   &lt;span class="srckeyw"&gt;var&lt;/span&gt; myCanvas = document.getElementById("myCanvas");&lt;br /&gt;   &lt;span class="srckeyw"&gt;if&lt;/span&gt;(myCanvas.getContext) {&lt;br /&gt;                     &lt;br /&gt;     &lt;span class="srckeyw"&gt;var&lt;/span&gt; ctxt = myCanvas.getContext(&lt;span class="srctext"&gt;'2d'&lt;/span&gt;);&lt;br /&gt;     ctxt.clearRect(0,0,myCanvas.width,myCanvas.height);&lt;br /&gt;     &lt;span class="srckeyw"&gt;if&lt;/span&gt; (imageLoaded) {&lt;br /&gt;        for(&lt;span class="srckeyw"&gt;var&lt;/span&gt; i = 0;i &amp;lt; theObjects.length;i++) {&lt;br /&gt;           theObjects[i].draw(ctxt);&lt;br /&gt;        } &lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    // Draw the frame&lt;br /&gt;    ...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In order to allow the user to drag the pieces of the puzzle across the canvas the following mouse event handlers were added to the canvas.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;function&lt;/span&gt; mouseDownHandler(e)&lt;br /&gt;{&lt;br /&gt;   &lt;span class="srckeyw"&gt;var&lt;/span&gt; x = e.pageX - e.target.offsetLeft;&lt;br /&gt;   &lt;span class="srckeyw"&gt;var&lt;/span&gt; y = e.pageY - e.target.offsetTop;&lt;br /&gt;   &lt;span class="srckeyw"&gt;for&lt;/span&gt;(&lt;span class="srckeyw"&gt;var&lt;/span&gt; i = 0; i &amp;lt; theObjects.length;i++) {&lt;br /&gt;      &lt;span class="srckeyw"&gt;var&lt;/span&gt; theObject = theObjects[i];&lt;br /&gt;      &lt;span class="srckeyw"&gt;if&lt;/span&gt; (theObject.isInside({x:x,y:y})) {&lt;br /&gt;         dragging = &lt;span class="srckeyw"&gt;true&lt;/span&gt;;&lt;br /&gt;         lastPoint.x = x;&lt;br /&gt;         lastPoint.y = y;&lt;br /&gt;         currentDragObject = theObject;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;function&lt;/span&gt; mouseUpHandler(e)&lt;br /&gt;{&lt;br /&gt;   dragging = &lt;span class="srckeyw"&gt;false&lt;/span&gt;;&lt;br /&gt;   lastPoint.x = -1;&lt;br /&gt;   lastPoint.y = -1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;function&lt;/span&gt; moveHandler(e) {&lt;br /&gt;   &lt;span class="srckeyw"&gt;if&lt;/span&gt; (dragging) {&lt;br /&gt;       &lt;span class="srckeyw"&gt;var&lt;/span&gt; x = e.pageX - e.target.offsetLeft;&lt;br /&gt;       &lt;span class="srckeyw"&gt;var&lt;/span&gt; y = e.pageY - e.target.offsetTop;&lt;br /&gt;       &lt;span class="srckeyw"&gt;var&lt;/span&gt; deltaX = x - lastPoint.x;&lt;br /&gt;       &lt;span class="srckeyw"&gt;var&lt;/span&gt; deltaY = y - lastPoint.y;&lt;br /&gt;&lt;br /&gt;       &lt;br /&gt;       currentDragObject.position.x += deltaX;&lt;br /&gt;       currentDragObject.position.y += deltaY;&lt;br /&gt; &lt;br /&gt;       &lt;br /&gt;       lastPoint.x = x;&lt;br /&gt;       lastPoint.y = y;&lt;br /&gt;       draw();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Basically what these event handlers do is to calculate the new position of the image being dragged and update the canvas.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Html Canvas object provides a nice way to draw custom graphics in a web page using Javascript. For future posts I'm going to try to rewrite the example from the &lt;br /&gt;&lt;a href="http://langexplr.blogspot.com/2008/07/javafx-script-overview.html"&gt;JavaFX Script&lt;/a&gt;, &lt;a href="http://langexplr.blogspot.com/2008/07/quick-look-at-silverlight-with-ironruby.html"&gt;Silverlight&lt;/a&gt; and &lt;a href="http://langexplr.blogspot.com/2008/10/quick-look-at-flex.html"&gt;Flex&lt;/a&gt; posts using Javascript and Canvas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8273201239805322932-9039175284264859602?l=langexplr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://langexplr.blogspot.com/feeds/9039175284264859602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8273201239805322932&amp;postID=9039175284264859602' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/9039175284264859602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8273201239805322932/posts/default/9039175284264859602'/><link rel='alternate' type='text/html' href='http://langexplr.blogspot.com/2008/11/using-canvas-html-element.html' title='Using the Canvas Html element'/><author><name>Luis Diego Fallas</name><uri>http://www.blogger.com/profile/01461500891939895224</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-edi-8UIsKCQ/TZcv8XMjR8I/AAAAAAAAASY/faWXItth5rU/s220/papaynacho.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_qePSufqunG4/SSVV1D3I_eI/AAAAAAAAAKA/Qp63yj1dR6Q/s72-c/jscnvsjpuzzle.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8273201239805322932.post-8935016079581112926</id><published>2008-11-13T05:53:00.002-06:00</published><updated>2008-11-13T05:55:51.435-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mgrammar'/><category scheme='http://www.blogger.com/atom/ns#' term='m'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Using a MGrammar parser from F#</title><content type='html'>In this post I'm going to show a little example of manipulating the output tree of a &lt;a href="http://msdn.microsoft.com/en-us/library/dd129869.aspx"&gt;MGrammar &lt;/a&gt;parser using some &lt;a href="http://research.microsoft.com/fsharp/fsharp.aspx"&gt;F#&lt;/a&gt; features.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;MGrammar&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;MGrammar is one of the components of the &lt;a href="http://msdn.microsoft.com/en-us/oslo/default.aspx"&gt;"Oslo" Modeling Platform&lt;/a&gt; which allows the definition of domain specific languages.&lt;br /&gt;&lt;br /&gt;In his post I'm not giving an introduction to MGrammar. There are really nice articles about it for example: &lt;a href="http://msdn.microsoft.com/en-us/library/dd129870.aspx"&gt;MGrammar in a Nutshell&lt;/a&gt;,  &lt;a href="http://blogs.artinsoft.net/carlosloria/archive/2008/11/07/parsing-with-oslo-s-mgrammar-mg.aspx"&gt;Parsing with Oslo’s MGrammar (Mg) &lt;/a&gt; and &lt;a href="http://www.codinginstinct.com/2008/11/creating-watin-dsl-using-mgrammar.html"&gt;Creating a WatiN DSL using MGrammar&lt;/a&gt;. Also the &lt;a href="http://channel9.msdn.com/pdc2008/TL31/"&gt;Oslo:Building Textual DSLs&lt;/a&gt; talk provides a very nice introduction to the topic.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The example&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;For this post I'm going to create a MGrammar definition of a little language that describes the structure of a binary file. Then I'm going to create a F# program that interprets these definitions to load binary files.&lt;br /&gt;&lt;br /&gt;The following code shows an example of the language to be defined:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;test = begin&lt;br /&gt;   byte == 0x22&lt;br /&gt;   int32 x&lt;br /&gt;   int16 w&lt;br /&gt;   bytes[16] k&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This code describes binary files that start with a &lt;code&gt;byte&lt;/code&gt; with the 0x22 value, followed by a &lt;code&gt;int32&lt;/code&gt; value associated with the "x" name, followed by an  &lt;code&gt;int16&lt;/code&gt; value named "w" followed by an array of 16 bytes named "k".&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The grammar&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;The grammar for this language is the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;module&lt;/span&gt; LangexplTests &lt;br /&gt;{&lt;br /&gt;  &lt;span class="srckeyw"&gt;language&lt;/span&gt; BinaryRecognizer &lt;br /&gt;  {&lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; Int32Type = "int32";&lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; Int16Type = "int16";&lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; ByteType = "byte";         &lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; Bytes = "bytes";         &lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; Integer = ("0".."9")+;&lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; HexNumber = "0x" ("0".."9"|"A".."F")+;&lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; Symbol = (("A".."Z") | ("a".."z"))+;         &lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; NewLine = "\n";&lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; LineFeed = "\r";&lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; LineBreak  =   LineFeed? NewLine;&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; Begin = "begin";&lt;br /&gt;   &lt;span class="srckeyw"&gt;token&lt;/span&gt; End = "end";&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; TypeName = Int32Type =&amp;gt; Int32[] |Int16Type =&amp;gt; Int16[] |ByteType =&amp;gt; Byte[];&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; Expression = i:Integer=&amp;gt;Int[i] | s:Symbol =&amp;gt; Var[s] | h:HexNumber =&amp;gt; Hex[h];&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; TypeDeclaration = TypeName Symbol;&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; MultipleBytesDeclaration = Bytes "[" n:Expression "]" s:Symbol =&amp;gt; &lt;br /&gt;                        MultipleBytesDeclaration[n,s];&lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; LiteralValueDeclaration = t:TypeName "==" e:Expression =&amp;gt; LiteralValueDeclaration[t,e];&lt;br /&gt;                     &lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; ItemDeclaration = TypeDeclaration|MultipleBytesDeclaration|LiteralValueDeclaration;&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; Sequence(G,Separator) = &lt;br /&gt;                     e:G  =&amp;gt; [e]&lt;br /&gt;                   | es:Sequence(G,Separator) Separator e:G  =&amp;gt; [&lt;span class="srckeyw"&gt;valuesof&lt;/span&gt;(es),e];&lt;br /&gt;                   &lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; Definition = name:Symbol "=" Begin LineBreak          &lt;br /&gt;                                decs:Sequence(ItemDeclaration, LineBreak)               &lt;br /&gt;                                LineBreak                      &lt;br /&gt;                                End&lt;br /&gt;                                LineBreak* =&amp;gt; Recognizer[name,decs];&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;syntax&lt;/span&gt; Main = Definition;&lt;br /&gt;   &lt;br /&gt;   &lt;span class="srckeyw"&gt;interleave&lt;/span&gt; Whitespace = " ";&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Parsing the code&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;After compiling the grammar we can now load it in F#. Based on the example presented the in the introductory articles we can write:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; Microsoft.M.Grammar&lt;br /&gt;&lt;span class="srckeyw"&gt;open&lt;/span&gt; System.Dataflow&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; runProgram() =&lt;br /&gt;   printf &lt;span class="srctext"&gt;"Start\n"&lt;/span&gt;&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; parser = MGrammarCompiler.LoadParserFromMgx(basepath+&lt;span class="srctext"&gt;"BinaryFileRecognizer.mgx"&lt;/span&gt;, null);&lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; parsedDocument = parser.ParseObject(basepath+&lt;span class="srctext"&gt;"sample.brg"&lt;/span&gt;,ErrorReporter.Standard)   &lt;br /&gt;   &lt;span class="srckeyw"&gt;let&lt;/span&gt; reco = buildRecognizer(parsedDocument)&lt;br /&gt;   ...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;buildRecognizer&lt;/code&gt; will navigate the MGraph structure generated by the parser and generate a binary file recognizer based on the code from the &lt;a href="http://langexplr.blogspot.com/2008/10/using-f-computation-expressions-to-read.html"&gt;"Using F# computation expressions to read binary files"&lt;/a&gt; post.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Active patterns for the parsed AST&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;As described in the C# samples provided in the "Programatic" section of the &lt;a href="http://msdn.microsoft.com/en-us/library/dd129870.aspx"&gt;MGrammar in a Nutshell&lt;/a&gt; article, the &lt;code&gt;GraphBuilder&lt;/code&gt; class provides a way to access parts of the parsed AST.&lt;br /&gt;&lt;br /&gt;By defining a some  &lt;a href="http://blogs.msdn.com/dsyme/archive/2007/04/07/draft-paper-on-f-active-patterns.aspx"&gt;F# Active Patterns&lt;/a&gt; we can improve the experience of navigating this tree structure.  For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; (|SequenceElements|_|)(x) = &lt;br /&gt;  &lt;span class="srckeyw"&gt;let&lt;/span&gt; gb = &lt;span class="srckeyw"&gt;new&lt;/span&gt; GraphBuilder() &lt;br /&gt;  &lt;span class="srckeyw"&gt;in&lt;/span&gt;    &lt;br /&gt;    &lt;span class="srckeyw"&gt;if&lt;/span&gt; (gb.IsSequence(x)) &lt;span class="srckeyw"&gt;then&lt;/span&gt;&lt;br /&gt;       Some(Seq.to_list &amp;lt;| gb.GetSequenceElements(x))&lt;br /&gt;    &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;       None&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; (|Entity|_|)(x) = &lt;br /&gt;  &lt;span class="srckeyw"&gt;let&lt;/span&gt; gb = &lt;span class="srckeyw"&gt;new&lt;/span&gt; GraphBuilder() &lt;br /&gt;  &lt;span class="srckeyw"&gt;in&lt;/span&gt;    &lt;br /&gt;    &lt;span class="srckeyw"&gt;if&lt;/span&gt; (gb.IsEntity(x)) &lt;span class="srckeyw"&gt;then&lt;/span&gt;&lt;br /&gt;       Some(gb.GetEntityLabel(x),&lt;br /&gt;            gb.GetEntityMembers(x) &lt;br /&gt;            |&amp;gt; Seq.map (fun (kvp:System.Collections.Generic.KeyValuePair&lt;obj,obj&gt;) -&gt; kvp.Value)&lt;br /&gt;            |&amp;gt; Seq.to_list)&lt;br /&gt;    &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;       None&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; (|EntityName|_|)(x) = &lt;br /&gt;  &lt;span class="srckeyw"&gt;let&lt;/span&gt; gb = &lt;span class="srckeyw"&gt;new&lt;/span&gt; GraphBuilder() &lt;br /&gt;  &lt;span class="srckeyw"&gt;in&lt;/span&gt;    &lt;br /&gt;    &lt;span class="srckeyw"&gt;if&lt;/span&gt; (gb.IsEntity(x)) &lt;span class="srckeyw"&gt;then&lt;/span&gt;&lt;br /&gt;       Some(gb.GetEntityLabel(x))&lt;br /&gt;    &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;       None &lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; (|Identifier|_|)(x:obj) =                  &lt;br /&gt;    &lt;span class="srckeyw"&gt;if&lt;/span&gt; (x :? System.Dataflow.Identifier) &lt;span class="srckeyw"&gt;then&lt;/span&gt;&lt;br /&gt;       &lt;span class="srckeyw"&gt;let&lt;/span&gt; identifier = (x :?&gt; System.Dataflow.Identifier)&lt;br /&gt;       &lt;span class="srckeyw"&gt;in&lt;/span&gt;&lt;br /&gt;           Some(identifier.Text)&lt;br /&gt;    &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;       None &lt;br /&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; (|AString|_|)(x:obj) =         &lt;br /&gt;       &lt;span class="srckeyw"&gt;if&lt;/span&gt; (x :? System.String) &lt;span class="srckeyw"&gt;then&lt;/span&gt;&lt;br /&gt;          Some(x :?&gt; System.String)&lt;br /&gt;       &lt;span class="srckeyw"&gt;else&lt;/span&gt;&lt;br /&gt;          None &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;These active pattern definitions allow the extraction of parts of a MGraph structure. &lt;br /&gt;&lt;br /&gt;For example given following code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;test = begin&lt;br /&gt;   int32 x&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The following tree structure is created by the parser.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Main[&lt;br /&gt;  Recognizer[&lt;br /&gt;    "test",&lt;br /&gt;    [&lt;br /&gt;      ItemDeclaration[&lt;br /&gt;        TypeDeclaration[&lt;br /&gt;          Int32[&lt;br /&gt;          ],&lt;br /&gt;          "x"&lt;br /&gt;        ]&lt;br /&gt;      ]&lt;br /&gt;    ]&lt;br /&gt;  ]&lt;br /&gt;]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Based on this example we can look at the definition of the &lt;code&gt;buildRecognizer&lt;/code&gt; function that was referenced above.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="srckeyw"&gt;let&lt;/span&gt; buildRecognizer(ast:obj) = &lt;br /&gt;   &lt;span class="srckeyw"&gt;match&lt;/span&gt; ast &lt;span class="srckeyw"&gt;with&lt;/span&gt;&lt;br /&gt;   | &lt;strong&gt;Entity(Identifier(&lt;span class="srctext"&gt;"Main"&lt;/span&gt;),&lt;br /&gt;            [Entity(Identifier(&lt;span class="srctext"&gt;"Recognizer"&lt;/span&gt;),&lt;br /&gt;                      [AString(name);&lt;br /&gt;                       SequenceElements(definitions)])]) &lt;/strong&gt; -&amp;gt; &lt;br /&gt;            printf &lt;span class="srctext"&gt;"Processing %s \n"&lt;/span&gt; name&lt;br /&gt;            buildingRecognizer(definitions,Map.empty,new BinParserBuilder())&lt;br /&gt;   | _ -&amp;gt; raise (new System.InvalidOperationException(&lt;span class="srctext"&gt;"Invalid document"&lt;/span&gt;))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that by combining the &lt;code&gt;Entity&lt;/code&gt; and &lt;code&gt;SequenceElements&lt;/code&gt; active patterns we can easily get the sequence of definitions for a given file.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the &lt;code&gt;buildingRecognizer&lt;/code&gt; we can process each different case of def
