I spent too much time reading the files, until today, when Minh Tuh pointed me the right direction on reading the floats...<br><br>Anyway, I will still keep trying until Xmas :-)<br><br><br><br><div class="gmail_quote">On Mon, Jun 29, 2009 at 15:40, Justin Bailey <span dir="ltr">&lt;<a href="mailto:jgbailey@gmail.com">jgbailey@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Anyone have thoughts to share? I&#39;d love to read others&#39; experiences<br>
but there isn&#39;t much coming up with searches or on redditt ...<br>
<br>
I was happiest with the VM I implemented. Sadly, I wasn&#39;t able to<br>
solve any of the scenarios, but my VM ran damn fast. That didn&#39;t seem<br>
to matter so much this year as it did two years ago - I think I am<br>
still scarred by Endo&#39;s DNA ..<br>
<br>
Anyways, for those who care, the heart of my VM implementation was a<br>
monadic fold over the program, with a mutable array representing the<br>
machine&#39;s memory, all inside &#39;&#39;runSTUArray.&#39;&#39; I used a simple data<br>
type to represent the machine:<br>
<br>
data Machine = Machine { instrs :: [OpCode]<br>
                       , dataMem :: UArray Int Val<br>
                       , outputs :: UArray Int Val<br>
                       , status :: !Int<br>
                       , inputs :: IntMap Val }<br>
<br>
where &#39;&#39;dataMem&#39;&#39; holds the data memory area. To execute a program, I<br>
folded over the &#39;&#39;instrs&#39;&#39; list and updated memory as I went:<br>
<br>
exec :: Machine -&gt; Input -&gt; Machine<br>
exec m@(Machine { instrs = instrs }) inps =<br>
    let m&#39; = m { inputs = readInputs inps }<br>
        newMem = runSTUArray $ do<br>
            mem&#39; &lt;- thaw (dataMem m)<br>
            foldM (step m&#39;) mem&#39; (zip instrs [0..])<br>
<br>
I considered &#39;&#39;unsafeThaw&#39;&#39; in the above, but performance didn&#39;t hurt<br>
me much and it seemed safer. Since I was recording all output I was<br>
worried that would break referential integrity. In any case, when the<br>
fold was finished I just assigned &#39;&#39;newMem&#39;&#39; to the new machine and<br>
moved to the next iteration.<br>
<br>
&#39;&#39;step&#39;&#39; takes the mutable array and updates it while the program<br>
executes. I won&#39;t show the whole body, as it just a separate<br>
definition for each opcode, just the type:<br>
<br>
  step :: Machine -&gt; STUArray s Int Val -&gt; (OpCode, Addr) -&gt; ST s<br>
(STUArray s Int Val)<br>
<br>
The only downside to this approach was the machine had three mutuable<br>
states: memory, output, and status. runSTUArray only wants to return a<br>
single array so inside step I had to hold all values in one array. Not<br>
a big deal but a little ugly.<br>
<br>
I kept a diary of my experience over the weekend at<br>
<a href="http://icfp2009.codeslower.com" target="_blank">http://icfp2009.codeslower.com</a>. I started out with such optimism ...<br>
Stil, I&#39;m glad to have done it. Lots of fun! My thanks to the<br>
organizers!<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</blockquote></div><br><br clear="all"><br>-- <br>Rafael Gustavo da Cunha Pereira Pinto<br>Electronic Engineer, MSc.<br>