update output
authorSimon Marlow <marlowsd@gmail.com>
Tue, 7 Oct 2008 15:31:22 +0000 (15:31 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Tue, 7 Oct 2008 15:31:22 +0000 (15:31 +0000)
tests/raytrace/hpc_raytrace.stdout

index 60fd7e2..91d0243 100644 (file)
@@ -1,7 +1,7 @@
 "GOOD MATCH"
 
 
- 48% expressions used (2292/4718)
+ 48% expressions used (2292/4715)
  21% boolean coverage (18/83)
       21% guards (12/55), 17 always True, 8 always False, 18 unevaluated
       22% 'if' conditions (6/27), 3 always True, 3 always False, 15 unevaluated
@@ -30,7 +30,7 @@
 100% local declarations used (5/5)
  41% top-level declarations used (17/41)
 -----<module Data>-----
- 39% expressions used (254/647)
+ 39% expressions used (254/646)
   0% boolean coverage (0/4)
        0% guards (0/4), 1 always True, 3 unevaluated
      100% 'if' conditions (0/0)
@@ -39,7 +39,7 @@
   0% local declarations used (0/2)
  22% top-level declarations used (10/45)
 -----<module Eval>-----
- 57% expressions used (361/629)
+ 57% expressions used (361/628)
  20% boolean coverage (1/5)
      100% guards (0/0)
       20% 'if' conditions (1/5), 1 always False, 3 unevaluated
@@ -57,7 +57,7 @@
  66% local declarations used (2/3)
  58% top-level declarations used (42/72)
 -----<module Illumination>-----
- 44% expressions used (299/679)
+ 44% expressions used (299/678)
  18% boolean coverage (3/16)
       16% guards (2/12), 2 always True, 1 always False, 7 unevaluated
       33% 'if' conditions (1/3), 1 always True, 1 always False
@@ -162,7 +162,7 @@ span.spaces    { background: white }
 
 </pre>
 </html>
-Writing: Eval.hs.html
+Writing: Parse.hs.html
 <html><style type="text/css">
 span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
 span.nottickedoff { background: yellow}
@@ -179,412 +179,194 @@ span.spaces    { background: white }
 <span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
 <span class="lineno">    4 </span>-- which is included in the distribution.
 <span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Eval where
+<span class="lineno">    6 </span>module Parse where
+<span class="lineno">    7 </span>
+<span class="lineno">    8 </span>import Char
+<span class="lineno">    9 </span>import Text.ParserCombinators.Parsec hiding (token)
+<span class="lineno">   10 </span>
+<span class="lineno">   11 </span>import Data
+<span class="lineno">   12 </span>
+<span class="lineno">   13 </span>
+<span class="lineno">   14 </span>program :: Parser Code
+<span class="lineno">   15 </span><span class="decl"><span class="istickedoff">program =</span>
+<span class="lineno">   16 </span><span class="spaces">  </span><span class="istickedoff">do { whiteSpace</span>
+<span class="lineno">   17 </span><span class="spaces">     </span><span class="istickedoff">; ts &lt;- tokenList</span>
+<span class="lineno">   18 </span><span class="spaces">     </span><span class="istickedoff">; eof</span>
+<span class="lineno">   19 </span><span class="spaces">     </span><span class="istickedoff">; return ts</span>
+<span class="lineno">   20 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
+<span class="lineno">   21 </span>
+<span class="lineno">   22 </span>tokenList :: Parser Code
+<span class="lineno">   23 </span><span class="decl"><span class="istickedoff">tokenList = many token &lt;?&gt; <span class="nottickedoff">&quot;list of tokens&quot;</span></span></span>
+<span class="lineno">   24 </span>
+<span class="lineno">   25 </span>token :: Parser GMLToken
+<span class="lineno">   26 </span><span class="decl"><span class="istickedoff">token =</span>
+<span class="lineno">   27 </span><span class="spaces">       </span><span class="istickedoff">do { ts &lt;- braces   tokenList          ; return (TBody ts) } </span>
+<span class="lineno">   28 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt;  do { ts &lt;- brackets tokenList          ; return (TArray ts) }</span>
+<span class="lineno">   29 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt; (do { s  &lt;- gmlString                   ; return (TString <span class="nottickedoff">s</span>) } &lt;?&gt; <span class="nottickedoff">&quot;string&quot;</span>)</span>
+<span class="lineno">   30 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt; (do { t &lt;- pident False                 ; return t }           &lt;?&gt; <span class="nottickedoff">&quot;identifier&quot;</span>)</span>
+<span class="lineno">   31 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt; (do { char '/'   -- No whitespace after slash</span>
+<span class="lineno">   32 </span><span class="spaces">          </span><span class="istickedoff">; t &lt;- pident True                  ; return t } &lt;?&gt; <span class="nottickedoff">&quot;binding identifier&quot;</span>)</span>
+<span class="lineno">   33 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt; (do { n &lt;- number                       ; return n } &lt;?&gt; <span class="nottickedoff">&quot;number&quot;</span>)</span></span>
+<span class="lineno">   34 </span>
+<span class="lineno">   35 </span>pident :: Bool -&gt; Parser GMLToken
+<span class="lineno">   36 </span><span class="decl"><span class="istickedoff">pident rebind =</span>
+<span class="lineno">   37 </span><span class="spaces">  </span><span class="istickedoff">do { id &lt;- ident</span>
+<span class="lineno">   38 </span><span class="spaces">     </span><span class="istickedoff">; case (lookup id opTable) of</span>
+<span class="lineno">   39 </span><span class="spaces">       </span><span class="istickedoff">Nothing -&gt; if rebind then return (TBind id) else return (TId id)</span>
+<span class="lineno">   40 </span><span class="spaces">       </span><span class="istickedoff">Just t  -&gt; if <span class="tickonlyfalse">rebind</span> then <span class="nottickedoff">error (&quot;Attempted rebinding of identifier &quot; ++ id)</span> else return t</span>
+<span class="lineno">   41 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
+<span class="lineno">   42 </span>
+<span class="lineno">   43 </span>ident :: Parser String
+<span class="lineno">   44 </span><span class="decl"><span class="istickedoff">ident = lexeme $</span>
+<span class="lineno">   45 </span><span class="spaces">  </span><span class="istickedoff">do { l &lt;- letter</span>
+<span class="lineno">   46 </span><span class="spaces">     </span><span class="istickedoff">; ls &lt;- many (satisfy (\x -&gt; isAlphaNum x || x == '-' || x == '_'))</span>
+<span class="lineno">   47 </span><span class="spaces">     </span><span class="istickedoff">; return (l:ls)</span>
+<span class="lineno">   48 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
+<span class="lineno">   49 </span>
+<span class="lineno">   50 </span>gmlString :: Parser String
+<span class="lineno">   51 </span><span class="decl"><span class="istickedoff">gmlString = lexeme $ between (char '&quot;') (char '&quot;') (many (satisfy (\x -&gt; isPrint x &amp;&amp; x /= '&quot;')))</span></span>
+<span class="lineno">   52 </span>
+<span class="lineno">   53 </span>-- Tests for numbers
+<span class="lineno">   54 </span>-- Hugs breaks on big exponents (&gt; ~40)
+<span class="lineno">   55 </span><span class="decl"><span class="nottickedoff">test_number = &quot;1234 -1234 1 -0 0&quot; ++</span>
+<span class="lineno">   56 </span><span class="spaces">              </span><span class="nottickedoff">&quot; 1234.5678 -1234.5678 1234.5678e12 1234.5678e-12 -1234.5678e-12&quot; ++</span>
+<span class="lineno">   57 </span><span class="spaces">              </span><span class="nottickedoff">&quot; -1234.5678e12 -1234.5678E-12 -1234.5678E12&quot; ++</span>
+<span class="lineno">   58 </span><span class="spaces">              </span><span class="nottickedoff">&quot; 1234e11 1234E33 -1234e33 1234e-33&quot; ++</span>
+<span class="lineno">   59 </span><span class="spaces">              </span><span class="nottickedoff">&quot; 123e 123.4e 123ee 123.4ee 123E 123.4E 123EE 123.4EE&quot;</span></span>
+<span class="lineno">   60 </span>              
+<span class="lineno">   61 </span>
+<span class="lineno">   62 </span>-- Always int or real
+<span class="lineno">   63 </span>number :: Parser GMLToken
+<span class="lineno">   64 </span><span class="decl"><span class="istickedoff">number = lexeme $</span>
+<span class="lineno">   65 </span><span class="spaces">  </span><span class="istickedoff">do { s &lt;- optSign</span>
+<span class="lineno">   66 </span><span class="spaces">     </span><span class="istickedoff">; n &lt;- decimal</span>
+<span class="lineno">   67 </span><span class="spaces">     </span><span class="istickedoff">;     do { string &quot;.&quot;</span>
+<span class="lineno">   68 </span><span class="spaces">              </span><span class="istickedoff">; m &lt;- decimal</span>
+<span class="lineno">   69 </span><span class="spaces">              </span><span class="istickedoff">; e &lt;- option &quot;&quot; exponent'</span>
+<span class="lineno">   70 </span><span class="spaces">              </span><span class="istickedoff">; return (TReal (read (s ++ n ++ &quot;.&quot; ++ m ++ e)))  -- FIXME: Handle error conditions</span>
+<span class="lineno">   71 </span><span class="spaces">              </span><span class="istickedoff">}</span>
+<span class="lineno">   72 </span><span class="spaces">       </span><span class="istickedoff">&lt;|&gt; do { e &lt;- exponent'</span>
+<span class="lineno">   73 </span><span class="spaces">              </span><span class="istickedoff">; <span class="nottickedoff">return (TReal (read (s ++ n ++ &quot;.0&quot; ++ e)))</span></span>
+<span class="lineno">   74 </span><span class="spaces">              </span><span class="istickedoff">}</span>
+<span class="lineno">   75 </span><span class="spaces">       </span><span class="istickedoff">&lt;|&gt; do { return (TInt (read (s ++ n))) }</span>
+<span class="lineno">   76 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
+<span class="lineno">   77 </span>
+<span class="lineno">   78 </span>exponent' :: Parser String
+<span class="lineno">   79 </span><span class="decl"><span class="istickedoff">exponent' = try $</span>
+<span class="lineno">   80 </span><span class="spaces">  </span><span class="istickedoff">do { e &lt;- oneOf &quot;eE&quot;</span>
+<span class="lineno">   81 </span><span class="spaces">     </span><span class="istickedoff">; s &lt;- <span class="nottickedoff">optSign</span></span>
+<span class="lineno">   82 </span><span class="spaces">     </span><span class="istickedoff">; n &lt;- <span class="nottickedoff">decimal</span></span>
+<span class="lineno">   83 </span><span class="spaces">     </span><span class="istickedoff">; <span class="nottickedoff">return (e:s ++ n)</span></span>
+<span class="lineno">   84 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
+<span class="lineno">   85 </span>
+<span class="lineno">   86 </span><span class="decl"><span class="istickedoff">decimal = many1 digit</span></span>
+<span class="lineno">   87 </span>
+<span class="lineno">   88 </span>optSign :: Parser String
+<span class="lineno">   89 </span><span class="decl"><span class="istickedoff">optSign = option &quot;&quot; (string &quot;-&quot;)</span></span>
+<span class="lineno">   90 </span>
+<span class="lineno">   91 </span>
+<span class="lineno">   92 </span>------------------------------------------------------
+<span class="lineno">   93 </span>-- Library for tokenizing.
+<span class="lineno">   94 </span>
+<span class="lineno">   95 </span><span class="decl"><span class="istickedoff">braces   p = between (symbol &quot;{&quot;) (symbol &quot;}&quot;) p</span></span>
+<span class="lineno">   96 </span><span class="decl"><span class="istickedoff">brackets p = between (symbol &quot;[&quot;) (symbol &quot;]&quot;) p</span></span>
+<span class="lineno">   97 </span>
+<span class="lineno">   98 </span><span class="decl"><span class="istickedoff">symbol name = lexeme (string name)</span></span>
+<span class="lineno">   99 </span>
+<span class="lineno">  100 </span><span class="decl"><span class="istickedoff">lexeme p = do{ x &lt;- p; whiteSpace; return x  }</span></span>
+<span class="lineno">  101 </span>
+<span class="lineno">  102 </span><span class="decl"><span class="istickedoff">whiteSpace  = skipMany (simpleSpace &lt;|&gt; oneLineComment &lt;?&gt; <span class="nottickedoff">&quot;&quot;</span>)</span>
+<span class="lineno">  103 </span><span class="spaces">  </span><span class="istickedoff">where simpleSpace = skipMany1 (oneOf &quot; \t\n\r\v&quot;)    </span>
+<span class="lineno">  104 </span><span class="spaces">        </span><span class="istickedoff">oneLineComment =</span>
+<span class="lineno">  105 </span><span class="spaces">            </span><span class="istickedoff">do{ string &quot;%&quot;</span>
+<span class="lineno">  106 </span><span class="spaces">              </span><span class="istickedoff">; skipMany (noneOf &quot;\n\r\v&quot;)</span>
+<span class="lineno">  107 </span><span class="spaces">              </span><span class="istickedoff">; return ()</span>
+<span class="lineno">  108 </span><span class="spaces">              </span><span class="istickedoff">}</span></span>
+<span class="lineno">  109 </span>
+<span class="lineno">  110 </span>
+<span class="lineno">  111 </span>------------------------------------------------------------------------------
+<span class="lineno">  112 </span>
+<span class="lineno">  113 </span>rayParse :: String -&gt; Code
+<span class="lineno">  114 </span><span class="decl"><span class="istickedoff">rayParse is = case (parse program <span class="nottickedoff">&quot;&lt;stdin&gt;&quot;</span> is) of</span>
+<span class="lineno">  115 </span><span class="spaces">              </span><span class="istickedoff">Left err -&gt; <span class="nottickedoff">error (show err)</span></span>
+<span class="lineno">  116 </span><span class="spaces">              </span><span class="istickedoff">Right x  -&gt; x</span></span>
+<span class="lineno">  117 </span>
+<span class="lineno">  118 </span>rayParseF :: String -&gt; IO Code
+<span class="lineno">  119 </span><span class="decl"><span class="nottickedoff">rayParseF file =</span>
+<span class="lineno">  120 </span><span class="spaces">  </span><span class="nottickedoff">do { r &lt;- parseFromFile program file</span>
+<span class="lineno">  121 </span><span class="spaces">     </span><span class="nottickedoff">; case r of</span>
+<span class="lineno">  122 </span><span class="spaces">       </span><span class="nottickedoff">Left err -&gt; error (show err)</span>
+<span class="lineno">  123 </span><span class="spaces">       </span><span class="nottickedoff">Right x  -&gt; return x</span>
+<span class="lineno">  124 </span><span class="spaces">     </span><span class="nottickedoff">}</span></span>
+<span class="lineno">  125 </span>
+<span class="lineno">  126 </span>run :: String -&gt; IO ()
+<span class="lineno">  127 </span><span class="decl"><span class="nottickedoff">run is = case (parse program &quot;&quot; is) of</span>
+<span class="lineno">  128 </span><span class="spaces">         </span><span class="nottickedoff">Left err -&gt; print err</span>
+<span class="lineno">  129 </span><span class="spaces">         </span><span class="nottickedoff">Right x  -&gt; print x</span></span>
+<span class="lineno">  130 </span>
+<span class="lineno">  131 </span>runF :: IO ()
+<span class="lineno">  132 </span><span class="decl"><span class="nottickedoff">runF =</span>
+<span class="lineno">  133 </span><span class="spaces">  </span><span class="nottickedoff">do { r &lt;- parseFromFile program &quot;simple.gml&quot;</span>
+<span class="lineno">  134 </span><span class="spaces">     </span><span class="nottickedoff">; case r of</span>
+<span class="lineno">  135 </span><span class="spaces">       </span><span class="nottickedoff">Left err -&gt; print err</span>
+<span class="lineno">  136 </span><span class="spaces">       </span><span class="nottickedoff">Right x  -&gt; print x</span>
+<span class="lineno">  137 </span><span class="spaces">     </span><span class="nottickedoff">}</span></span>
+
+</pre>
+</html>
+Writing: Data.hs.html
+<html><style type="text/css">
+span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
+span.nottickedoff { background: yellow}
+span.istickedoff { background: white }
+span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
+span.tickonlytrue  { margin: -1px; border: 1px solid #60de51; background: #60de51 }
+span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
+span.decl { font-weight: bold }
+span.spaces    { background: white }
+</style>
+<pre>
+<span class="lineno">    1 </span>-- Copyright (c) 2000 Galois Connections, Inc.
+<span class="lineno">    2 </span>-- All rights reserved.  This software is distributed as
+<span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
+<span class="lineno">    4 </span>-- which is included in the distribution.
+<span class="lineno">    5 </span>
+<span class="lineno">    6 </span>module Data where
 <span class="lineno">    7 </span>
 <span class="lineno">    8 </span>import Array
 <span class="lineno">    9 </span>
-<span class="lineno">   10 </span>import Geometry
-<span class="lineno">   11 </span>import CSG
-<span class="lineno">   12 </span>import Surface
-<span class="lineno">   13 </span>import Data
-<span class="lineno">   14 </span>import Parse (rayParse, rayParseF)
+<span class="lineno">   10 </span>import CSG      
+<span class="lineno">   11 </span>import Geometry
+<span class="lineno">   12 </span>import Illumination
+<span class="lineno">   13 </span>import Primitives
+<span class="lineno">   14 </span>import Surface
 <span class="lineno">   15 </span>
-<span class="lineno">   16 </span>class Monad m =&gt; MonadEval m where
-<span class="lineno">   17 </span>  doOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; m Stack
-<span class="lineno">   18 </span>  tick :: m ()
-<span class="lineno">   19 </span>  err  :: String -&gt; m a
-<span class="lineno">   20 </span>
-<span class="lineno">   21 </span>  <span class="decl"><span class="istickedoff">tick = return <span class="nottickedoff">()</span></span></span>
-<span class="lineno">   22 </span>
-<span class="lineno">   23 </span>newtype Pure a = Pure a deriving <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>
-<span class="lineno">   24 </span>
-<span class="lineno">   25 </span>instance Monad Pure where
-<span class="lineno">   26 </span>    <span class="decl"><span class="istickedoff">Pure x &gt;&gt;= k = k x</span></span>
-<span class="lineno">   27 </span>    <span class="decl"><span class="istickedoff">return       = Pure</span></span>
-<span class="lineno">   28 </span>    <span class="decl"><span class="nottickedoff">fail s       = error s</span></span>
-<span class="lineno">   29 </span>
-<span class="lineno">   30 </span>instance MonadEval Pure where
-<span class="lineno">   31 </span>  <span class="decl"><span class="istickedoff">doOp   = doPureOp</span></span> 
-<span class="lineno">   32 </span>  <span class="decl"><span class="nottickedoff">err  s = error s</span></span>
-<span class="lineno">   33 </span>
-<span class="lineno">   34 </span>instance MonadEval IO where
-<span class="lineno">   35 </span>  <span class="decl"><span class="istickedoff">doOp prim op stk = do { -- putStrLn (&quot;Calling &quot; ++ show op</span>
-<span class="lineno">   36 </span><span class="spaces">                          </span><span class="istickedoff">--           ++ &quot; &lt;&lt; &quot; ++ show stk ++ &quot; &gt;&gt;&quot;)</span>
-<span class="lineno">   37 </span><span class="spaces">                          </span><span class="istickedoff">doAllOp  prim op stk</span>
-<span class="lineno">   38 </span><span class="spaces">                        </span><span class="istickedoff">}</span></span>
-<span class="lineno">   39 </span>  <span class="decl"><span class="nottickedoff">err  s = error s</span></span>
+<span class="lineno">   16 </span>import Debug.Trace
+<span class="lineno">   17 </span>
+<span class="lineno">   18 </span>-- Now the parsed (expresssion) language
+<span class="lineno">   19 </span>
+<span class="lineno">   20 </span>type Name = String
+<span class="lineno">   21 </span>
+<span class="lineno">   22 </span>type Code = [GMLToken]
+<span class="lineno">   23 </span>
+<span class="lineno">   24 </span>data GMLToken
+<span class="lineno">   25 </span>    -- All these can occur in parsed code
+<span class="lineno">   26 </span>        = TOp     GMLOp
+<span class="lineno">   27 </span>        | TId     Name
+<span class="lineno">   28 </span>        | TBind   Name
+<span class="lineno">   29 </span>        | TBool   Bool
+<span class="lineno">   30 </span>        | TInt    Int
+<span class="lineno">   31 </span>        | TReal   Double
+<span class="lineno">   32 </span>        | TString String
+<span class="lineno">   33 </span>        | TBody   Code
+<span class="lineno">   34 </span>        | TArray  Code
+<span class="lineno">   35 </span>        | TApply
+<span class="lineno">   36 </span>        | TIf
+<span class="lineno">   37 </span>         -- These can occur in optimized/transformed code
+<span class="lineno">   38 </span>         -- NONE (yet!)
+<span class="lineno">   39 </span>
 <span class="lineno">   40 </span>
-<span class="lineno">   41 </span>data State
-<span class="lineno">   42 </span>        = State { env   :: Env
-<span class="lineno">   43 </span>                , stack :: Stack
-<span class="lineno">   44 </span>                , code  :: Code
-<span class="lineno">   45 </span>                } deriving <span class="nottickedoff"><span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span></span>
-<span class="lineno">   46 </span>
-<span class="lineno">   47 </span>callback :: Env -&gt; Code -&gt; Stack -&gt; Stack
-<span class="lineno">   48 </span><span class="decl"><span class="istickedoff">callback env code stk</span>
-<span class="lineno">   49 </span><span class="spaces">      </span><span class="istickedoff">= case eval (State { env = env, stack = stk, code = code}) of</span>
-<span class="lineno">   50 </span><span class="spaces">             </span><span class="istickedoff">Pure stk -&gt; stk</span></span>
-<span class="lineno">   51 </span>
-<span class="lineno">   52 </span>{-# SPECIALIZE eval ::  State -&gt; Pure Stack #-}
-<span class="lineno">   53 </span>{-# SPECIALIZE eval ::  State -&gt; IO Stack #-}
-<span class="lineno">   54 </span>
-<span class="lineno">   55 </span>eval :: MonadEval m =&gt; State -&gt; m Stack
-<span class="lineno">   56 </span><span class="decl"><span class="istickedoff">eval st =</span>
-<span class="lineno">   57 </span><span class="spaces">  </span><span class="istickedoff">do { () &lt;- return () -- $ unsafePerformIO (print st)   -- Functional debugger</span>
-<span class="lineno">   58 </span><span class="spaces">     </span><span class="istickedoff">; if moreCode st then</span>
-<span class="lineno">   59 </span><span class="spaces">       </span><span class="istickedoff">do { tick             -- tick first, so as to catch loops on new eval.</span>
-<span class="lineno">   60 </span><span class="spaces">            </span><span class="istickedoff">; st' &lt;- step st</span>
-<span class="lineno">   61 </span><span class="spaces">            </span><span class="istickedoff">; eval st'</span>
-<span class="lineno">   62 </span><span class="spaces">            </span><span class="istickedoff">}</span>
-<span class="lineno">   63 </span><span class="spaces">        </span><span class="istickedoff">else return (stack st)</span>
-<span class="lineno">   64 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
-<span class="lineno">   65 </span>     
-<span class="lineno">   66 </span>moreCode :: State -&gt; Bool
-<span class="lineno">   67 </span><span class="decl"><span class="istickedoff">moreCode (State {code = []}) = False</span>
-<span class="lineno">   68 </span><span class="spaces"></span><span class="istickedoff">moreCode _                   = True</span></span>
-<span class="lineno">   69 </span>
-<span class="lineno">   70 </span>-- Step has a precondition that there *is* code to run
-<span class="lineno">   71 </span>{-# SPECIALIZE step ::  State -&gt; Pure State #-}
-<span class="lineno">   72 </span>{-# SPECIALIZE step ::  State -&gt; IO State #-}
-<span class="lineno">   73 </span>step :: MonadEval m =&gt; State -&gt; m State
-<span class="lineno">   74 </span>
-<span class="lineno">   75 </span>-- Rule 1: Pushing BaseValues
-<span class="lineno">   76 </span><span class="decl"><span class="istickedoff">step st@(State{ stack = stack, code = (TBool b):cs })    </span>
-<span class="lineno">   77 </span><span class="spaces">    </span><span class="istickedoff">= <span class="nottickedoff">return (st { stack = (VBool b):stack,    code = cs })</span></span>
-<span class="lineno">   78 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ stack = stack, code = (TInt i):cs })     </span>
-<span class="lineno">   79 </span><span class="spaces">    </span><span class="istickedoff">= return (st { stack = (VInt i):stack,     code = cs })</span>
-<span class="lineno">   80 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ stack = stack, code = (TReal r):cs })    </span>
-<span class="lineno">   81 </span><span class="spaces">    </span><span class="istickedoff">= return (st { stack = (VReal r):stack,    code = cs })</span>
-<span class="lineno">   82 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ stack = stack, code = (TString s):cs })  </span>
-<span class="lineno">   83 </span><span class="spaces">    </span><span class="istickedoff">= return (st { stack = (VString <span class="nottickedoff">s</span>):stack,  code = cs })</span>
-<span class="lineno">   84 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">   85 </span><span class="spaces"></span><span class="istickedoff">-- Rule 2: Name binding</span>
-<span class="lineno">   86 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = (v:stack), code = (TBind id):cs }) =</span>
-<span class="lineno">   87 </span><span class="spaces">  </span><span class="istickedoff">return (State { env = extendEnv env id v, stack = stack,  code = cs })</span>
-<span class="lineno">   88 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = [], code = (TBind id):cs }) =</span>
-<span class="lineno">   89 </span><span class="spaces">  </span><span class="istickedoff"><span class="nottickedoff">err &quot;Attempt to bind the top of an empty stack&quot;</span></span>
-<span class="lineno">   90 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">   91 </span><span class="spaces"></span><span class="istickedoff">-- Rule 3: Name lookup</span>
-<span class="lineno">   92 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = stack, code = (TId id):cs }) =</span>
-<span class="lineno">   93 </span><span class="spaces">  </span><span class="istickedoff">case (lookupEnv env id) of</span>
-<span class="lineno">   94 </span><span class="spaces">  </span><span class="istickedoff">Just v -&gt; return (st { stack = v:stack,  code = cs })</span>
-<span class="lineno">   95 </span><span class="spaces">  </span><span class="istickedoff">Nothing -&gt; <span class="nottickedoff">err (&quot;Cannot find value for identifier: &quot; ++ id)</span></span>
-<span class="lineno">   96 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">   97 </span><span class="spaces"></span><span class="istickedoff">-- Rule 4: Closure creation</span>
-<span class="lineno">   98 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = stack, code = (TBody body):cs }) =</span>
-<span class="lineno">   99 </span><span class="spaces">  </span><span class="istickedoff">return (st { stack = (VClosure env body):stack, code = cs })</span>
-<span class="lineno">  100 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  101 </span><span class="spaces"></span><span class="istickedoff">-- Rule 5: Application</span>
-<span class="lineno">  102 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = (VClosure env' code'):stack, code = TApply:cs }) =</span>
-<span class="lineno">  103 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- eval (State {env = <span class="nottickedoff">env'</span>, stack = stack, code = code'})</span>
-<span class="lineno">  104 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = stk, code = cs })</span>
-<span class="lineno">  105 </span><span class="spaces">     </span><span class="istickedoff">}</span>
-<span class="lineno">  106 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = [], code = TApply:cs }) =</span>
-<span class="lineno">  107 </span><span class="spaces">  </span><span class="istickedoff"><span class="nottickedoff">err &quot;Application with an empty stack&quot;</span></span>
-<span class="lineno">  108 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = _:_, code = TApply:cs }) =</span>
-<span class="lineno">  109 </span><span class="spaces">  </span><span class="istickedoff"><span class="nottickedoff">err &quot;Application of a non-closure&quot;</span></span>
-<span class="lineno">  110 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  111 </span><span class="spaces"></span><span class="istickedoff">-- Rule 6: Arrays</span>
-<span class="lineno">  112 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = stack, code = TArray code':cs }) =</span>
-<span class="lineno">  113 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- eval (State {env = env, stack = [], code = code'})</span>
-<span class="lineno">  114 </span><span class="spaces">     </span><span class="istickedoff">; let last = length stk-1</span>
-<span class="lineno">  115 </span><span class="spaces">     </span><span class="istickedoff">; let arr = array (0,last) (zip [last,last-1..] stk)</span>
-<span class="lineno">  116 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = (VArray arr):stack, code = cs })</span>
-<span class="lineno">  117 </span><span class="spaces">     </span><span class="istickedoff">}</span>
-<span class="lineno">  118 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  119 </span><span class="spaces"></span><span class="istickedoff">-- Rule 7 &amp; 8: If statement</span>
-<span class="lineno">  120 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = (VClosure e2 c2):(VClosure e1 c1):(VBool True):stack, code = TIf:cs }) =</span>
-<span class="lineno">  121 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- eval (State {env = e1, stack = stack, code = c1})</span>
-<span class="lineno">  122 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = stk, code = cs })</span>
-<span class="lineno">  123 </span><span class="spaces">     </span><span class="istickedoff">}</span>
-<span class="lineno">  124 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = (VClosure e2 c2):(VClosure e1 c1):(VBool False):stack, code = TIf:cs }) =</span>
-<span class="lineno">  125 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- eval (State {env = e2, stack = stack, code = c2})</span>
-<span class="lineno">  126 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = stk, code = cs })</span>
-<span class="lineno">  127 </span><span class="spaces">     </span><span class="istickedoff">}</span>
-<span class="lineno">  128 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = _, code = TIf:cs }) =</span>
-<span class="lineno">  129 </span><span class="spaces">  </span><span class="istickedoff"><span class="nottickedoff">err &quot;Incorrect use of if (bad and/or inappropriate values on the stack)&quot;</span></span>
-<span class="lineno">  130 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  131 </span><span class="spaces"></span><span class="istickedoff">-- Rule 9: Operators</span>
-<span class="lineno">  132 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = stack, code = (TOp op):cs }) =</span>
-<span class="lineno">  133 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- doOp (opFnTable ! op) op stack</span>
-<span class="lineno">  134 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = stk, code = cs })</span>
-<span class="lineno">  135 </span><span class="spaces">     </span><span class="istickedoff">}</span>
-<span class="lineno">  136 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  137 </span><span class="spaces"></span><span class="istickedoff">-- Rule Opps</span>
-<span class="lineno">  138 </span><span class="spaces"></span><span class="istickedoff">step _ = <span class="nottickedoff">err &quot;Tripped on sidewalk while stepping.&quot;</span></span></span>
-<span class="lineno">  139 </span>
-<span class="lineno">  140 </span>
-<span class="lineno">  141 </span>--------------------------------------------------------------------------
-<span class="lineno">  142 </span>-- Operator code
-<span class="lineno">  143 </span>
-<span class="lineno">  144 </span>opFnTable :: Array GMLOp PrimOp
-<span class="lineno">  145 </span><span class="decl"><span class="istickedoff">opFnTable = array (minBound,maxBound) </span>
-<span class="lineno">  146 </span><span class="spaces">                  </span><span class="istickedoff">[ (op,prim) | (_,TOp op,prim) &lt;- opcodes ]</span></span>
-<span class="lineno">  147 </span>
-<span class="lineno">  148 </span>
-<span class="lineno">  149 </span>
-<span class="lineno">  150 </span>
-<span class="lineno">  151 </span>doPureOp :: (MonadEval m) =&gt; PrimOp -&gt; GMLOp -&gt; Stack -&gt; m Stack
-<span class="lineno">  152 </span><span class="decl"><span class="istickedoff">doPureOp _ Op_render _ = </span>
-<span class="lineno">  153 </span><span class="spaces">    </span><span class="istickedoff"><span class="nottickedoff">err (&quot;\nAttempting to call render from inside a purely functional callback.&quot;)</span></span>
-<span class="lineno">  154 </span><span class="spaces"></span><span class="istickedoff">doPureOp primOp op stk = doPrimOp primOp <span class="nottickedoff">op</span> stk</span></span> -- call the purely functional operators
-<span class="lineno">  155 </span>
-<span class="lineno">  156 </span>{-# SPECIALIZE doPrimOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; Pure Stack #-}
-<span class="lineno">  157 </span>{-# SPECIALIZE doPrimOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; IO Stack #-}
-<span class="lineno">  158 </span>{-# SPECIALIZE doPrimOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; Abs Stack #-}
-<span class="lineno">  159 </span>
-<span class="lineno">  160 </span>doPrimOp ::  (MonadEval m) =&gt; PrimOp -&gt; GMLOp -&gt; Stack -&gt; m Stack
-<span class="lineno">  161 </span>
-<span class="lineno">  162 </span>-- 1 argument.
-<span class="lineno">  163 </span>
-<span class="lineno">  164 </span><span class="decl"><span class="istickedoff">doPrimOp (Int_Int fn) _ (VInt i1:stk)</span>
-<span class="lineno">  165 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">return ((VInt (fn i1)) : stk)</span></span>
-<span class="lineno">  166 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Real fn) _ (VReal r1:stk)</span>
-<span class="lineno">  167 </span><span class="spaces">  </span><span class="istickedoff">= return ((VReal (fn r1)) : stk)</span>
-<span class="lineno">  168 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Point_Real fn) _ (VPoint x y z:stk)</span>
-<span class="lineno">  169 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">return ((VReal (fn x y z)) : stk)</span></span>
-<span class="lineno">  170 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  171 </span><span class="spaces"></span><span class="istickedoff">-- This is where the callbacks happen from...</span>
-<span class="lineno">  172 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Surface_Obj fn) _ (VClosure env code:stk)</span>
-<span class="lineno">  173 </span><span class="spaces">  </span><span class="istickedoff">= case absapply env code [<span class="nottickedoff">VAbsObj AbsFACE</span>,<span class="nottickedoff">VAbsObj AbsU</span>,<span class="nottickedoff">VAbsObj AbsV</span>] of</span>
-<span class="lineno">  174 </span><span class="spaces">      </span><span class="istickedoff">Just [VReal r3,VReal r2,VReal r1,VPoint c1 c2 c3] -&gt; </span>
-<span class="lineno">  175 </span><span class="spaces">           </span><span class="istickedoff"><span class="nottickedoff">let</span></span>
-<span class="lineno">  176 </span><span class="spaces">               </span><span class="istickedoff"><span class="nottickedoff">res = prop (color c1 c2 c3) r1 r2 r3</span></span>
-<span class="lineno">  177 </span><span class="spaces">           </span><span class="istickedoff"><span class="nottickedoff">in</span></span>
-<span class="lineno">  178 </span><span class="spaces">               </span><span class="istickedoff"><span class="nottickedoff">return ((VObject (fn (SConst res))) : stk)</span></span>
-<span class="lineno">  179 </span><span class="spaces">      </span><span class="istickedoff">_ -&gt; return ((VObject (fn (SFun call))) : stk)</span>
-<span class="lineno">  180 </span><span class="spaces">  </span><span class="istickedoff">where </span>
-<span class="lineno">  181 </span><span class="spaces">        </span><span class="istickedoff">-- The most general case</span>
-<span class="lineno">  182 </span><span class="spaces">        </span><span class="istickedoff">call i r1 r2 =</span>
-<span class="lineno">  183 </span><span class="spaces">          </span><span class="istickedoff">case callback env code [VReal r2,VReal r1,<span class="nottickedoff">VInt i</span>] of</span>
-<span class="lineno">  184 </span><span class="spaces">             </span><span class="istickedoff">[VReal r3,VReal r2,VReal r1,VPoint c1 c2 c3] </span>
-<span class="lineno">  185 </span><span class="spaces">                 </span><span class="istickedoff">-&gt; prop (color c1 c2 c3) r1 r2 r3</span>
-<span class="lineno">  186 </span><span class="spaces">             </span><span class="istickedoff">stk -&gt; <span class="nottickedoff">error (&quot;callback failed: incorrectly typed return arguments&quot;</span></span>
-<span class="lineno">  187 </span><span class="spaces">                         </span><span class="istickedoff"><span class="nottickedoff">++ show stk)</span></span>
-<span class="lineno">  188 </span><span class="spaces">       </span><span class="istickedoff"></span>
-<span class="lineno">  189 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Int fn) _ (VReal r1:stk)</span>
-<span class="lineno">  190 </span><span class="spaces">  </span><span class="istickedoff">= return ((VInt (fn r1)) : stk)</span>
-<span class="lineno">  191 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Int_Real fn) _ (VInt r1:stk)</span>
-<span class="lineno">  192 </span><span class="spaces">  </span><span class="istickedoff">= return ((VReal (fn r1)) : stk)</span>
-<span class="lineno">  193 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Arr_Int fn) _ (VArray arr:stk)</span>
-<span class="lineno">  194 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">return ((VInt (fn arr)) : stk)</span></span>
-<span class="lineno">  195 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  196 </span><span class="spaces"></span><span class="istickedoff">-- 2 arguments.</span>
-<span class="lineno">  197 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  198 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Int_Int_Int fn) _ (VInt i2:VInt i1:stk)</span>
-<span class="lineno">  199 </span><span class="spaces">  </span><span class="istickedoff">= return ((VInt (fn i1 i2)) : stk)</span>
-<span class="lineno">  200 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Int_Int_Bool fn) _ (VInt i2:VInt i1:stk)</span>
-<span class="lineno">  201 </span><span class="spaces">  </span><span class="istickedoff">= return ((VBool (fn i1 i2)) : stk)</span>
-<span class="lineno">  202 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Real_Real fn) _ (VReal r2:VReal r1:stk)</span>
-<span class="lineno">  203 </span><span class="spaces">  </span><span class="istickedoff">= return ((VReal (fn r1 r2)) : stk)</span>
-<span class="lineno">  204 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Real_Bool fn) _ (VReal r2:VReal r1:stk)</span>
-<span class="lineno">  205 </span><span class="spaces">  </span><span class="istickedoff">= return ((VBool (fn r1 r2)) : stk)</span>
-<span class="lineno">  206 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Arr_Int_Value fn) _ (VInt i:VArray arr:stk)</span>
-<span class="lineno">  207 </span><span class="spaces">  </span><span class="istickedoff">= return ((fn arr i) : stk)</span>
-<span class="lineno">  208 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  209 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  210 </span><span class="spaces">    </span><span class="istickedoff">-- Many arguments, typically image mangling</span>
-<span class="lineno">  211 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  212 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Obj_Obj_Obj fn) _ (VObject o2:VObject o1:stk)</span>
-<span class="lineno">  213 </span><span class="spaces">  </span><span class="istickedoff">= return ((VObject (fn o1 o2)) : <span class="nottickedoff">stk</span>)</span>
-<span class="lineno">  214 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Point_Color_Light fn) _ (VPoint r g b:VPoint x y z : stk)</span>
-<span class="lineno">  215 </span><span class="spaces">  </span><span class="istickedoff">= return (VLight (fn (x,y,z) (color r g b)) : <span class="nottickedoff">stk</span>)</span>
-<span class="lineno">  216 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Point_Point_Color_Real_Real_Light fn) _ </span>
-<span class="lineno">  217 </span><span class="spaces">         </span><span class="istickedoff">(VReal r2:VReal r1:VPoint r g b:VPoint x2 y2 z2:VPoint x1 y1 z1 : stk)</span>
-<span class="lineno">  218 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">return (VLight (fn (x1,y1,z1) (x2,y2,z2) (color r g b) r1 r2) : stk)</span></span>
-<span class="lineno">  219 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Real_Real_Point fn) _ (VReal r3:VReal r2:VReal r1:stk)</span>
-<span class="lineno">  220 </span><span class="spaces">  </span><span class="istickedoff">= return ((fn r1 r2 r3) : stk)</span>
-<span class="lineno">  221 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Obj_Real_Obj fn) _ (VReal r:VObject o:stk)</span>
-<span class="lineno">  222 </span><span class="spaces">  </span><span class="istickedoff">= return (VObject (fn o r) : <span class="nottickedoff">stk</span>)</span>
-<span class="lineno">  223 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Obj_Real_Real_Real_Obj fn) _ (VReal r3:VReal r2:VReal r1:VObject o:stk)</span>
-<span class="lineno">  224 </span><span class="spaces">  </span><span class="istickedoff">= return (VObject (fn o r1 r2 r3) : stk)</span>
-<span class="lineno">  225 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  226 </span><span class="spaces"></span><span class="istickedoff">-- This one is our testing harness</span>
-<span class="lineno">  227 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Value_String_Value fn) _ (VString s:o:stk)</span>
-<span class="lineno">  228 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">res `seq` return (res : stk)</span></span>
-<span class="lineno">  229 </span><span class="spaces">  </span><span class="istickedoff">where</span>
-<span class="lineno">  230 </span><span class="spaces">     </span><span class="istickedoff"><span class="nottickedoff">res = fn o s</span></span>
-<span class="lineno">  231 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  232 </span><span class="spaces"></span><span class="istickedoff">doPrimOp primOp op args </span>
-<span class="lineno">  233 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">err (&quot;\n\ntype error when attempting to execute builtin primitive \&quot;&quot; ++</span></span>
-<span class="lineno">  234 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">show op ++ &quot;\&quot;\n\n| &quot; ++</span></span>
-<span class="lineno">  235 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">show op ++ &quot; takes &quot; ++ show (length types) ++ &quot; argument&quot; ++ s</span></span>
-<span class="lineno">  236 </span><span class="spaces">                   </span><span class="istickedoff"><span class="nottickedoff">++ &quot; with&quot; ++ the ++ &quot; type&quot; ++ s ++ &quot;\n|\n|&quot; ++</span></span>
-<span class="lineno">  237 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">&quot;      &quot; ++ unwords [ show ty | ty &lt;- types ]  ++ &quot;\n|\n|&quot; ++ </span></span>
-<span class="lineno">  238 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">&quot; currently, the relevent argument&quot; ++ s ++ &quot; on the stack &quot; ++ </span></span>
-<span class="lineno">  239 </span><span class="spaces">                  </span><span class="istickedoff"><span class="nottickedoff">are ++ &quot;\n|\n| &quot; ++ </span></span>
-<span class="lineno">  240 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">unwords [ &quot;(&quot; ++ show arg ++ &quot;)&quot; </span></span>
-<span class="lineno">  241 </span><span class="spaces">                  </span><span class="istickedoff"><span class="nottickedoff">| arg &lt;-  reverse (take (length types) args) ]  ++ &quot;\n|\n| &quot;</span></span>
-<span class="lineno">  242 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">++ &quot;    (top of stack is on the right hand side)\n\n&quot;)</span></span>
-<span class="lineno">  243 </span><span class="spaces">  </span><span class="istickedoff">where</span>
-<span class="lineno">  244 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">len   = length types</span></span>
-<span class="lineno">  245 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">s =  (if len /= 1 then &quot;s&quot; else &quot;&quot;)</span></span>
-<span class="lineno">  246 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">are =  (if len /= 1 then &quot;are&quot; else &quot;is&quot;)</span></span>
-<span class="lineno">  247 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">the =  (if len /= 1 then &quot;&quot; else &quot; the&quot;)</span></span>
-<span class="lineno">  248 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">types = getPrimOpType primOp</span></span></span>
-<span class="lineno">  249 </span>
-<span class="lineno">  250 </span>
-<span class="lineno">  251 </span>-- Render is somewhat funny, becauase it can only get called at top level.
-<span class="lineno">  252 </span>-- All other operations are purely functional.
-<span class="lineno">  253 </span>
-<span class="lineno">  254 </span>doAllOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; IO Stack
-<span class="lineno">  255 </span><span class="decl"><span class="istickedoff">doAllOp (Render render) Op_render</span>
-<span class="lineno">  256 </span><span class="spaces">                           </span><span class="istickedoff">(VString str:VInt ht:VInt wid:VReal fov</span>
-<span class="lineno">  257 </span><span class="spaces">                           </span><span class="istickedoff">:VInt dep:VObject obj:VArray arr</span>
-<span class="lineno">  258 </span><span class="spaces">                           </span><span class="istickedoff">:VPoint r g b : stk)</span>
-<span class="lineno">  259 </span><span class="spaces">  </span><span class="istickedoff">= do { render (color r g b) lights obj dep (fov * (pi / 180.0)) wid ht <span class="nottickedoff">str</span></span>
-<span class="lineno">  260 </span><span class="spaces">       </span><span class="istickedoff">; return <span class="nottickedoff">stk</span></span>
-<span class="lineno">  261 </span><span class="spaces">       </span><span class="istickedoff">}</span>
-<span class="lineno">  262 </span><span class="spaces">  </span><span class="istickedoff">where</span>
-<span class="lineno">  263 </span><span class="spaces">      </span><span class="istickedoff">lights = [ light | (VLight light) &lt;- elems arr ]</span>
-<span class="lineno">  264 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  265 </span><span class="spaces"></span><span class="istickedoff">doAllOp primOp op stk = doPrimOp primOp <span class="nottickedoff">op</span> stk</span></span> -- call the purely functional operators
-<span class="lineno">  266 </span>
-<span class="lineno">  267 </span>------------------------------------------------------------------------------
-<span class="lineno">  268 </span>{-
-<span class="lineno">  269 </span> - Abstract evaluation.
-<span class="lineno">  270 </span> -
-<span class="lineno">  271 </span> - The idea is you check for constant code that 
-<span class="lineno">  272 </span> - (1) does not look at its arguments
-<span class="lineno">  273 </span> - (2) gives a fixed result
-<span class="lineno">  274 </span> -
-<span class="lineno">  275 </span> - We run for 100 steps.
-<span class="lineno">  276 </span> -
-<span class="lineno">  277 </span> -}
-<span class="lineno">  278 </span>
-<span class="lineno">  279 </span>absapply :: Env -&gt; Code -&gt; Stack -&gt; Maybe Stack
-<span class="lineno">  280 </span><span class="decl"><span class="istickedoff">absapply env code stk = </span>
-<span class="lineno">  281 </span><span class="spaces">     </span><span class="istickedoff">case runAbs (eval (State env stk code)) 100 of</span>
-<span class="lineno">  282 </span><span class="spaces">       </span><span class="istickedoff">AbsState stk _ -&gt; <span class="nottickedoff">Just stk</span></span>
-<span class="lineno">  283 </span><span class="spaces">       </span><span class="istickedoff">AbsFail m      -&gt; Nothing</span></span>
-<span class="lineno">  284 </span>
-<span class="lineno">  285 </span>newtype Abs a   = Abs { runAbs :: Int -&gt; AbsState a }
-<span class="lineno">  286 </span>data AbsState a = AbsState a !Int
-<span class="lineno">  287 </span>                | AbsFail String
-<span class="lineno">  288 </span>
-<span class="lineno">  289 </span>instance Monad Abs where
-<span class="lineno">  290 </span>    <span class="decl"><span class="istickedoff">(Abs fn) &gt;&gt;= k = Abs (\ s -&gt; case fn s of</span>
-<span class="lineno">  291 </span><span class="spaces">                                   </span><span class="istickedoff">AbsState r s' -&gt; runAbs (k r) s'</span>
-<span class="lineno">  292 </span><span class="spaces">                                   </span><span class="istickedoff">AbsFail m     -&gt; AbsFail <span class="nottickedoff">m</span>)</span></span>
-<span class="lineno">  293 </span>    <span class="decl"><span class="istickedoff">return x     = Abs (\ n -&gt; AbsState x n)</span></span>
-<span class="lineno">  294 </span>    <span class="decl"><span class="istickedoff">fail s       = Abs (\ n -&gt; AbsFail <span class="nottickedoff">s</span>)</span></span>
-<span class="lineno">  295 </span>
-<span class="lineno">  296 </span>instance MonadEval Abs where
-<span class="lineno">  297 </span>  <span class="decl"><span class="istickedoff">doOp = doAbsOp</span></span>
-<span class="lineno">  298 </span>  <span class="decl"><span class="istickedoff">err  = fail</span></span>
-<span class="lineno">  299 </span>  <span class="decl"><span class="istickedoff">tick = Abs (\ n -&gt; if <span class="tickonlyfalse">n &lt;= 0</span></span>
-<span class="lineno">  300 </span><span class="spaces">                     </span><span class="istickedoff">then <span class="nottickedoff">AbsFail &quot;run out of time&quot;</span></span>
-<span class="lineno">  301 </span><span class="spaces">                     </span><span class="istickedoff">else AbsState <span class="nottickedoff">()</span> (n-1))</span></span>
-<span class="lineno">  302 </span>
-<span class="lineno">  303 </span>doAbsOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; Abs Stack
-<span class="lineno">  304 </span><span class="decl"><span class="istickedoff">doAbsOp _ Op_point (VReal r3:VReal r2:VReal r1:stk) </span>
-<span class="lineno">  305 </span><span class="spaces">               </span><span class="istickedoff">= <span class="nottickedoff">return ((VPoint r1 r2 r3) : stk)</span></span>
-<span class="lineno">  306 </span><span class="spaces"> </span><span class="istickedoff">-- here, you could have an (AbsPoint :: AbsObj) which you put on the</span>
-<span class="lineno">  307 </span><span class="spaces"> </span><span class="istickedoff">-- stack, with any object in the three fields.</span>
-<span class="lineno">  308 </span><span class="spaces"></span><span class="istickedoff">doAbsOp _ op _ = err <span class="nottickedoff">(&quot;operator not understood (&quot; ++ show op ++ &quot;)&quot;)</span></span></span>
-<span class="lineno">  309 </span>
-<span class="lineno">  310 </span>------------------------------------------------------------------------------
-<span class="lineno">  311 </span>-- Driver
-<span class="lineno">  312 </span>
-<span class="lineno">  313 </span>mainEval :: Code -&gt; IO ()
-<span class="lineno">  314 </span><span class="decl"><span class="istickedoff">mainEval prog = do { stk &lt;- eval (State <span class="nottickedoff">emptyEnv</span> [] prog) </span>
-<span class="lineno">  315 </span><span class="spaces">                   </span><span class="istickedoff">; return <span class="nottickedoff">()</span></span>
-<span class="lineno">  316 </span><span class="spaces">                   </span><span class="istickedoff">}</span></span>
-<span class="lineno">  317 </span>{- 
-<span class="lineno">  318 </span>  * Oops, one of the example actually has something
-<span class="lineno">  319 </span>  * on the stack at the end. 
-<span class="lineno">  320 </span>  * Oh well...
-<span class="lineno">  321 </span>                  ; if null stk
-<span class="lineno">  322 </span>                     then return ()
-<span class="lineno">  323 </span>                    else do { putStrLn done
-<span class="lineno">  324 </span>                             ; print stk
-<span class="lineno">  325 </span>                             }
-<span class="lineno">  326 </span>-}
-<span class="lineno">  327 </span>
-<span class="lineno">  328 </span><span class="decl"><span class="nottickedoff">done = &quot;Items still on stack at (successfull) termination of program&quot;</span></span>
-<span class="lineno">  329 </span>
-<span class="lineno">  330 </span>------------------------------------------------------------------------------
-<span class="lineno">  331 </span>-- testing
-<span class="lineno">  332 </span>
-<span class="lineno">  333 </span>test :: String -&gt; Pure Stack
-<span class="lineno">  334 </span><span class="decl"><span class="nottickedoff">test is = eval (State emptyEnv [] (rayParse is))</span></span>
-<span class="lineno">  335 </span>
-<span class="lineno">  336 </span>testF :: String -&gt; IO Stack
-<span class="lineno">  337 </span><span class="decl"><span class="nottickedoff">testF is = do prog &lt;- rayParseF is</span>
-<span class="lineno">  338 </span><span class="spaces">              </span><span class="nottickedoff">eval (State emptyEnv [] prog)</span></span>
-<span class="lineno">  339 </span>
-<span class="lineno">  340 </span>testA :: String -&gt; Either String (Stack,Int)
-<span class="lineno">  341 </span><span class="decl"><span class="nottickedoff">testA is = case runAbs (eval (State emptyEnv </span>
-<span class="lineno">  342 </span><span class="spaces">                                    </span><span class="nottickedoff">[VAbsObj AbsFACE,VAbsObj AbsU,VAbsObj AbsV]</span>
-<span class="lineno">  343 </span><span class="spaces">                                    </span><span class="nottickedoff">(rayParse is))) 100 of</span>
-<span class="lineno">  344 </span><span class="spaces">             </span><span class="nottickedoff">AbsState a n -&gt; Right (a,n)</span>
-<span class="lineno">  345 </span><span class="spaces">             </span><span class="nottickedoff">AbsFail m -&gt; Left m</span></span>
-<span class="lineno">  346 </span>
-<span class="lineno">  347 </span><span class="decl"><span class="nottickedoff">abstest1 = &quot;1.0 0.0 0.0 point /red { /v /u /face red 1.0 0.0 1.0 } apply&quot;</span></span> 
-<span class="lineno">  348 </span>
-<span class="lineno">  349 </span>-- should be [3:: Int]
-<span class="lineno">  350 </span><span class="decl"><span class="nottickedoff">et1 = test &quot;1 /x { x } /f 2 /x f apply x addi&quot;</span></span>
-<span class="lineno">  351 </span>
-<span class="lineno">  352 </span>
-<span class="lineno">  353 </span>
-<span class="lineno">  354 </span>
-<span class="lineno">  355 </span>
-
-</pre>
-</html>
-Writing: Data.hs.html
-<html><style type="text/css">
-span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
-span.nottickedoff { background: yellow}
-span.istickedoff { background: white }
-span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
-span.tickonlytrue  { margin: -1px; border: 1px solid #60de51; background: #60de51 }
-span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
-span.decl { font-weight: bold }
-span.spaces    { background: white }
-</style>
-<pre>
-<span class="lineno">    1 </span>-- Copyright (c) 2000 Galois Connections, Inc.
-<span class="lineno">    2 </span>-- All rights reserved.  This software is distributed as
-<span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
-<span class="lineno">    4 </span>-- which is included in the distribution.
-<span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Data where
-<span class="lineno">    7 </span>
-<span class="lineno">    8 </span>import Array
-<span class="lineno">    9 </span>
-<span class="lineno">   10 </span>import CSG      
-<span class="lineno">   11 </span>import Geometry
-<span class="lineno">   12 </span>import Illumination
-<span class="lineno">   13 </span>import Primitives
-<span class="lineno">   14 </span>import Surface
-<span class="lineno">   15 </span>
-<span class="lineno">   16 </span>import Debug.Trace
-<span class="lineno">   17 </span>
-<span class="lineno">   18 </span>-- Now the parsed (expresssion) language
-<span class="lineno">   19 </span>
-<span class="lineno">   20 </span>type Name = String
-<span class="lineno">   21 </span>
-<span class="lineno">   22 </span>type Code = [GMLToken]
-<span class="lineno">   23 </span>
-<span class="lineno">   24 </span>data GMLToken
-<span class="lineno">   25 </span>    -- All these can occur in parsed code
-<span class="lineno">   26 </span>        = TOp     GMLOp
-<span class="lineno">   27 </span>        | TId     Name
-<span class="lineno">   28 </span>        | TBind   Name
-<span class="lineno">   29 </span>        | TBool   Bool
-<span class="lineno">   30 </span>        | TInt    Int
-<span class="lineno">   31 </span>        | TReal   Double
-<span class="lineno">   32 </span>        | TString String
-<span class="lineno">   33 </span>        | TBody   Code
-<span class="lineno">   34 </span>        | TArray  Code
-<span class="lineno">   35 </span>        | TApply
-<span class="lineno">   36 </span>        | TIf
-<span class="lineno">   37 </span>         -- These can occur in optimized/transformed code
-<span class="lineno">   38 </span>         -- NONE (yet!)
-<span class="lineno">   39 </span>
-<span class="lineno">   40 </span>
-<span class="lineno">   41 </span>instance <span class="nottickedoff">Show GMLToken</span> where
+<span class="lineno">   41 </span>instance Show GMLToken where
 <span class="lineno">   42 </span>   <span class="decl"><span class="nottickedoff">showsPrec p (TOp op)     = shows op</span>
 <span class="lineno">   43 </span><span class="spaces">   </span><span class="nottickedoff">showsPrec p (TId id)     = showString id</span>
 <span class="lineno">   44 </span><span class="spaces">   </span><span class="nottickedoff">showsPrec p (TBind id)   = showString ('/' : id)</span>
@@ -955,45 +737,6 @@ span.spaces    { background: white }
 
 </pre>
 </html>
-Writing: Primitives.hs.html
-<html><style type="text/css">
-span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
-span.nottickedoff { background: yellow}
-span.istickedoff { background: white }
-span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
-span.tickonlytrue  { margin: -1px; border: 1px solid #60de51; background: #60de51 }
-span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
-span.decl { font-weight: bold }
-span.spaces    { background: white }
-</style>
-<pre>
-<span class="lineno">    1 </span>-- Copyright (c) 2000 Galois Connections, Inc.
-<span class="lineno">    2 </span>-- All rights reserved.  This software is distributed as
-<span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
-<span class="lineno">    4 </span>-- which is included in the distribution.
-<span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Primitives where
-<span class="lineno">    7 </span>
-<span class="lineno">    8 </span>rad2deg :: Double -&gt; Double
-<span class="lineno">    9 </span><span class="decl"><span class="nottickedoff">rad2deg r = r * 180 / pi</span></span>
-<span class="lineno">   10 </span>
-<span class="lineno">   11 </span>deg2rad :: Double -&gt; Double
-<span class="lineno">   12 </span><span class="decl"><span class="istickedoff">deg2rad d = d * pi / 180</span></span>
-<span class="lineno">   13 </span>
-<span class="lineno">   14 </span>addi :: Int -&gt; Int -&gt; Int
-<span class="lineno">   15 </span><span class="decl"><span class="nottickedoff">addi = (+)</span></span>
-<span class="lineno">   16 </span>
-<span class="lineno">   17 </span>addf :: Double -&gt; Double -&gt; Double
-<span class="lineno">   18 </span><span class="decl"><span class="nottickedoff">addf = (+)</span></span>
-<span class="lineno">   19 </span>
-<span class="lineno">   20 </span>acosD :: Double -&gt; Double
-<span class="lineno">   21 </span><span class="decl"><span class="nottickedoff">acosD x = acos x * 180 / pi</span></span>
-<span class="lineno">   22 </span>
-<span class="lineno">   23 </span>asinD :: Double -&gt; Double
-<span class="lineno">   24 </span><span class="decl"><span class="nottickedoff">asinD x = asin x * 180 / pi</span></span>
-
-</pre>
-</html>
 Writing: Illumination.hs.html
 <html><style type="text/css">
 span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
@@ -1032,7 +775,7 @@ span.spaces    { background: white }
 <span class="lineno">   24 </span>type Object = CSG (SurfaceFn Color Double)
 <span class="lineno">   25 </span>
 <span class="lineno">   26 </span>data Cxt = Cxt {ambient::Color, lights::[Light], object::Object, depth::Int}
-<span class="lineno">   27 </span>        deriving <span class="nottickedoff"><span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span></span>
+<span class="lineno">   27 </span>        deriving <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>
 <span class="lineno">   28 </span>
 <span class="lineno">   29 </span>render :: (Matrix,Matrix) -&gt; Color -&gt; [Light] -&gt; Object -&gt; Int -&gt;
 <span class="lineno">   30 </span>          Radian -&gt; Int -&gt; Int -&gt; String -&gt; IO ()
@@ -1240,33 +983,7 @@ span.spaces    { background: white }
 
 </pre>
 </html>
-Writing: Misc.hs.html
-<html><style type="text/css">
-span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
-span.nottickedoff { background: yellow}
-span.istickedoff { background: white }
-span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
-span.tickonlytrue  { margin: -1px; border: 1px solid #60de51; background: #60de51 }
-span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
-span.decl { font-weight: bold }
-span.spaces    { background: white }
-</style>
-<pre>
-<span class="lineno">    1 </span>-- Copyright (c) 2000 Galois Connections, Inc.
-<span class="lineno">    2 </span>-- All rights reserved.  This software is distributed as
-<span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
-<span class="lineno">    4 </span>-- which is included in the distribution.
-<span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Misc where
-<span class="lineno">    7 </span>
-<span class="lineno">    8 </span>import Debug.Trace
-<span class="lineno">    9 </span>
-<span class="lineno">   10 </span><span class="decl"><span class="nottickedoff">debug s v = trace (s ++&quot; : &quot;++ show v ++ &quot;\n&quot;) v</span></span>
-<span class="lineno">   11 </span>-- debug s v = v
-
-</pre>
-</html>
-Writing: Surface.hs.html
+Writing: Geometry.hs.html
 <html><style type="text/css">
 span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
 span.nottickedoff { background: yellow}
@@ -1283,116 +1000,315 @@ span.spaces    { background: white }
 <span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
 <span class="lineno">    4 </span>-- which is included in the distribution.
 <span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Surface
-<span class="lineno">    7 </span>    ( SurfaceFn (..)
-<span class="lineno">    8 </span>    , Properties
-<span class="lineno">    9 </span>    , sfun, sconst
-<span class="lineno">   10 </span>    , prop
-<span class="lineno">   11 </span>    , matte, shiny
-<span class="lineno">   12 </span>    , chgColor
-<span class="lineno">   13 </span>    , surface
-<span class="lineno">   14 </span>    ) where
-<span class="lineno">   15 </span>
-<span class="lineno">   16 </span>import Geometry
-<span class="lineno">   17 </span>import CSG
-<span class="lineno">   18 </span>import Misc
-<span class="lineno">   19 </span>
-<span class="lineno">   20 </span>-- the surface gets passed face then u then v.
-<span class="lineno">   21 </span>data SurfaceFn c v = SFun (Int -&gt; Double -&gt; Double -&gt; Properties c v)
-<span class="lineno">   22 </span>                   | SConst (Properties c v)
-<span class="lineno">   23 </span>
-<span class="lineno">   24 </span>sfun :: (Int -&gt; Double -&gt; Double -&gt; Properties c v) -&gt; SurfaceFn c v
-<span class="lineno">   25 </span><span class="decl"><span class="nottickedoff">sfun = SFun</span></span>
-<span class="lineno">   26 </span>sconst :: Properties c v -&gt; SurfaceFn c v
-<span class="lineno">   27 </span><span class="decl"><span class="nottickedoff">sconst = SConst</span></span>
-<span class="lineno">   28 </span>
-<span class="lineno">   29 </span>type Properties c v = (c, v, v, v)
-<span class="lineno">   30 </span>
-<span class="lineno">   31 </span><span class="decl"><span class="istickedoff">prop c d s p = (c, d, s, p)</span></span>
-<span class="lineno">   32 </span>
-<span class="lineno">   33 </span><span class="decl"><span class="nottickedoff">matte = (white, 1.0, 0.0, 1.0)</span></span>
-<span class="lineno">   34 </span><span class="decl"><span class="nottickedoff">shiny = (white, 0.0, 1.0, 1.0)</span></span>
-<span class="lineno">   35 </span>
-<span class="lineno">   36 </span>chgColor :: c -&gt; Properties d v -&gt; Properties c v
-<span class="lineno">   37 </span><span class="decl"><span class="nottickedoff">chgColor c (_, d, s, p) = (c, d, s, p)</span></span>
-<span class="lineno">   38 </span>
-<span class="lineno">   39 </span>instance (Show c, Show v) =&gt; Show (SurfaceFn c v) where
-<span class="lineno">   40 </span>  <span class="decl"><span class="nottickedoff">show (SFun _)   = &quot;Surface function&quot;</span>
-<span class="lineno">   41 </span><span class="spaces">  </span><span class="nottickedoff">-- show (SConst p) = &quot;Surface constant: &quot; ++ show p</span>
-<span class="lineno">   42 </span><span class="spaces">  </span><span class="nottickedoff">show (SConst p) = &quot;Surface constant&quot;</span></span>
-<span class="lineno">   43 </span>
-<span class="lineno">   44 </span>evalSurface :: SurfaceFn Color Double -&gt; Int -&gt; Double -&gt; Double -&gt; Properties Color Double
-<span class="lineno">   45 </span><span class="decl"><span class="istickedoff">evalSurface (SConst p) = <span class="nottickedoff">\_ _ _ -&gt; p</span></span>
-<span class="lineno">   46 </span><span class="spaces"></span><span class="istickedoff">evalSurface (SFun f)   = f</span></span>
-<span class="lineno">   47 </span>
-<span class="lineno">   48 </span>-- calculate surface properties, given the type of
-<span class="lineno">   49 </span>-- surface, and intersection point in object coordinates
-<span class="lineno">   50 </span>
-<span class="lineno">   51 </span>-- surface :: Surface SurfaceFn -&gt; (Int, Point) -&gt; (Vector, Properties)
-<span class="lineno">   52 </span>
-<span class="lineno">   53 </span><span class="decl"><span class="istickedoff">surface (Planar _ v0 v1) (n, p0, fn)</span>
-<span class="lineno">   54 </span><span class="spaces">  </span><span class="istickedoff">= (norm, evalSurface fn <span class="nottickedoff">n'</span> u v)</span>
-<span class="lineno">   55 </span><span class="spaces">  </span><span class="istickedoff">where norm = normalize $ cross v0 v1</span>
-<span class="lineno">   56 </span><span class="spaces">        </span><span class="istickedoff">(n', u, v) = planarUV n p0</span>
-<span class="lineno">   57 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">   58 </span><span class="spaces"></span><span class="istickedoff">surface (Spherical _ v0 v1) (_, p0, fn)</span>
-<span class="lineno">   59 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">(norm, evalSurface fn 0 u v)</span></span>
-<span class="lineno">   60 </span><span class="spaces">  </span><span class="istickedoff">where <span class="nottickedoff">x = xCoord p0</span></span>
-<span class="lineno">   61 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">y = yCoord p0</span></span>
-<span class="lineno">   62 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">z = zCoord p0</span></span>
-<span class="lineno">   63 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">k = sqrt (1 - sq y)</span></span>
-<span class="lineno">   64 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">theta = adjustRadian (atan2 (x / k) (z / k))</span></span>
-<span class="lineno">   65 </span><span class="spaces">        </span><span class="istickedoff">-- correct so that the image grows left-to-right</span>
-<span class="lineno">   66 </span><span class="spaces">        </span><span class="istickedoff">-- instead of right-to-left</span>
-<span class="lineno">   67 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">u = 1.0 - clampf (theta / (2 * pi))</span></span>
-<span class="lineno">   68 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">v =       clampf ((y + 1) / 2)</span></span>
-<span class="lineno">   69 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">norm = normalize $ cross v0 v1</span></span>
-<span class="lineno">   70 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">   71 </span><span class="spaces"></span><span class="istickedoff">-- ZZ ignore the (incorrect) surface model, and estimate the normal</span>
-<span class="lineno">   72 </span><span class="spaces"></span><span class="istickedoff">-- from the intersection in object space</span>
-<span class="lineno">   73 </span><span class="spaces"></span><span class="istickedoff">surface (Cylindrical _ v0 v1) (_, p0, fn)</span>
-<span class="lineno">   74 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">(norm, evalSurface fn 0 u v)</span></span>
-<span class="lineno">   75 </span><span class="spaces">  </span><span class="istickedoff">where <span class="nottickedoff">x = xCoord p0</span></span>
-<span class="lineno">   76 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">y = yCoord p0</span></span>
-<span class="lineno">   77 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">z = zCoord p0</span></span>
-<span class="lineno">   78 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">u = clampf $ adjustRadian (atan2 x z) / (2 * pi)</span></span>
-<span class="lineno">   79 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">v = y</span></span>
-<span class="lineno">   80 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">norm = normalize $ cross v0 v1</span></span>
-<span class="lineno">   81 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">   82 </span><span class="spaces"></span><span class="istickedoff">-- ZZ ignore the (incorrect) surface model, and estimate the normal</span>
-<span class="lineno">   83 </span><span class="spaces"></span><span class="istickedoff">-- from the intersection in object space</span>
-<span class="lineno">   84 </span><span class="spaces"></span><span class="istickedoff">surface (Conic _ v0 v1) (_, p0, fn)</span>
-<span class="lineno">   85 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">(norm, evalSurface fn 0 u v)</span></span>
-<span class="lineno">   86 </span><span class="spaces">  </span><span class="istickedoff">where <span class="nottickedoff">x = xCoord p0</span></span>
-<span class="lineno">   87 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">y = yCoord p0</span></span>
-<span class="lineno">   88 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">z = zCoord p0</span></span>
-<span class="lineno">   89 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">u = clampf $ adjustRadian (atan2 (x / y) (z / y)) / (2 * pi)</span></span>
-<span class="lineno">   90 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">v = y</span></span>
-<span class="lineno">   91 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">norm = normalize $ cross v0 v1</span></span></span>
-<span class="lineno">   92 </span>
-<span class="lineno">   93 </span><span class="decl"><span class="istickedoff">planarUV face p0</span>
-<span class="lineno">   94 </span><span class="spaces">  </span><span class="istickedoff">= case face of</span>
-<span class="lineno">   95 </span><span class="spaces">    </span><span class="istickedoff">PlaneFace      -&gt; (<span class="nottickedoff">0</span>, x, z)</span>
-<span class="lineno">   96 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">   97 </span><span class="spaces">    </span><span class="istickedoff">CubeFront      -&gt; (<span class="nottickedoff">0</span>, x, y)</span>
-<span class="lineno">   98 </span><span class="spaces">    </span><span class="istickedoff">CubeBack       -&gt; <span class="nottickedoff">(1, x, y)</span></span>
-<span class="lineno">   99 </span><span class="spaces">    </span><span class="istickedoff">CubeLeft       -&gt; (<span class="nottickedoff">2</span>, z, y)</span>
-<span class="lineno">  100 </span><span class="spaces">    </span><span class="istickedoff">CubeRight      -&gt; <span class="nottickedoff">(3, z, y)</span></span>
-<span class="lineno">  101 </span><span class="spaces">    </span><span class="istickedoff">CubeTop        -&gt; (<span class="nottickedoff">4</span>, x, z)</span>
-<span class="lineno">  102 </span><span class="spaces">    </span><span class="istickedoff">CubeBottom     -&gt; (<span class="nottickedoff">5</span>, x, z)</span>
-<span class="lineno">  103 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  104 </span><span class="spaces">    </span><span class="istickedoff">CylinderTop    -&gt; <span class="nottickedoff">(1, (x + 1) / 2, (z + 1) / 2)</span></span>
-<span class="lineno">  105 </span><span class="spaces">    </span><span class="istickedoff">CylinderBottom -&gt; <span class="nottickedoff">(2, (x + 1) / 2, (z + 1) / 2)</span></span>
-<span class="lineno">  106 </span><span class="spaces"></span><span class="istickedoff"></span>
-<span class="lineno">  107 </span><span class="spaces">    </span><span class="istickedoff">ConeBase       -&gt; <span class="nottickedoff">(1, (x + 1) / 2, (z + 1) / 2)</span></span>
-<span class="lineno">  108 </span><span class="spaces">  </span><span class="istickedoff">where x = xCoord p0</span>
-<span class="lineno">  109 </span><span class="spaces">        </span><span class="istickedoff">y = yCoord p0</span>
-<span class="lineno">  110 </span><span class="spaces">        </span><span class="istickedoff">z = zCoord p0</span></span>
-<span class="lineno">  111 </span>
-<span class="lineno">  112 </span>-- misc
+<span class="lineno">    6 </span>module Geometry
+<span class="lineno">    7 </span>    ( Coords
+<span class="lineno">    8 </span>    , Ray
+<span class="lineno">    9 </span>    , Point  -- abstract
+<span class="lineno">   10 </span>    , Vector -- abstract
+<span class="lineno">   11 </span>    , Matrix -- abstract
+<span class="lineno">   12 </span>    , Color  -- abstract
+<span class="lineno">   13 </span>    , Box(..)
+<span class="lineno">   14 </span>    , Radian
+<span class="lineno">   15 </span>    , matrix
+<span class="lineno">   16 </span>    , coord
+<span class="lineno">   17 </span>    , color
+<span class="lineno">   18 </span>    , uncolor
+<span class="lineno">   19 </span>    , xCoord , yCoord , zCoord
+<span class="lineno">   20 </span>    , xComponent , yComponent , zComponent
+<span class="lineno">   21 </span>    , point
+<span class="lineno">   22 </span>    , vector
+<span class="lineno">   23 </span>    , nearV
+<span class="lineno">   24 </span>    , point_to_vector
+<span class="lineno">   25 </span>    , vector_to_point
+<span class="lineno">   26 </span>    , dot
+<span class="lineno">   27 </span>    , cross
+<span class="lineno">   28 </span>    , tangents
+<span class="lineno">   29 </span>    , addVV
+<span class="lineno">   30 </span>    , addPV
+<span class="lineno">   31 </span>    , subVV
+<span class="lineno">   32 </span>    , negV
+<span class="lineno">   33 </span>    , subPP
+<span class="lineno">   34 </span>    , norm
+<span class="lineno">   35 </span>    , normalize
+<span class="lineno">   36 </span>    , dist2
+<span class="lineno">   37 </span>    , sq
+<span class="lineno">   38 </span>    , distFrom0Sq
+<span class="lineno">   39 </span>    , distFrom0
+<span class="lineno">   40 </span>    , multSV
+<span class="lineno">   41 </span>    , multMM
+<span class="lineno">   42 </span>    , transposeM
+<span class="lineno">   43 </span>    , multMV
+<span class="lineno">   44 </span>    , multMP
+<span class="lineno">   45 </span>    , multMQ
+<span class="lineno">   46 </span>    , multMR
+<span class="lineno">   47 </span>    , white
+<span class="lineno">   48 </span>    , black
+<span class="lineno">   49 </span>    , addCC
+<span class="lineno">   50 </span>    , subCC
+<span class="lineno">   51 </span>    , sumCC
+<span class="lineno">   52 </span>    , multCC
+<span class="lineno">   53 </span>    , multSC
+<span class="lineno">   54 </span>    , nearC
+<span class="lineno">   55 </span>    , offsetToPoint
+<span class="lineno">   56 </span>    , epsilon
+<span class="lineno">   57 </span>    , inf
+<span class="lineno">   58 </span>    , nonZero
+<span class="lineno">   59 </span>    , eqEps
+<span class="lineno">   60 </span>    , near
+<span class="lineno">   61 </span>    , clampf
+<span class="lineno">   62 </span>    ) where
+<span class="lineno">   63 </span>
+<span class="lineno">   64 </span>import List 
+<span class="lineno">   65 </span>
+<span class="lineno">   66 </span>type Coords = (Double,Double,Double)
+<span class="lineno">   67 </span>
+<span class="lineno">   68 </span>type Ray = (Point,Vector)    -- origin of ray, and unit vector giving direction
+<span class="lineno">   69 </span>
+<span class="lineno">   70 </span>data Point  = P !Double !Double !Double -- implicit extra arg of 1
+<span class="lineno">   71 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
+<span class="lineno">   72 </span>data Vector = V !Double !Double !Double -- implicit extra arg of 0
+<span class="lineno">   73 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>, <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Eq</span></span></span></span>)
+<span class="lineno">   74 </span>data Matrix = M !Quad   !Quad   !Quad   !Quad
+<span class="lineno">   75 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
+<span class="lineno">   76 </span>
+<span class="lineno">   77 </span>data Color  = C !Double !Double !Double
+<span class="lineno">   78 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>, <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Eq</span></span></span></span>)
+<span class="lineno">   79 </span>
+<span class="lineno">   80 </span>data Box = B !Double !Double !Double !Double !Double !Double
+<span class="lineno">   81 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
+<span class="lineno">   82 </span>
+<span class="lineno">   83 </span>data Quad   = Q !Double !Double !Double !Double
+<span class="lineno">   84 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
+<span class="lineno">   85 </span>
+<span class="lineno">   86 </span>type Radian = Double
+<span class="lineno">   87 </span>
+<span class="lineno">   88 </span>type Tup4 a = (a,a,a,a)
+<span class="lineno">   89 </span>
+<span class="lineno">   90 </span>--{-# INLINE matrix #-}
+<span class="lineno">   91 </span>matrix :: Tup4 (Tup4 Double) -&gt; Matrix
+<span class="lineno">   92 </span><span class="decl"><span class="istickedoff">matrix ((m11, m12, m13, m14),</span>
+<span class="lineno">   93 </span><span class="spaces">          </span><span class="istickedoff">(m21, m22, m23, m24),</span>
+<span class="lineno">   94 </span><span class="spaces">          </span><span class="istickedoff">(m31, m32, m33, m34),</span>
+<span class="lineno">   95 </span><span class="spaces">          </span><span class="istickedoff">(m41, m42, m43, m44))</span>
+<span class="lineno">   96 </span><span class="spaces">  </span><span class="istickedoff">= M (Q m11 m12 m13 m14)</span>
+<span class="lineno">   97 </span><span class="spaces">      </span><span class="istickedoff">(Q m21 m22 m23 m24)</span>
+<span class="lineno">   98 </span><span class="spaces">      </span><span class="istickedoff">(Q m31 m32 m33 m34)</span>
+<span class="lineno">   99 </span><span class="spaces">      </span><span class="istickedoff">(Q m41 m42 m43 m44)</span></span>
+<span class="lineno">  100 </span>
+<span class="lineno">  101 </span><span class="decl"><span class="nottickedoff">coord x y z = (x, y, z)</span></span>
+<span class="lineno">  102 </span>
+<span class="lineno">  103 </span><span class="decl"><span class="istickedoff">color r g b = C r g b</span></span>
+<span class="lineno">  104 </span>
+<span class="lineno">  105 </span><span class="decl"><span class="istickedoff">uncolor (C r g b) = (r,g,b)</span></span>
+<span class="lineno">  106 </span>
+<span class="lineno">  107 </span>{-# INLINE xCoord #-}
+<span class="lineno">  108 </span><span class="decl"><span class="istickedoff">xCoord (P x y z) = x</span></span>
+<span class="lineno">  109 </span>{-# INLINE yCoord #-}
+<span class="lineno">  110 </span><span class="decl"><span class="istickedoff">yCoord (P x y z) = y</span></span>
+<span class="lineno">  111 </span>{-# INLINE zCoord #-}
+<span class="lineno">  112 </span><span class="decl"><span class="istickedoff">zCoord (P x y z) = z</span></span>
 <span class="lineno">  113 </span>
-<span class="lineno">  114 </span>adjustRadian :: Radian -&gt; Radian
-<span class="lineno">  115 </span><span class="decl"><span class="nottickedoff">adjustRadian r = if r &gt; 0 then r else r + 2 * pi</span></span>
+<span class="lineno">  114 </span>{-# INLINE xComponent #-}
+<span class="lineno">  115 </span><span class="decl"><span class="istickedoff">xComponent (V x y z) = x</span></span>
+<span class="lineno">  116 </span>{-# INLINE yComponent #-}
+<span class="lineno">  117 </span><span class="decl"><span class="istickedoff">yComponent (V x y z) = y</span></span>
+<span class="lineno">  118 </span>{-# INLINE zComponent #-}
+<span class="lineno">  119 </span><span class="decl"><span class="istickedoff">zComponent (V x y z) = z</span></span>
+<span class="lineno">  120 </span>
+<span class="lineno">  121 </span>point :: Double -&gt; Double -&gt; Double -&gt; Point
+<span class="lineno">  122 </span><span class="decl"><span class="istickedoff">point x y z = P x y z</span></span>
+<span class="lineno">  123 </span>
+<span class="lineno">  124 </span>vector :: Double -&gt; Double -&gt; Double -&gt; Vector
+<span class="lineno">  125 </span><span class="decl"><span class="istickedoff">vector x y z = V x y z</span></span>
+<span class="lineno">  126 </span>
+<span class="lineno">  127 </span>nearV :: Vector -&gt; Vector -&gt; Bool
+<span class="lineno">  128 </span><span class="decl"><span class="nottickedoff">nearV (V a b c) (V d e f) = a `near` d &amp;&amp; b `near` e &amp;&amp; c `near` f</span></span>
+<span class="lineno">  129 </span>
+<span class="lineno">  130 </span>point_to_vector :: Point -&gt; Vector
+<span class="lineno">  131 </span><span class="decl"><span class="nottickedoff">point_to_vector (P x y z) = V x y z</span></span>
+<span class="lineno">  132 </span>
+<span class="lineno">  133 </span>vector_to_point :: Vector -&gt; Point
+<span class="lineno">  134 </span><span class="decl"><span class="nottickedoff">vector_to_point (V x y z)  = P x y z</span></span> 
+<span class="lineno">  135 </span>
+<span class="lineno">  136 </span>{-# INLINE vector_to_quad #-}
+<span class="lineno">  137 </span>vector_to_quad :: Vector -&gt; Quad
+<span class="lineno">  138 </span><span class="decl"><span class="istickedoff">vector_to_quad (V x y z) = Q x y z 0</span></span>
+<span class="lineno">  139 </span>
+<span class="lineno">  140 </span>{-# INLINE point_to_quad #-}
+<span class="lineno">  141 </span>point_to_quad :: Point -&gt; Quad
+<span class="lineno">  142 </span><span class="decl"><span class="istickedoff">point_to_quad (P x y z) = Q x y z 1</span></span>
+<span class="lineno">  143 </span>
+<span class="lineno">  144 </span>{-# INLINE quad_to_point #-}
+<span class="lineno">  145 </span>quad_to_point :: Quad -&gt; Point
+<span class="lineno">  146 </span><span class="decl"><span class="istickedoff">quad_to_point (Q x y z _) = P x y z</span></span>
+<span class="lineno">  147 </span>
+<span class="lineno">  148 </span>{-# INLINE quad_to_vector #-}
+<span class="lineno">  149 </span>quad_to_vector :: Quad -&gt; Vector
+<span class="lineno">  150 </span><span class="decl"><span class="istickedoff">quad_to_vector (Q x y z _) = V x y z</span></span>
+<span class="lineno">  151 </span>
+<span class="lineno">  152 </span>--{-# INLINE dot #-}
+<span class="lineno">  153 </span>dot :: Vector -&gt; Vector -&gt; Double
+<span class="lineno">  154 </span><span class="decl"><span class="istickedoff">dot (V x1 y1 z1) (V x2 y2 z2) = x1 * x2 + y1 * y2 + z1 * z2</span></span>
+<span class="lineno">  155 </span>
+<span class="lineno">  156 </span>cross :: Vector -&gt; Vector -&gt; Vector
+<span class="lineno">  157 </span><span class="decl"><span class="istickedoff">cross (V x1 y1 z1) (V x2 y2 z2)</span>
+<span class="lineno">  158 </span><span class="spaces">  </span><span class="istickedoff">= V (y1 * z2 - z1 * y2) (z1 * x2 - x1 * z2) (x1 * y2 - y1 * x2)</span></span>
+<span class="lineno">  159 </span>
+<span class="lineno">  160 </span>-- assumption: the input vector is a normal
+<span class="lineno">  161 </span>tangents :: Vector -&gt; (Vector, Vector)
+<span class="lineno">  162 </span><span class="decl"><span class="nottickedoff">tangents v@(V x y z)</span>
+<span class="lineno">  163 </span><span class="spaces">  </span><span class="nottickedoff">= (v1, v `cross` v1)</span>
+<span class="lineno">  164 </span><span class="spaces">  </span><span class="nottickedoff">where v1 | x == 0    = normalize (vector 0 z (-y))</span>
+<span class="lineno">  165 </span><span class="spaces">           </span><span class="nottickedoff">| otherwise = normalize (vector (-y) x 0)</span></span>
+<span class="lineno">  166 </span>
+<span class="lineno">  167 </span>{-# INLINE dot4 #-}
+<span class="lineno">  168 </span>dot4 :: Quad -&gt; Quad -&gt; Double
+<span class="lineno">  169 </span><span class="decl"><span class="istickedoff">dot4 (Q x1 y1 z1 w1) (Q x2 y2 z2 w2) = x1 * x2 + y1 * y2 + z1 * z2 + w1 * w2</span></span>
+<span class="lineno">  170 </span>
+<span class="lineno">  171 </span>addVV :: Vector -&gt; Vector -&gt; Vector
+<span class="lineno">  172 </span><span class="decl"><span class="nottickedoff">addVV (V x1 y1 z1) (V x2 y2 z2) </span>
+<span class="lineno">  173 </span><span class="spaces">    </span><span class="nottickedoff">= V (x1 + x2) (y1 + y2) (z1 + z2)</span></span>
+<span class="lineno">  174 </span>
+<span class="lineno">  175 </span>addPV :: Point -&gt; Vector -&gt; Point
+<span class="lineno">  176 </span><span class="decl"><span class="istickedoff">addPV (P x1 y1 z1) (V x2 y2 z2) </span>
+<span class="lineno">  177 </span><span class="spaces">    </span><span class="istickedoff">= P (x1 + x2) (y1 + y2) (z1 + z2)</span></span>
+<span class="lineno">  178 </span>
+<span class="lineno">  179 </span>subVV :: Vector -&gt; Vector -&gt; Vector
+<span class="lineno">  180 </span><span class="decl"><span class="istickedoff">subVV (V x1 y1 z1) (V x2 y2 z2) </span>
+<span class="lineno">  181 </span><span class="spaces">    </span><span class="istickedoff">= V (x1 - x2) (y1 - y2) (z1 - z2)</span></span>
+<span class="lineno">  182 </span>
+<span class="lineno">  183 </span>negV :: Vector -&gt; Vector
+<span class="lineno">  184 </span><span class="decl"><span class="nottickedoff">negV (V x1 y1 z1) </span>
+<span class="lineno">  185 </span><span class="spaces">    </span><span class="nottickedoff">= V (-x1) (-y1) (-z1)</span></span>
+<span class="lineno">  186 </span>
+<span class="lineno">  187 </span>subPP :: Point -&gt; Point -&gt; Vector
+<span class="lineno">  188 </span><span class="decl"><span class="nottickedoff">subPP (P x1 y1 z1) (P x2 y2 z2) </span>
+<span class="lineno">  189 </span><span class="spaces">    </span><span class="nottickedoff">= V (x1 - x2) (y1 - y2) (z1 - z2)</span></span>
+<span class="lineno">  190 </span>
+<span class="lineno">  191 </span>--{-# INLINE norm #-}
+<span class="lineno">  192 </span>norm :: Vector -&gt; Double
+<span class="lineno">  193 </span><span class="decl"><span class="nottickedoff">norm (V x y z) = sqrt (sq x + sq y + sq z)</span></span>
+<span class="lineno">  194 </span>
+<span class="lineno">  195 </span>--{-# INLINE normalize #-}
+<span class="lineno">  196 </span>-- normalize a vector to a unit vector
+<span class="lineno">  197 </span>normalize :: Vector -&gt; Vector
+<span class="lineno">  198 </span><span class="decl"><span class="istickedoff">normalize v@(V x y z)</span>
+<span class="lineno">  199 </span><span class="spaces">             </span><span class="istickedoff">| <span class="tickonlytrue">norm /= 0</span> = multSV (1/norm) v</span>
+<span class="lineno">  200 </span><span class="spaces">             </span><span class="istickedoff">| <span class="nottickedoff">otherwise</span> = <span class="nottickedoff">error &quot;normalize empty!&quot;</span></span>
+<span class="lineno">  201 </span><span class="spaces">    </span><span class="istickedoff">where norm = sqrt (sq x + sq y + sq z)</span></span>
+<span class="lineno">  202 </span>
+<span class="lineno">  203 </span>-- This does computes the distance *squared*
+<span class="lineno">  204 </span>dist2 :: Point -&gt; Point -&gt; Double
+<span class="lineno">  205 </span><span class="decl"><span class="nottickedoff">dist2 us vs = sq x + sq y + sq z</span>
+<span class="lineno">  206 </span><span class="spaces">    </span><span class="nottickedoff">where</span>
+<span class="lineno">  207 </span><span class="spaces">       </span><span class="nottickedoff">(V x y z) = subPP us vs</span></span>
+<span class="lineno">  208 </span>
+<span class="lineno">  209 </span>{-# INLINE sq #-}
+<span class="lineno">  210 </span>sq :: Double -&gt; Double
+<span class="lineno">  211 </span><span class="decl"><span class="istickedoff">sq d = d * d</span></span> 
+<span class="lineno">  212 </span>
+<span class="lineno">  213 </span>{-# INLINE distFrom0Sq #-}
+<span class="lineno">  214 </span>distFrom0Sq :: Point -&gt; Double  -- Distance of point from origin.
+<span class="lineno">  215 </span><span class="decl"><span class="nottickedoff">distFrom0Sq (P x y z) = sq x + sq y + sq z</span></span>
+<span class="lineno">  216 </span>
+<span class="lineno">  217 </span>{-# INLINE distFrom0 #-}
+<span class="lineno">  218 </span>distFrom0 :: Point -&gt; Double  -- Distance of point from origin.
+<span class="lineno">  219 </span><span class="decl"><span class="nottickedoff">distFrom0 p = sqrt (distFrom0Sq p)</span></span>
+<span class="lineno">  220 </span>
+<span class="lineno">  221 </span>--{-# INLINE multSV #-}
+<span class="lineno">  222 </span>multSV :: Double -&gt; Vector -&gt; Vector
+<span class="lineno">  223 </span><span class="decl"><span class="istickedoff">multSV k (V x y z) = V (k*x) (k*y) (k*z)</span></span>
+<span class="lineno">  224 </span>
+<span class="lineno">  225 </span>--{-# INLINE multMM #-}
+<span class="lineno">  226 </span>multMM :: Matrix -&gt; Matrix -&gt; Matrix
+<span class="lineno">  227 </span><span class="decl"><span class="istickedoff">multMM m1@(M q1 q2 q3 q4) m2</span>
+<span class="lineno">  228 </span><span class="spaces">     </span><span class="istickedoff">= M (multMQ m2' q1)</span>
+<span class="lineno">  229 </span><span class="spaces">         </span><span class="istickedoff">(multMQ m2' q2)</span>
+<span class="lineno">  230 </span><span class="spaces">         </span><span class="istickedoff">(multMQ m2' q3)</span>
+<span class="lineno">  231 </span><span class="spaces">         </span><span class="istickedoff">(multMQ m2' q4)</span>
+<span class="lineno">  232 </span><span class="spaces">  </span><span class="istickedoff">where</span>
+<span class="lineno">  233 </span><span class="spaces">     </span><span class="istickedoff">m2' = transposeM m2</span></span>
+<span class="lineno">  234 </span>
+<span class="lineno">  235 </span>{-# INLINE transposeM #-}     
+<span class="lineno">  236 </span>transposeM :: Matrix -&gt; Matrix
+<span class="lineno">  237 </span><span class="decl"><span class="istickedoff">transposeM (M (Q e11  e12  e13  e14)</span>
+<span class="lineno">  238 </span><span class="spaces">              </span><span class="istickedoff">(Q e21  e22  e23  e24)</span>
+<span class="lineno">  239 </span><span class="spaces">              </span><span class="istickedoff">(Q e31  e32  e33  e34)</span>
+<span class="lineno">  240 </span><span class="spaces">              </span><span class="istickedoff">(Q e41  e42  e43  e44)) = (M (Q e11  e21  e31  e41)</span>
+<span class="lineno">  241 </span><span class="spaces">                                           </span><span class="istickedoff">(Q e12  e22  e32  e42)</span>
+<span class="lineno">  242 </span><span class="spaces">                                           </span><span class="istickedoff">(Q e13  e23  e33  e43)</span>
+<span class="lineno">  243 </span><span class="spaces">                                           </span><span class="istickedoff">(Q e14  e24  e34  e44))</span></span>
+<span class="lineno">  244 </span>
+<span class="lineno">  245 </span>
+<span class="lineno">  246 </span>--multMM m1 m2 = [map (dot4 row) (transpose m2) | row &lt;- m1]
+<span class="lineno">  247 </span>
+<span class="lineno">  248 </span>--{-# INLINE multMV #-}
+<span class="lineno">  249 </span>multMV :: Matrix -&gt; Vector -&gt; Vector
+<span class="lineno">  250 </span><span class="decl"><span class="istickedoff">multMV m v = quad_to_vector (multMQ m (vector_to_quad v))</span></span>
+<span class="lineno">  251 </span>
+<span class="lineno">  252 </span>--{-# INLINE multMP #-}
+<span class="lineno">  253 </span>multMP :: Matrix -&gt; Point -&gt; Point
+<span class="lineno">  254 </span><span class="decl"><span class="istickedoff">multMP m p = quad_to_point (multMQ m (point_to_quad p))</span></span>
+<span class="lineno">  255 </span>
+<span class="lineno">  256 </span>-- mat vec = map (dot4 vec) mat
+<span class="lineno">  257 </span>
+<span class="lineno">  258 </span>{-# INLINE multMQ #-}
+<span class="lineno">  259 </span>multMQ :: Matrix -&gt; Quad -&gt; Quad
+<span class="lineno">  260 </span><span class="decl"><span class="istickedoff">multMQ (M q1 q2 q3 q4) q</span>
+<span class="lineno">  261 </span><span class="spaces">       </span><span class="istickedoff">= Q (dot4 q q1)</span>
+<span class="lineno">  262 </span><span class="spaces">           </span><span class="istickedoff">(dot4 q q2)</span>
+<span class="lineno">  263 </span><span class="spaces">           </span><span class="istickedoff">(dot4 q q3)</span>
+<span class="lineno">  264 </span><span class="spaces">           </span><span class="istickedoff">(dot4 q q4)</span></span>
+<span class="lineno">  265 </span>
+<span class="lineno">  266 </span>{-# INLINE multMR #-}
+<span class="lineno">  267 </span>multMR :: Matrix -&gt; Ray -&gt; Ray
+<span class="lineno">  268 </span><span class="decl"><span class="istickedoff">multMR m (r, v) = (multMP m r, multMV m v)</span></span>
+<span class="lineno">  269 </span>
+<span class="lineno">  270 </span>white :: Color
+<span class="lineno">  271 </span><span class="decl"><span class="nottickedoff">white = C 1 1 1</span></span>
+<span class="lineno">  272 </span>black :: Color
+<span class="lineno">  273 </span><span class="decl"><span class="istickedoff">black = C 0 0 0</span></span>
+<span class="lineno">  274 </span>
+<span class="lineno">  275 </span>addCC :: Color -&gt; Color -&gt; Color
+<span class="lineno">  276 </span><span class="decl"><span class="istickedoff">addCC (C a b c) (C d e f) = C (a+d) (b+e) (c+f)</span></span>
+<span class="lineno">  277 </span>
+<span class="lineno">  278 </span>subCC :: Color -&gt; Color -&gt; Color
+<span class="lineno">  279 </span><span class="decl"><span class="nottickedoff">subCC (C a b c) (C d e f) = C (a-d) (b-e) (c-f)</span></span>
+<span class="lineno">  280 </span>
+<span class="lineno">  281 </span>sumCC :: [Color] -&gt; Color
+<span class="lineno">  282 </span><span class="decl"><span class="istickedoff">sumCC = foldr addCC black</span></span>
+<span class="lineno">  283 </span>
+<span class="lineno">  284 </span>multCC :: Color -&gt; Color -&gt; Color
+<span class="lineno">  285 </span><span class="decl"><span class="istickedoff">multCC (C a b c) (C d e f) = C (a*d) (b*e) (c*f)</span></span>
+<span class="lineno">  286 </span>
+<span class="lineno">  287 </span>multSC :: Double -&gt; Color -&gt; Color
+<span class="lineno">  288 </span><span class="decl"><span class="istickedoff">multSC k       (C a b c) = C (a*k) (b*k) (c*k)</span></span>
+<span class="lineno">  289 </span>
+<span class="lineno">  290 </span>nearC :: Color -&gt; Color -&gt; Bool
+<span class="lineno">  291 </span><span class="decl"><span class="istickedoff">nearC (C a b c) (C d e f) = a `near` d &amp;&amp; b `near` e &amp;&amp; c `near` f</span></span>
+<span class="lineno">  292 </span>
+<span class="lineno">  293 </span>offsetToPoint :: Ray -&gt; Double -&gt; Point
+<span class="lineno">  294 </span><span class="decl"><span class="istickedoff">offsetToPoint (r,v) i = r `addPV` (i `multSV` v)</span></span>
+<span class="lineno">  295 </span>
+<span class="lineno">  296 </span>--
+<span class="lineno">  297 </span>
+<span class="lineno">  298 </span>epsilon, inf :: Double      -- aproximate zero and infinity
+<span class="lineno">  299 </span><span class="decl"><span class="istickedoff">epsilon = 1.0e-10</span></span>
+<span class="lineno">  300 </span><span class="decl"><span class="istickedoff">inf = 1.0e20</span></span>
+<span class="lineno">  301 </span>
+<span class="lineno">  302 </span>nonZero :: Double -&gt; Double         -- Use before a division. It makes definitions
+<span class="lineno">  303 </span><span class="decl"><span class="istickedoff">nonZero x | <span class="tickonlytrue">x &gt; epsilon</span>  = x        -- more complete and I bet the errors that get </span>
+<span class="lineno">  304 </span><span class="spaces">          </span><span class="istickedoff">| <span class="nottickedoff">x &lt; -epsilon</span> = <span class="nottickedoff">x</span>        -- introduced will be undetectable if epsilon</span>
+<span class="lineno">  305 </span><span class="spaces">          </span><span class="istickedoff">| <span class="nottickedoff">otherwise</span>    = <span class="nottickedoff">epsilon</span></span></span>  -- is small enough
+<span class="lineno">  306 </span>
+<span class="lineno">  307 </span>
+<span class="lineno">  308 </span><span class="decl"><span class="istickedoff">eqEps x y = abs (x-y) &lt; epsilon</span></span>
+<span class="lineno">  309 </span><span class="decl"><span class="istickedoff">near = eqEps</span></span>
+<span class="lineno">  310 </span>
+<span class="lineno">  311 </span>clampf :: Double -&gt; Double
+<span class="lineno">  312 </span><span class="decl"><span class="istickedoff">clampf p | <span class="tickonlyfalse">p &lt; 0</span> = <span class="nottickedoff">0</span></span>
+<span class="lineno">  313 </span><span class="spaces">         </span><span class="istickedoff">| p &gt; 1 = 1</span>
+<span class="lineno">  314 </span><span class="spaces">         </span><span class="istickedoff">| <span class="tickonlytrue">True</span>  = p</span></span>
 
 </pre>
 </html>
@@ -1427,143 +1343,7 @@ span.spaces    { background: white }
 
 </pre>
 </html>
-Writing: Interval.hs.html
-<html><style type="text/css">
-span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
-span.nottickedoff { background: yellow}
-span.istickedoff { background: white }
-span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
-span.tickonlytrue  { margin: -1px; border: 1px solid #60de51; background: #60de51 }
-span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
-span.decl { font-weight: bold }
-span.spaces    { background: white }
-</style>
-<pre>
-<span class="lineno">    1 </span>-- Copyright (c) 2000 Galois Connections, Inc.
-<span class="lineno">    2 </span>-- All rights reserved.  This software is distributed as
-<span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
-<span class="lineno">    4 </span>-- which is included in the distribution.
-<span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Interval
-<span class="lineno">    7 </span>    ( IList
-<span class="lineno">    8 </span>    , Intersection
-<span class="lineno">    9 </span>    , emptyIList, openIList
-<span class="lineno">   10 </span>    , mkEntry, mkExit
-<span class="lineno">   11 </span>    , entryexit, exitentry
-<span class="lineno">   12 </span>    , mapI
-<span class="lineno">   13 </span>    , unionIntervals, intersectIntervals, differenceIntervals
-<span class="lineno">   14 </span>    , complementIntervals
-<span class="lineno">   15 </span>    ) where
-<span class="lineno">   16 </span>
-<span class="lineno">   17 </span>import Geometry
-<span class="lineno">   18 </span>
-<span class="lineno">   19 </span>-- The result of a ray trace is represented as a list of surface
-<span class="lineno">   20 </span>-- intersections.  Each intersection is a point along the ray with
-<span class="lineno">   21 </span>-- a flag indicating whether this intersection is an entry or an
-<span class="lineno">   22 </span>-- exit from the solid.  Each intersection also carries unspecified
-<span class="lineno">   23 </span>-- surface data for use by the illumination model.
-<span class="lineno">   24 </span>
-<span class="lineno">   25 </span>-- Just the list of intersections isn't enough, however.  An empty
-<span class="lineno">   26 </span>-- list can denote either a trace that is always within the solid
-<span class="lineno">   27 </span>-- or never in the solid.  To dissambiguate, an extra flag is kept
-<span class="lineno">   28 </span>-- that indicates whether we are starting inside or outside of the
-<span class="lineno">   29 </span>-- solid.  As a convenience, we also keep an additional flag that
-<span class="lineno">   30 </span>-- indicates whether the last intersection ends inside or outside.
-<span class="lineno">   31 </span>
-<span class="lineno">   32 </span>type IList a       = (Bool, [Intersection a], Bool)
-<span class="lineno">   33 </span>type Intersection a     = (Double, Bool, a)
-<span class="lineno">   34 </span>
-<span class="lineno">   35 </span><span class="decl"><span class="istickedoff">emptyIList = (False, [], False)</span></span>
-<span class="lineno">   36 </span><span class="decl"><span class="nottickedoff">openIList = (True, [], True)</span></span>
-<span class="lineno">   37 </span>
-<span class="lineno">   38 </span><span class="decl"><span class="istickedoff">mapI f (b1, is, b2) = (b1, map f is, b2)</span></span>
-<span class="lineno">   39 </span>
-<span class="lineno">   40 </span><span class="decl"><span class="istickedoff">isEntry (_, entry, _) = entry</span></span>
-<span class="lineno">   41 </span><span class="decl"><span class="nottickedoff">isExit  (_, entry, _) = not entry</span></span>
-<span class="lineno">   42 </span>
-<span class="lineno">   43 </span><span class="decl"><span class="istickedoff">mkEntry (t, a) = (t, True,  a)</span></span>
-<span class="lineno">   44 </span><span class="decl"><span class="istickedoff">mkExit  (t, a) = (t, False, a)</span></span>
-<span class="lineno">   45 </span>
-<span class="lineno">   46 </span><span class="decl"><span class="istickedoff">entryexit w1 w2 = (False, [mkEntry w1, mkExit w2], False)</span></span>
-<span class="lineno">   47 </span><span class="decl"><span class="nottickedoff">exitentry w1 w2 = (True, [mkExit w1, mkEntry w2], True)</span></span>
-<span class="lineno">   48 </span><span class="decl"><span class="nottickedoff">arrange   w1@(t1, _) w2@(t2, _) | t1 &lt; t2   = entryexit w1 w2</span>
-<span class="lineno">   49 </span><span class="spaces">                                </span><span class="nottickedoff">| otherwise = entryexit w2 w1</span></span>
-<span class="lineno">   50 </span>
-<span class="lineno">   51 </span>
-<span class="lineno">   52 </span>cmpI :: Intersection a -&gt; Intersection a -&gt; Ordering
-<span class="lineno">   53 </span><span class="decl"><span class="istickedoff">cmpI (i, _, _) (j, _, _)</span>
-<span class="lineno">   54 </span><span class="spaces">  </span><span class="istickedoff">| <span class="tickonlyfalse">i `near` j</span> = <span class="nottickedoff">EQ</span></span>
-<span class="lineno">   55 </span><span class="spaces">  </span><span class="istickedoff">| i   &lt;    j = LT</span>
-<span class="lineno">   56 </span><span class="spaces">  </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span>  = GT</span></span>
-<span class="lineno">   57 </span>
-<span class="lineno">   58 </span><span class="decl"><span class="nottickedoff">bad (b1, [], b2) = b1 /= b2</span>
-<span class="lineno">   59 </span><span class="spaces"></span><span class="nottickedoff">bad (b1, is, b2) = bad' b1 is || b2 /= b3</span>
-<span class="lineno">   60 </span><span class="spaces">  </span><span class="nottickedoff">where (_, b3, _) = last is</span></span>
-<span class="lineno">   61 </span>
-<span class="lineno">   62 </span><span class="decl"><span class="nottickedoff">bad' b [] = False</span>
-<span class="lineno">   63 </span><span class="spaces"></span><span class="nottickedoff">bad' b ((_, c, _) : is) = b == c || bad' c is</span></span>
-<span class="lineno">   64 </span>
-<span class="lineno">   65 </span>unionIntervals :: IList a -&gt; IList a -&gt; IList a
-<span class="lineno">   66 </span><span class="decl"><span class="istickedoff">unionIntervals (isStartOpen, is, isEndOpen) (jsStartOpen, js, jsEndOpen)</span>
-<span class="lineno">   67 </span><span class="spaces">  </span><span class="istickedoff">= (isStartOpen || jsStartOpen, uniIntervals is js, isEndOpen || jsEndOpen)</span>
-<span class="lineno">   68 </span><span class="spaces">  </span><span class="istickedoff">where uniIntervals is [] | <span class="tickonlyfalse">jsEndOpen</span> = <span class="nottickedoff">[]</span></span>
-<span class="lineno">   69 </span><span class="spaces">                           </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span> = is</span>
-<span class="lineno">   70 </span><span class="spaces">        </span><span class="istickedoff">uniIntervals [] js | <span class="tickonlyfalse">isEndOpen</span> = <span class="nottickedoff">[]</span></span>
-<span class="lineno">   71 </span><span class="spaces">                           </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span> = js</span>
-<span class="lineno">   72 </span><span class="spaces">        </span><span class="istickedoff">uniIntervals is@(i : is') js@(j : js')</span>
-<span class="lineno">   73 </span><span class="spaces">          </span><span class="istickedoff">= case cmpI i j of</span>
-<span class="lineno">   74 </span><span class="spaces">            </span><span class="istickedoff">EQ -&gt; <span class="nottickedoff">if isEntry i == isEntry j then i : uniIntervals is' js'</span></span>
-<span class="lineno">   75 </span><span class="spaces">                                            </span><span class="istickedoff"><span class="nottickedoff">else uniIntervals is' js'</span></span>
-<span class="lineno">   76 </span><span class="spaces">            </span><span class="istickedoff">LT -&gt; if <span class="tickonlytrue">isEntry j</span> then i : <span class="nottickedoff">uniIntervals is' js</span></span>
-<span class="lineno">   77 </span><span class="spaces">                               </span><span class="istickedoff">else     <span class="nottickedoff">uniIntervals is' js</span></span>
-<span class="lineno">   78 </span><span class="spaces">            </span><span class="istickedoff">GT -&gt; if <span class="tickonlytrue">isEntry i</span> then j : uniIntervals is js'</span>
-<span class="lineno">   79 </span><span class="spaces">                               </span><span class="istickedoff">else     <span class="nottickedoff">uniIntervals is js'</span></span></span>
-<span class="lineno">   80 </span>
-<span class="lineno">   81 </span>intersectIntervals :: IList a -&gt; IList a -&gt; IList a
-<span class="lineno">   82 </span><span class="decl"><span class="nottickedoff">intersectIntervals is js</span>
-<span class="lineno">   83 </span><span class="spaces">  </span><span class="nottickedoff">= complementIntervals (unionIntervals is' js')</span>
-<span class="lineno">   84 </span><span class="spaces">  </span><span class="nottickedoff">where is' = complementIntervals is</span>
-<span class="lineno">   85 </span><span class="spaces">        </span><span class="nottickedoff">js' = complementIntervals js</span></span>
-<span class="lineno">   86 </span>
-<span class="lineno">   87 </span>differenceIntervals :: IList a -&gt; IList a -&gt; IList a
-<span class="lineno">   88 </span><span class="decl"><span class="nottickedoff">differenceIntervals is js</span>
-<span class="lineno">   89 </span><span class="spaces">  </span><span class="nottickedoff">= complementIntervals (unionIntervals is' js)</span>
-<span class="lineno">   90 </span><span class="spaces">  </span><span class="nottickedoff">where is' = complementIntervals is</span></span>
-<span class="lineno">   91 </span>
-<span class="lineno">   92 </span>complementIntervals :: IList a -&gt; IList a
-<span class="lineno">   93 </span><span class="decl"><span class="nottickedoff">complementIntervals (o1, is, o2)</span>
-<span class="lineno">   94 </span><span class="spaces">  </span><span class="nottickedoff">= (not o1, [ (i, not isentry, a) | (i, isentry, a) &lt;- is ], not o2)</span></span>
-<span class="lineno">   95 </span>
-<span class="lineno">   96 </span>-- tests...
-<span class="lineno">   97 </span>
-<span class="lineno">   98 </span>{-
-<span class="lineno">   99 </span>mkIn, mkOut :: Double -&gt; Intersection a
-<span class="lineno">  100 </span>mkIn x = (x, True, undefined)
-<span class="lineno">  101 </span>mkOut x = (x, False, undefined)
-<span class="lineno">  102 </span>
-<span class="lineno">  103 </span>i1 =  (False, [ mkIn 2, mkOut 7 ], False)
-<span class="lineno">  104 </span>i1' = (True, [ mkOut 2, mkIn 7 ], True)
-<span class="lineno">  105 </span>i2 =  (False, [ mkIn 1, mkOut 3, mkIn 4, mkOut 5, mkIn 6, mkOut 8 ], False)
-<span class="lineno">  106 </span>
-<span class="lineno">  107 </span>t1 = unionIntervals i1 i2
-<span class="lineno">  108 </span>t2 = intersectIntervals i1 i2
-<span class="lineno">  109 </span>t3 = intersectIntervals i2 i1
-<span class="lineno">  110 </span>t4 = complementIntervals i1
-<span class="lineno">  111 </span>t5 = intersectIntervals i2 i1'
-<span class="lineno">  112 </span>t6 = differenceIntervals i2 i1
-<span class="lineno">  113 </span>t7 = differenceIntervals i2 i2
-<span class="lineno">  114 </span>
-<span class="lineno">  115 </span>sh (o1,is,o2) =
-<span class="lineno">  116 </span>    do  if o1 then putStr &quot;...&quot; else return ()
-<span class="lineno">  117 </span>        putStr $ foldr1 (++) (map si is)
-<span class="lineno">  118 </span>        if o2 then putStr &quot;...&quot; else return ()
-<span class="lineno">  119 </span>si (i, True, _, _) = &quot;&lt;&quot; ++ show i
-<span class="lineno">  120 </span>si (i, False, _, _) = &quot; &quot; ++ show i ++ &quot;&gt;&quot;
-<span class="lineno">  121 </span>-}
-
-</pre>
-</html>
-Writing: Geometry.hs.html
+Writing: Construct.hs.html
 <html><style type="text/css">
 span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
 span.nottickedoff { background: yellow}
@@ -1580,315 +1360,266 @@ span.spaces    { background: white }
 <span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
 <span class="lineno">    4 </span>-- which is included in the distribution.
 <span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Geometry
-<span class="lineno">    7 </span>    ( Coords
-<span class="lineno">    8 </span>    , Ray
-<span class="lineno">    9 </span>    , Point  -- abstract
-<span class="lineno">   10 </span>    , Vector -- abstract
-<span class="lineno">   11 </span>    , Matrix -- abstract
-<span class="lineno">   12 </span>    , Color  -- abstract
-<span class="lineno">   13 </span>    , Box(..)
-<span class="lineno">   14 </span>    , Radian
-<span class="lineno">   15 </span>    , matrix
-<span class="lineno">   16 </span>    , coord
-<span class="lineno">   17 </span>    , color
-<span class="lineno">   18 </span>    , uncolor
-<span class="lineno">   19 </span>    , xCoord , yCoord , zCoord
-<span class="lineno">   20 </span>    , xComponent , yComponent , zComponent
-<span class="lineno">   21 </span>    , point
-<span class="lineno">   22 </span>    , vector
-<span class="lineno">   23 </span>    , nearV
-<span class="lineno">   24 </span>    , point_to_vector
-<span class="lineno">   25 </span>    , vector_to_point
-<span class="lineno">   26 </span>    , dot
-<span class="lineno">   27 </span>    , cross
-<span class="lineno">   28 </span>    , tangents
-<span class="lineno">   29 </span>    , addVV
-<span class="lineno">   30 </span>    , addPV
-<span class="lineno">   31 </span>    , subVV
-<span class="lineno">   32 </span>    , negV
-<span class="lineno">   33 </span>    , subPP
-<span class="lineno">   34 </span>    , norm
-<span class="lineno">   35 </span>    , normalize
-<span class="lineno">   36 </span>    , dist2
-<span class="lineno">   37 </span>    , sq
-<span class="lineno">   38 </span>    , distFrom0Sq
-<span class="lineno">   39 </span>    , distFrom0
-<span class="lineno">   40 </span>    , multSV
-<span class="lineno">   41 </span>    , multMM
-<span class="lineno">   42 </span>    , transposeM
-<span class="lineno">   43 </span>    , multMV
-<span class="lineno">   44 </span>    , multMP
-<span class="lineno">   45 </span>    , multMQ
-<span class="lineno">   46 </span>    , multMR
-<span class="lineno">   47 </span>    , white
-<span class="lineno">   48 </span>    , black
-<span class="lineno">   49 </span>    , addCC
-<span class="lineno">   50 </span>    , subCC
-<span class="lineno">   51 </span>    , sumCC
-<span class="lineno">   52 </span>    , multCC
-<span class="lineno">   53 </span>    , multSC
-<span class="lineno">   54 </span>    , nearC
-<span class="lineno">   55 </span>    , offsetToPoint
-<span class="lineno">   56 </span>    , epsilon
-<span class="lineno">   57 </span>    , inf
-<span class="lineno">   58 </span>    , nonZero
-<span class="lineno">   59 </span>    , eqEps
-<span class="lineno">   60 </span>    , near
-<span class="lineno">   61 </span>    , clampf
-<span class="lineno">   62 </span>    ) where
-<span class="lineno">   63 </span>
-<span class="lineno">   64 </span>import List 
+<span class="lineno">    6 </span>module Construct
+<span class="lineno">    7 </span>    ( Surface (..)
+<span class="lineno">    8 </span>    , Face (..)
+<span class="lineno">    9 </span>    , CSG (..)
+<span class="lineno">   10 </span>    , Texture
+<span class="lineno">   11 </span>    , Transform
+<span class="lineno">   12 </span>    , union, intersect, difference
+<span class="lineno">   13 </span>    , plane, sphere, cube, cylinder, cone
+<span class="lineno">   14 </span>    , transform
+<span class="lineno">   15 </span>    , translate, translateX, translateY, translateZ
+<span class="lineno">   16 </span>    , scale, scaleX, scaleY, scaleZ, uscale
+<span class="lineno">   17 </span>    , rotateX, rotateY, rotateZ
+<span class="lineno">   18 </span>    , eye, translateEye
+<span class="lineno">   19 </span>    , rotateEyeX, rotateEyeY, rotateEyeZ
+<span class="lineno">   20 </span>    ) where
+<span class="lineno">   21 </span>
+<span class="lineno">   22 </span>import Geometry
+<span class="lineno">   23 </span>
+<span class="lineno">   24 </span>-- In each case, we model the surface by a point and a pair of tangent vectors.
+<span class="lineno">   25 </span>-- This gives us enough information to determine the surface
+<span class="lineno">   26 </span>-- normal at that point, which is all that is required by the current
+<span class="lineno">   27 </span>-- illumination model.  We can't just save the surface normal because
+<span class="lineno">   28 </span>-- that isn't preserved by transformations.
+<span class="lineno">   29 </span>
+<span class="lineno">   30 </span>data Surface
+<span class="lineno">   31 </span>  = Planar Point Vector Vector
+<span class="lineno">   32 </span>  | Spherical Point Vector Vector
+<span class="lineno">   33 </span>  | Cylindrical Point Vector Vector
+<span class="lineno">   34 </span>  | Conic Point Vector Vector
+<span class="lineno">   35 </span>  deriving <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>
+<span class="lineno">   36 </span>
+<span class="lineno">   37 </span>data Face
+<span class="lineno">   38 </span>  = PlaneFace
+<span class="lineno">   39 </span>  | SphereFace
+<span class="lineno">   40 </span>  | CubeFront
+<span class="lineno">   41 </span>  | CubeBack
+<span class="lineno">   42 </span>  | CubeLeft
+<span class="lineno">   43 </span>  | CubeRight
+<span class="lineno">   44 </span>  | CubeTop
+<span class="lineno">   45 </span>  | CubeBottom
+<span class="lineno">   46 </span>  | CylinderSide
+<span class="lineno">   47 </span>  | CylinderTop
+<span class="lineno">   48 </span>  | CylinderBottom
+<span class="lineno">   49 </span>  | ConeSide
+<span class="lineno">   50 </span>  | ConeBase
+<span class="lineno">   51 </span>  deriving <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>
+<span class="lineno">   52 </span>
+<span class="lineno">   53 </span>data CSG a
+<span class="lineno">   54 </span>  = Plane a
+<span class="lineno">   55 </span>  | Sphere a
+<span class="lineno">   56 </span>  | Cylinder a
+<span class="lineno">   57 </span>  | Cube a
+<span class="lineno">   58 </span>  | Cone a
+<span class="lineno">   59 </span>  | Transform Matrix Matrix (CSG a)
+<span class="lineno">   60 </span>  | Union (CSG a) (CSG a)
+<span class="lineno">   61 </span>  | Intersect (CSG a) (CSG a)
+<span class="lineno">   62 </span>  | Difference (CSG a) (CSG a)
+<span class="lineno">   63 </span>  | Box Box (CSG a)
+<span class="lineno">   64 </span>  deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
 <span class="lineno">   65 </span>
-<span class="lineno">   66 </span>type Coords = (Double,Double,Double)
-<span class="lineno">   67 </span>
-<span class="lineno">   68 </span>type Ray = (Point,Vector)    -- origin of ray, and unit vector giving direction
-<span class="lineno">   69 </span>
-<span class="lineno">   70 </span>data Point  = P !Double !Double !Double -- implicit extra arg of 1
-<span class="lineno">   71 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
-<span class="lineno">   72 </span>data Vector = V !Double !Double !Double -- implicit extra arg of 0
-<span class="lineno">   73 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>, <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Eq</span></span></span></span>)
-<span class="lineno">   74 </span>data Matrix = M !Quad   !Quad   !Quad   !Quad
-<span class="lineno">   75 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
+<span class="lineno">   66 </span>-- the data returned for determining surface texture
+<span class="lineno">   67 </span>-- the Face tells which face of a primitive this is
+<span class="lineno">   68 </span>-- the Point is the point of intersection in object coordinates
+<span class="lineno">   69 </span>-- the a is application-specific texture information
+<span class="lineno">   70 </span>type Texture a = (Face, Point, a)
+<span class="lineno">   71 </span>
+<span class="lineno">   72 </span>union, intersect, difference       :: CSG a -&gt; CSG a -&gt; CSG a
+<span class="lineno">   73 </span>
+<span class="lineno">   74 </span><span class="decl"><span class="istickedoff">union p@(Box b1 _) q@(Box b2 _) = <span class="nottickedoff">Box (mergeBox b1 b2) (Union p q)</span></span>
+<span class="lineno">   75 </span><span class="spaces"></span><span class="istickedoff">union p q = Union p q</span></span>
 <span class="lineno">   76 </span>
-<span class="lineno">   77 </span>data Color  = C !Double !Double !Double
-<span class="lineno">   78 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>, <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Eq</span></span></span></span>)
-<span class="lineno">   79 </span>
-<span class="lineno">   80 </span>data Box = B !Double !Double !Double !Double !Double !Double
-<span class="lineno">   81 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
-<span class="lineno">   82 </span>
-<span class="lineno">   83 </span>data Quad   = Q !Double !Double !Double !Double
-<span class="lineno">   84 </span>    deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
+<span class="lineno">   77 </span>-- rather pessimistic
+<span class="lineno">   78 </span><span class="decl"><span class="nottickedoff">intersect p@(Box b1 _) q@(Box b2 _) = Box (mergeBox b1 b2) (Intersect p q)</span>
+<span class="lineno">   79 </span><span class="spaces"></span><span class="nottickedoff">intersect p q = Intersect p q</span></span>
+<span class="lineno">   80 </span>
+<span class="lineno">   81 </span><span class="decl"><span class="nottickedoff">difference (Box b1 p) q = Box b1 (Difference p q)</span>
+<span class="lineno">   82 </span><span class="spaces"></span><span class="nottickedoff">-- no need to box again inside</span>
+<span class="lineno">   83 </span><span class="spaces"></span><span class="nottickedoff">-- difference p@(Box b1 _) q = Box b1 (Difference p q)</span>
+<span class="lineno">   84 </span><span class="spaces"></span><span class="nottickedoff">difference p q = Difference p q</span></span>
 <span class="lineno">   85 </span>
-<span class="lineno">   86 </span>type Radian = Double
+<span class="lineno">   86 </span><span class="decl"><span class="istickedoff">mkBox b p = Box b p</span></span>
 <span class="lineno">   87 </span>
-<span class="lineno">   88 </span>type Tup4 a = (a,a,a,a)
+<span class="lineno">   88 </span>plane, sphere, cube, cylinder, cone     :: a -&gt; CSG a
 <span class="lineno">   89 </span>
-<span class="lineno">   90 </span>--{-# INLINE matrix #-}
-<span class="lineno">   91 </span>matrix :: Tup4 (Tup4 Double) -&gt; Matrix
-<span class="lineno">   92 </span><span class="decl"><span class="istickedoff">matrix ((m11, m12, m13, m14),</span>
-<span class="lineno">   93 </span><span class="spaces">          </span><span class="istickedoff">(m21, m22, m23, m24),</span>
-<span class="lineno">   94 </span><span class="spaces">          </span><span class="istickedoff">(m31, m32, m33, m34),</span>
-<span class="lineno">   95 </span><span class="spaces">          </span><span class="istickedoff">(m41, m42, m43, m44))</span>
-<span class="lineno">   96 </span><span class="spaces">  </span><span class="istickedoff">= M (Q m11 m12 m13 m14)</span>
-<span class="lineno">   97 </span><span class="spaces">      </span><span class="istickedoff">(Q m21 m22 m23 m24)</span>
-<span class="lineno">   98 </span><span class="spaces">      </span><span class="istickedoff">(Q m31 m32 m33 m34)</span>
-<span class="lineno">   99 </span><span class="spaces">      </span><span class="istickedoff">(Q m41 m42 m43 m44)</span></span>
-<span class="lineno">  100 </span>
-<span class="lineno">  101 </span><span class="decl"><span class="nottickedoff">coord x y z = (x, y, z)</span></span>
-<span class="lineno">  102 </span>
-<span class="lineno">  103 </span><span class="decl"><span class="istickedoff">color r g b = C r g b</span></span>
-<span class="lineno">  104 </span>
-<span class="lineno">  105 </span><span class="decl"><span class="istickedoff">uncolor (C r g b) = (r,g,b)</span></span>
-<span class="lineno">  106 </span>
-<span class="lineno">  107 </span>{-# INLINE xCoord #-}
-<span class="lineno">  108 </span><span class="decl"><span class="istickedoff">xCoord (P x y z) = x</span></span>
-<span class="lineno">  109 </span>{-# INLINE yCoord #-}
-<span class="lineno">  110 </span><span class="decl"><span class="istickedoff">yCoord (P x y z) = y</span></span>
-<span class="lineno">  111 </span>{-# INLINE zCoord #-}
-<span class="lineno">  112 </span><span class="decl"><span class="istickedoff">zCoord (P x y z) = z</span></span>
+<span class="lineno">   90 </span><span class="decl"><span class="istickedoff">plane = Plane</span></span>
+<span class="lineno">   91 </span><span class="decl"><span class="nottickedoff">sphere s =</span>
+<span class="lineno">   92 </span><span class="spaces">    </span><span class="nottickedoff">mkBox (B (-1 - epsilon) (1 + epsilon)</span>
+<span class="lineno">   93 </span><span class="spaces">             </span><span class="nottickedoff">(-1 - epsilon) (1 + epsilon)</span>
+<span class="lineno">   94 </span><span class="spaces">             </span><span class="nottickedoff">(-1 - epsilon) (1 + epsilon)) (Sphere s)</span></span>
+<span class="lineno">   95 </span><span class="decl"><span class="nottickedoff">cone s =</span>
+<span class="lineno">   96 </span><span class="spaces">    </span><span class="nottickedoff">mkBox (B (-1 - epsilon) (1 + epsilon)</span>
+<span class="lineno">   97 </span><span class="spaces">             </span><span class="nottickedoff">(   - epsilon) (1 + epsilon)</span>
+<span class="lineno">   98 </span><span class="spaces">             </span><span class="nottickedoff">(-1 - epsilon) (1 + epsilon)) (Cone s)</span></span>
+<span class="lineno">   99 </span><span class="decl"><span class="istickedoff">cube s =</span>
+<span class="lineno">  100 </span><span class="spaces">    </span><span class="istickedoff">mkBox (B (- epsilon) (1 + epsilon)</span>
+<span class="lineno">  101 </span><span class="spaces">             </span><span class="istickedoff">(- epsilon) (1 + epsilon)</span>
+<span class="lineno">  102 </span><span class="spaces">             </span><span class="istickedoff">(- epsilon) (1 + epsilon)) (Cube s)</span></span>
+<span class="lineno">  103 </span><span class="decl"><span class="nottickedoff">cylinder s =</span>
+<span class="lineno">  104 </span><span class="spaces">    </span><span class="nottickedoff">mkBox (B (-1 - epsilon) (1 + epsilon)</span>
+<span class="lineno">  105 </span><span class="spaces">             </span><span class="nottickedoff">(   - epsilon) (1 + epsilon)</span>
+<span class="lineno">  106 </span><span class="spaces">             </span><span class="nottickedoff">(-1 - epsilon) (1 + epsilon)) (Cylinder s)</span></span>
+<span class="lineno">  107 </span>
+<span class="lineno">  108 </span>----------------------------
+<span class="lineno">  109 </span>-- Object transformations
+<span class="lineno">  110 </span>----------------------------
+<span class="lineno">  111 </span>
+<span class="lineno">  112 </span>type Transform = (Matrix, Matrix)
 <span class="lineno">  113 </span>
-<span class="lineno">  114 </span>{-# INLINE xComponent #-}
-<span class="lineno">  115 </span><span class="decl"><span class="istickedoff">xComponent (V x y z) = x</span></span>
-<span class="lineno">  116 </span>{-# INLINE yComponent #-}
-<span class="lineno">  117 </span><span class="decl"><span class="istickedoff">yComponent (V x y z) = y</span></span>
-<span class="lineno">  118 </span>{-# INLINE zComponent #-}
-<span class="lineno">  119 </span><span class="decl"><span class="istickedoff">zComponent (V x y z) = z</span></span>
-<span class="lineno">  120 </span>
-<span class="lineno">  121 </span>point :: Double -&gt; Double -&gt; Double -&gt; Point
-<span class="lineno">  122 </span><span class="decl"><span class="istickedoff">point x y z = P x y z</span></span>
-<span class="lineno">  123 </span>
-<span class="lineno">  124 </span>vector :: Double -&gt; Double -&gt; Double -&gt; Vector
-<span class="lineno">  125 </span><span class="decl"><span class="istickedoff">vector x y z = V x y z</span></span>
-<span class="lineno">  126 </span>
-<span class="lineno">  127 </span>nearV :: Vector -&gt; Vector -&gt; Bool
-<span class="lineno">  128 </span><span class="decl"><span class="nottickedoff">nearV (V a b c) (V d e f) = a `near` d &amp;&amp; b `near` e &amp;&amp; c `near` f</span></span>
-<span class="lineno">  129 </span>
-<span class="lineno">  130 </span>point_to_vector :: Point -&gt; Vector
-<span class="lineno">  131 </span><span class="decl"><span class="nottickedoff">point_to_vector (P x y z) = V x y z</span></span>
-<span class="lineno">  132 </span>
-<span class="lineno">  133 </span>vector_to_point :: Vector -&gt; Point
-<span class="lineno">  134 </span><span class="decl"><span class="nottickedoff">vector_to_point (V x y z)  = P x y z</span></span> 
-<span class="lineno">  135 </span>
-<span class="lineno">  136 </span>{-# INLINE vector_to_quad #-}
-<span class="lineno">  137 </span>vector_to_quad :: Vector -&gt; Quad
-<span class="lineno">  138 </span><span class="decl"><span class="istickedoff">vector_to_quad (V x y z) = Q x y z 0</span></span>
+<span class="lineno">  114 </span>transform :: Transform -&gt; CSG a -&gt; CSG a
+<span class="lineno">  115 </span>
+<span class="lineno">  116 </span><span class="decl"><span class="istickedoff">transform (m, m')   (Transform mp mp' p) = Transform  (multMM m mp)       (multMM mp' m') p</span>
+<span class="lineno">  117 </span><span class="spaces"></span><span class="istickedoff">transform mm'       (Union p q)          = Union      (transform mm' p)   (transform mm' q)</span>
+<span class="lineno">  118 </span><span class="spaces"></span><span class="istickedoff">transform mm'       (Intersect p q)      = <span class="nottickedoff">Intersect  (transform mm' p)   (transform mm' q)</span></span>
+<span class="lineno">  119 </span><span class="spaces"></span><span class="istickedoff">transform mm'       (Difference p q)     = <span class="nottickedoff">Difference (transform mm' p)   (transform mm' q)</span></span>
+<span class="lineno">  120 </span><span class="spaces"></span><span class="istickedoff">transform mm'@(m,_) (Box box p)          = Box        (transformBox m box) (transform mm' p)</span>
+<span class="lineno">  121 </span><span class="spaces"></span><span class="istickedoff">transform (m, m')   prim                 = Transform  m m' prim</span></span>
+<span class="lineno">  122 </span>
+<span class="lineno">  123 </span>translate                      :: Coords -&gt; CSG a -&gt; CSG a
+<span class="lineno">  124 </span>translateX, translateY, translateZ      :: Double -&gt; CSG a -&gt; CSG a
+<span class="lineno">  125 </span>
+<span class="lineno">  126 </span><span class="decl"><span class="istickedoff">translate xyz = transform $ transM xyz</span></span>
+<span class="lineno">  127 </span><span class="decl"><span class="nottickedoff">translateX x = translate (x, 0, 0)</span></span>
+<span class="lineno">  128 </span><span class="decl"><span class="nottickedoff">translateY y = translate (0, y, 0)</span></span>
+<span class="lineno">  129 </span><span class="decl"><span class="nottickedoff">translateZ z = translate (0, 0, z)</span></span>
+<span class="lineno">  130 </span>
+<span class="lineno">  131 </span>scale                    :: Coords -&gt; CSG a -&gt; CSG a
+<span class="lineno">  132 </span>scaleX, scaleY, scaleZ, uscale   :: Double -&gt; CSG a -&gt; CSG a
+<span class="lineno">  133 </span>
+<span class="lineno">  134 </span><span class="decl"><span class="istickedoff">scale xyz = transform $ scaleM xyz</span></span>
+<span class="lineno">  135 </span><span class="decl"><span class="nottickedoff">scaleX x = scale (x, 1, 1)</span></span>
+<span class="lineno">  136 </span><span class="decl"><span class="nottickedoff">scaleY y = scale (1, y, 1)</span></span>
+<span class="lineno">  137 </span><span class="decl"><span class="nottickedoff">scaleZ z = scale (1, 1, z)</span></span>
+<span class="lineno">  138 </span><span class="decl"><span class="istickedoff">uscale u = scale (u,u,u)</span></span>
 <span class="lineno">  139 </span>
-<span class="lineno">  140 </span>{-# INLINE point_to_quad #-}
-<span class="lineno">  141 </span>point_to_quad :: Point -&gt; Quad
-<span class="lineno">  142 </span><span class="decl"><span class="istickedoff">point_to_quad (P x y z) = Q x y z 1</span></span>
-<span class="lineno">  143 </span>
-<span class="lineno">  144 </span>{-# INLINE quad_to_point #-}
-<span class="lineno">  145 </span>quad_to_point :: Quad -&gt; Point
-<span class="lineno">  146 </span><span class="decl"><span class="istickedoff">quad_to_point (Q x y z _) = P x y z</span></span>
-<span class="lineno">  147 </span>
-<span class="lineno">  148 </span>{-# INLINE quad_to_vector #-}
-<span class="lineno">  149 </span>quad_to_vector :: Quad -&gt; Vector
-<span class="lineno">  150 </span><span class="decl"><span class="istickedoff">quad_to_vector (Q x y z _) = V x y z</span></span>
+<span class="lineno">  140 </span>rotateX, rotateY, rotateZ             :: Radian -&gt; CSG a -&gt; CSG a
+<span class="lineno">  141 </span>
+<span class="lineno">  142 </span><span class="decl"><span class="istickedoff">rotateX a = transform $ rotxM a</span></span>
+<span class="lineno">  143 </span><span class="decl"><span class="istickedoff">rotateY a = transform $ rotyM a</span></span>
+<span class="lineno">  144 </span><span class="decl"><span class="nottickedoff">rotateZ a = transform $ rotzM a</span></span>
+<span class="lineno">  145 </span>
+<span class="lineno">  146 </span><span class="decl"><span class="istickedoff">unit = matrix</span>
+<span class="lineno">  147 </span><span class="spaces">      </span><span class="istickedoff">( ( 1.0, 0.0, 0.0, 0.0 ),</span>
+<span class="lineno">  148 </span><span class="spaces">        </span><span class="istickedoff">( 0.0, 1.0, 0.0, 0.0 ),</span>
+<span class="lineno">  149 </span><span class="spaces">        </span><span class="istickedoff">( 0.0, 0.0, 1.0, 0.0 ),</span>
+<span class="lineno">  150 </span><span class="spaces">        </span><span class="istickedoff">( 0.0, 0.0, 0.0, 1.0 ) )</span></span>
 <span class="lineno">  151 </span>
-<span class="lineno">  152 </span>--{-# INLINE dot #-}
-<span class="lineno">  153 </span>dot :: Vector -&gt; Vector -&gt; Double
-<span class="lineno">  154 </span><span class="decl"><span class="istickedoff">dot (V x1 y1 z1) (V x2 y2 z2) = x1 * x2 + y1 * y2 + z1 * z2</span></span>
-<span class="lineno">  155 </span>
-<span class="lineno">  156 </span>cross :: Vector -&gt; Vector -&gt; Vector
-<span class="lineno">  157 </span><span class="decl"><span class="istickedoff">cross (V x1 y1 z1) (V x2 y2 z2)</span>
-<span class="lineno">  158 </span><span class="spaces">  </span><span class="istickedoff">= V (y1 * z2 - z1 * y2) (z1 * x2 - x1 * z2) (x1 * y2 - y1 * x2)</span></span>
-<span class="lineno">  159 </span>
-<span class="lineno">  160 </span>-- assumption: the input vector is a normal
-<span class="lineno">  161 </span>tangents :: Vector -&gt; (Vector, Vector)
-<span class="lineno">  162 </span><span class="decl"><span class="nottickedoff">tangents v@(V x y z)</span>
-<span class="lineno">  163 </span><span class="spaces">  </span><span class="nottickedoff">= (v1, v `cross` v1)</span>
-<span class="lineno">  164 </span><span class="spaces">  </span><span class="nottickedoff">where v1 | x == 0    = normalize (vector 0 z (-y))</span>
-<span class="lineno">  165 </span><span class="spaces">           </span><span class="nottickedoff">| otherwise = normalize (vector (-y) x 0)</span></span>
-<span class="lineno">  166 </span>
-<span class="lineno">  167 </span>{-# INLINE dot4 #-}
-<span class="lineno">  168 </span>dot4 :: Quad -&gt; Quad -&gt; Double
-<span class="lineno">  169 </span><span class="decl"><span class="istickedoff">dot4 (Q x1 y1 z1 w1) (Q x2 y2 z2 w2) = x1 * x2 + y1 * y2 + z1 * z2 + w1 * w2</span></span>
-<span class="lineno">  170 </span>
-<span class="lineno">  171 </span>addVV :: Vector -&gt; Vector -&gt; Vector
-<span class="lineno">  172 </span><span class="decl"><span class="nottickedoff">addVV (V x1 y1 z1) (V x2 y2 z2) </span>
-<span class="lineno">  173 </span><span class="spaces">    </span><span class="nottickedoff">= V (x1 + x2) (y1 + y2) (z1 + z2)</span></span>
-<span class="lineno">  174 </span>
-<span class="lineno">  175 </span>addPV :: Point -&gt; Vector -&gt; Point
-<span class="lineno">  176 </span><span class="decl"><span class="istickedoff">addPV (P x1 y1 z1) (V x2 y2 z2) </span>
-<span class="lineno">  177 </span><span class="spaces">    </span><span class="istickedoff">= P (x1 + x2) (y1 + y2) (z1 + z2)</span></span>
+<span class="lineno">  152 </span><span class="decl"><span class="istickedoff">transM (x, y, z)</span>
+<span class="lineno">  153 </span><span class="spaces">  </span><span class="istickedoff">= ( matrix</span>
+<span class="lineno">  154 </span><span class="spaces">      </span><span class="istickedoff">( ( 1, 0, 0, x ),</span>
+<span class="lineno">  155 </span><span class="spaces">        </span><span class="istickedoff">( 0, 1, 0, y ),</span>
+<span class="lineno">  156 </span><span class="spaces">        </span><span class="istickedoff">( 0, 0, 1, z ),</span>
+<span class="lineno">  157 </span><span class="spaces">        </span><span class="istickedoff">( 0, 0, 0, 1 ) ),</span>
+<span class="lineno">  158 </span><span class="spaces">      </span><span class="istickedoff">matrix</span>
+<span class="lineno">  159 </span><span class="spaces">      </span><span class="istickedoff">( ( 1, 0, 0, -x ),</span>
+<span class="lineno">  160 </span><span class="spaces">        </span><span class="istickedoff">( 0, 1, 0, -y ),</span>
+<span class="lineno">  161 </span><span class="spaces">        </span><span class="istickedoff">( 0, 0, 1, -z ),</span>
+<span class="lineno">  162 </span><span class="spaces">        </span><span class="istickedoff">( 0, 0, 0,  1 ) ) )</span></span>
+<span class="lineno">  163 </span>
+<span class="lineno">  164 </span><span class="decl"><span class="istickedoff">scaleM (x, y, z)</span>
+<span class="lineno">  165 </span><span class="spaces">  </span><span class="istickedoff">= ( matrix</span>
+<span class="lineno">  166 </span><span class="spaces">      </span><span class="istickedoff">( (   x',    0,    0, 0 ),</span>
+<span class="lineno">  167 </span><span class="spaces">        </span><span class="istickedoff">(    0,   y',    0, 0 ),</span>
+<span class="lineno">  168 </span><span class="spaces">        </span><span class="istickedoff">(    0,    0,   z', 0 ),</span>
+<span class="lineno">  169 </span><span class="spaces">        </span><span class="istickedoff">(    0,    0,    0, 1 ) ),</span>
+<span class="lineno">  170 </span><span class="spaces">      </span><span class="istickedoff">matrix</span>
+<span class="lineno">  171 </span><span class="spaces">      </span><span class="istickedoff">( ( 1/x',    0,    0, 0 ),</span>
+<span class="lineno">  172 </span><span class="spaces">        </span><span class="istickedoff">(    0, 1/y',    0, 0 ),</span>
+<span class="lineno">  173 </span><span class="spaces">        </span><span class="istickedoff">(    0,    0, 1/z', 0 ),</span>
+<span class="lineno">  174 </span><span class="spaces">        </span><span class="istickedoff">(    0,    0,    0, 1 ) ) )</span>
+<span class="lineno">  175 </span><span class="spaces">  </span><span class="istickedoff">where x' = nonZero x</span>
+<span class="lineno">  176 </span><span class="spaces">        </span><span class="istickedoff">y' = nonZero y</span>
+<span class="lineno">  177 </span><span class="spaces">        </span><span class="istickedoff">z' = nonZero z</span></span>
 <span class="lineno">  178 </span>
-<span class="lineno">  179 </span>subVV :: Vector -&gt; Vector -&gt; Vector
-<span class="lineno">  180 </span><span class="decl"><span class="istickedoff">subVV (V x1 y1 z1) (V x2 y2 z2) </span>
-<span class="lineno">  181 </span><span class="spaces">    </span><span class="istickedoff">= V (x1 - x2) (y1 - y2) (z1 - z2)</span></span>
-<span class="lineno">  182 </span>
-<span class="lineno">  183 </span>negV :: Vector -&gt; Vector
-<span class="lineno">  184 </span><span class="decl"><span class="nottickedoff">negV (V x1 y1 z1) </span>
-<span class="lineno">  185 </span><span class="spaces">    </span><span class="nottickedoff">= V (-x1) (-y1) (-z1)</span></span>
-<span class="lineno">  186 </span>
-<span class="lineno">  187 </span>subPP :: Point -&gt; Point -&gt; Vector
-<span class="lineno">  188 </span><span class="decl"><span class="nottickedoff">subPP (P x1 y1 z1) (P x2 y2 z2) </span>
-<span class="lineno">  189 </span><span class="spaces">    </span><span class="nottickedoff">= V (x1 - x2) (y1 - y2) (z1 - z2)</span></span>
+<span class="lineno">  179 </span><span class="decl"><span class="istickedoff">rotxM t</span>
+<span class="lineno">  180 </span><span class="spaces">  </span><span class="istickedoff">= ( matrix</span>
+<span class="lineno">  181 </span><span class="spaces">      </span><span class="istickedoff">( (      1,      0,      0, 0 ),</span>
+<span class="lineno">  182 </span><span class="spaces">        </span><span class="istickedoff">(      0,  cos t, -sin t, 0 ),</span>
+<span class="lineno">  183 </span><span class="spaces">        </span><span class="istickedoff">(      0,  sin t,  cos t, 0 ),</span>
+<span class="lineno">  184 </span><span class="spaces">        </span><span class="istickedoff">(      0,      0,      0, 1 ) ),</span>
+<span class="lineno">  185 </span><span class="spaces">      </span><span class="istickedoff">matrix</span>
+<span class="lineno">  186 </span><span class="spaces">      </span><span class="istickedoff">( (      1,      0,      0, 0 ),</span>
+<span class="lineno">  187 </span><span class="spaces">        </span><span class="istickedoff">(      0,  cos t,  sin t, 0 ),</span>
+<span class="lineno">  188 </span><span class="spaces">        </span><span class="istickedoff">(      0, -sin t,  cos t, 0 ),</span>
+<span class="lineno">  189 </span><span class="spaces">        </span><span class="istickedoff">(      0,      0,      0, 1 ) ) )</span></span>
 <span class="lineno">  190 </span>
-<span class="lineno">  191 </span>--{-# INLINE norm #-}
-<span class="lineno">  192 </span>norm :: Vector -&gt; Double
-<span class="lineno">  193 </span><span class="decl"><span class="nottickedoff">norm (V x y z) = sqrt (sq x + sq y + sq z)</span></span>
-<span class="lineno">  194 </span>
-<span class="lineno">  195 </span>--{-# INLINE normalize #-}
-<span class="lineno">  196 </span>-- normalize a vector to a unit vector
-<span class="lineno">  197 </span>normalize :: Vector -&gt; Vector
-<span class="lineno">  198 </span><span class="decl"><span class="istickedoff">normalize v@(V x y z)</span>
-<span class="lineno">  199 </span><span class="spaces">             </span><span class="istickedoff">| <span class="tickonlytrue">norm /= 0</span> = multSV (1/norm) v</span>
-<span class="lineno">  200 </span><span class="spaces">             </span><span class="istickedoff">| <span class="nottickedoff">otherwise</span> = <span class="nottickedoff">error &quot;normalize empty!&quot;</span></span>
-<span class="lineno">  201 </span><span class="spaces">    </span><span class="istickedoff">where norm = sqrt (sq x + sq y + sq z)</span></span>
+<span class="lineno">  191 </span><span class="decl"><span class="istickedoff">rotyM t</span>
+<span class="lineno">  192 </span><span class="spaces">  </span><span class="istickedoff">= ( matrix</span>
+<span class="lineno">  193 </span><span class="spaces">      </span><span class="istickedoff">( (  cos t,      0,  sin t, 0 ),</span>
+<span class="lineno">  194 </span><span class="spaces">        </span><span class="istickedoff">(      0,      1,      0, 0 ),</span>
+<span class="lineno">  195 </span><span class="spaces">        </span><span class="istickedoff">( -sin t,      0,  cos t, 0 ),</span>
+<span class="lineno">  196 </span><span class="spaces">        </span><span class="istickedoff">(      0,      0,      0, 1 ) ),</span>
+<span class="lineno">  197 </span><span class="spaces">      </span><span class="istickedoff">matrix</span>
+<span class="lineno">  198 </span><span class="spaces">      </span><span class="istickedoff">( (  cos t,      0, -sin t, 0 ),</span>
+<span class="lineno">  199 </span><span class="spaces">        </span><span class="istickedoff">(      0,      1,      0, 0 ),</span>
+<span class="lineno">  200 </span><span class="spaces">        </span><span class="istickedoff">(  sin t,      0,  cos t, 0 ),</span>
+<span class="lineno">  201 </span><span class="spaces">        </span><span class="istickedoff">(      0,      0,      0, 1 ) ) )</span></span>
 <span class="lineno">  202 </span>
-<span class="lineno">  203 </span>-- This does computes the distance *squared*
-<span class="lineno">  204 </span>dist2 :: Point -&gt; Point -&gt; Double
-<span class="lineno">  205 </span><span class="decl"><span class="nottickedoff">dist2 us vs = sq x + sq y + sq z</span>
-<span class="lineno">  206 </span><span class="spaces">    </span><span class="nottickedoff">where</span>
-<span class="lineno">  207 </span><span class="spaces">       </span><span class="nottickedoff">(V x y z) = subPP us vs</span></span>
-<span class="lineno">  208 </span>
-<span class="lineno">  209 </span>{-# INLINE sq #-}
-<span class="lineno">  210 </span>sq :: Double -&gt; Double
-<span class="lineno">  211 </span><span class="decl"><span class="istickedoff">sq d = d * d</span></span> 
-<span class="lineno">  212 </span>
-<span class="lineno">  213 </span>{-# INLINE distFrom0Sq #-}
-<span class="lineno">  214 </span>distFrom0Sq :: Point -&gt; Double  -- Distance of point from origin.
-<span class="lineno">  215 </span><span class="decl"><span class="nottickedoff">distFrom0Sq (P x y z) = sq x + sq y + sq z</span></span>
-<span class="lineno">  216 </span>
-<span class="lineno">  217 </span>{-# INLINE distFrom0 #-}
-<span class="lineno">  218 </span>distFrom0 :: Point -&gt; Double  -- Distance of point from origin.
-<span class="lineno">  219 </span><span class="decl"><span class="nottickedoff">distFrom0 p = sqrt (distFrom0Sq p)</span></span>
-<span class="lineno">  220 </span>
-<span class="lineno">  221 </span>--{-# INLINE multSV #-}
-<span class="lineno">  222 </span>multSV :: Double -&gt; Vector -&gt; Vector
-<span class="lineno">  223 </span><span class="decl"><span class="istickedoff">multSV k (V x y z) = V (k*x) (k*y) (k*z)</span></span>
-<span class="lineno">  224 </span>
-<span class="lineno">  225 </span>--{-# INLINE multMM #-}
-<span class="lineno">  226 </span>multMM :: Matrix -&gt; Matrix -&gt; Matrix
-<span class="lineno">  227 </span><span class="decl"><span class="istickedoff">multMM m1@(M q1 q2 q3 q4) m2</span>
-<span class="lineno">  228 </span><span class="spaces">     </span><span class="istickedoff">= M (multMQ m2' q1)</span>
-<span class="lineno">  229 </span><span class="spaces">         </span><span class="istickedoff">(multMQ m2' q2)</span>
-<span class="lineno">  230 </span><span class="spaces">         </span><span class="istickedoff">(multMQ m2' q3)</span>
-<span class="lineno">  231 </span><span class="spaces">         </span><span class="istickedoff">(multMQ m2' q4)</span>
-<span class="lineno">  232 </span><span class="spaces">  </span><span class="istickedoff">where</span>
-<span class="lineno">  233 </span><span class="spaces">     </span><span class="istickedoff">m2' = transposeM m2</span></span>
-<span class="lineno">  234 </span>
-<span class="lineno">  235 </span>{-# INLINE transposeM #-}     
-<span class="lineno">  236 </span>transposeM :: Matrix -&gt; Matrix
-<span class="lineno">  237 </span><span class="decl"><span class="istickedoff">transposeM (M (Q e11  e12  e13  e14)</span>
-<span class="lineno">  238 </span><span class="spaces">              </span><span class="istickedoff">(Q e21  e22  e23  e24)</span>
-<span class="lineno">  239 </span><span class="spaces">              </span><span class="istickedoff">(Q e31  e32  e33  e34)</span>
-<span class="lineno">  240 </span><span class="spaces">              </span><span class="istickedoff">(Q e41  e42  e43  e44)) = (M (Q e11  e21  e31  e41)</span>
-<span class="lineno">  241 </span><span class="spaces">                                           </span><span class="istickedoff">(Q e12  e22  e32  e42)</span>
-<span class="lineno">  242 </span><span class="spaces">                                           </span><span class="istickedoff">(Q e13  e23  e33  e43)</span>
-<span class="lineno">  243 </span><span class="spaces">                                           </span><span class="istickedoff">(Q e14  e24  e34  e44))</span></span>
+<span class="lineno">  203 </span><span class="decl"><span class="nottickedoff">rotzM t</span>
+<span class="lineno">  204 </span><span class="spaces">  </span><span class="nottickedoff">= ( matrix</span>
+<span class="lineno">  205 </span><span class="spaces">      </span><span class="nottickedoff">( (  cos t, -sin t,      0, 0 ),</span>
+<span class="lineno">  206 </span><span class="spaces">        </span><span class="nottickedoff">(  sin t,  cos t,      0, 0 ),</span>
+<span class="lineno">  207 </span><span class="spaces">        </span><span class="nottickedoff">(      0,      0,      1, 0 ),</span>
+<span class="lineno">  208 </span><span class="spaces">        </span><span class="nottickedoff">(      0,      0,      0, 1 ) ),</span>
+<span class="lineno">  209 </span><span class="spaces">      </span><span class="nottickedoff">matrix</span>
+<span class="lineno">  210 </span><span class="spaces">      </span><span class="nottickedoff">( (  cos t,  sin t,      0, 0 ),</span>
+<span class="lineno">  211 </span><span class="spaces">        </span><span class="nottickedoff">( -sin t,  cos t,      0, 0 ),</span>
+<span class="lineno">  212 </span><span class="spaces">        </span><span class="nottickedoff">(      0,      0,      1, 0 ),</span>
+<span class="lineno">  213 </span><span class="spaces">        </span><span class="nottickedoff">(      0,      0,      0, 1 ) ) )</span></span>
+<span class="lineno">  214 </span>
+<span class="lineno">  215 </span>-------------------
+<span class="lineno">  216 </span>-- Eye transformations
+<span class="lineno">  217 </span>
+<span class="lineno">  218 </span>-- These are used to specify placement of the eye.
+<span class="lineno">  219 </span>-- `eye' starts out at (0, 0, -1).
+<span class="lineno">  220 </span>-- These are implemented as inverse transforms of the model.
+<span class="lineno">  221 </span>-------------------
+<span class="lineno">  222 </span>
+<span class="lineno">  223 </span>eye                       :: Transform
+<span class="lineno">  224 </span>translateEye          :: Coords -&gt; Transform -&gt; Transform
+<span class="lineno">  225 </span>rotateEyeX, rotateEyeY, rotateEyeZ      :: Radian -&gt; Transform -&gt; Transform
+<span class="lineno">  226 </span>
+<span class="lineno">  227 </span><span class="decl"><span class="istickedoff">eye = (unit, unit)</span></span>
+<span class="lineno">  228 </span><span class="decl"><span class="nottickedoff">translateEye xyz (eye1, eye2)</span>
+<span class="lineno">  229 </span><span class="spaces">  </span><span class="nottickedoff">= (multMM m1 eye1, multMM eye2 m2)</span>
+<span class="lineno">  230 </span><span class="spaces">  </span><span class="nottickedoff">where (m1, m2) = transM xyz</span></span>
+<span class="lineno">  231 </span><span class="decl"><span class="nottickedoff">rotateEyeX t (eye1, eye2)</span>
+<span class="lineno">  232 </span><span class="spaces">  </span><span class="nottickedoff">= (multMM m1 eye1, multMM eye2 m2)</span>
+<span class="lineno">  233 </span><span class="spaces">  </span><span class="nottickedoff">where (m1, m2) = rotxM t</span></span>
+<span class="lineno">  234 </span><span class="decl"><span class="nottickedoff">rotateEyeY t (eye1, eye2)</span>
+<span class="lineno">  235 </span><span class="spaces">  </span><span class="nottickedoff">= (multMM m1 eye1, multMM eye2 m2)</span>
+<span class="lineno">  236 </span><span class="spaces">  </span><span class="nottickedoff">where (m1, m2) = rotyM t</span></span>
+<span class="lineno">  237 </span><span class="decl"><span class="nottickedoff">rotateEyeZ t (eye1, eye2)</span>
+<span class="lineno">  238 </span><span class="spaces">  </span><span class="nottickedoff">= (multMM m1 eye1, multMM eye2 m2)</span>
+<span class="lineno">  239 </span><span class="spaces">  </span><span class="nottickedoff">where (m1, m2) = rotzM t</span></span>
+<span class="lineno">  240 </span>
+<span class="lineno">  241 </span>-------------------
+<span class="lineno">  242 </span>-- Bounding boxes
+<span class="lineno">  243 </span>-------------------
 <span class="lineno">  244 </span>
-<span class="lineno">  245 </span>
-<span class="lineno">  246 </span>--multMM m1 m2 = [map (dot4 row) (transpose m2) | row &lt;- m1]
-<span class="lineno">  247 </span>
-<span class="lineno">  248 </span>--{-# INLINE multMV #-}
-<span class="lineno">  249 </span>multMV :: Matrix -&gt; Vector -&gt; Vector
-<span class="lineno">  250 </span><span class="decl"><span class="istickedoff">multMV m v = quad_to_vector (multMQ m (vector_to_quad v))</span></span>
-<span class="lineno">  251 </span>
-<span class="lineno">  252 </span>--{-# INLINE multMP #-}
-<span class="lineno">  253 </span>multMP :: Matrix -&gt; Point -&gt; Point
-<span class="lineno">  254 </span><span class="decl"><span class="istickedoff">multMP m p = quad_to_point (multMQ m (point_to_quad p))</span></span>
-<span class="lineno">  255 </span>
-<span class="lineno">  256 </span>-- mat vec = map (dot4 vec) mat
-<span class="lineno">  257 </span>
-<span class="lineno">  258 </span>{-# INLINE multMQ #-}
-<span class="lineno">  259 </span>multMQ :: Matrix -&gt; Quad -&gt; Quad
-<span class="lineno">  260 </span><span class="decl"><span class="istickedoff">multMQ (M q1 q2 q3 q4) q</span>
-<span class="lineno">  261 </span><span class="spaces">       </span><span class="istickedoff">= Q (dot4 q q1)</span>
-<span class="lineno">  262 </span><span class="spaces">           </span><span class="istickedoff">(dot4 q q2)</span>
-<span class="lineno">  263 </span><span class="spaces">           </span><span class="istickedoff">(dot4 q q3)</span>
-<span class="lineno">  264 </span><span class="spaces">           </span><span class="istickedoff">(dot4 q q4)</span></span>
-<span class="lineno">  265 </span>
-<span class="lineno">  266 </span>{-# INLINE multMR #-}
-<span class="lineno">  267 </span>multMR :: Matrix -&gt; Ray -&gt; Ray
-<span class="lineno">  268 </span><span class="decl"><span class="istickedoff">multMR m (r, v) = (multMP m r, multMV m v)</span></span>
-<span class="lineno">  269 </span>
-<span class="lineno">  270 </span>white :: Color
-<span class="lineno">  271 </span><span class="decl"><span class="nottickedoff">white = C 1 1 1</span></span>
-<span class="lineno">  272 </span>black :: Color
-<span class="lineno">  273 </span><span class="decl"><span class="istickedoff">black = C 0 0 0</span></span>
-<span class="lineno">  274 </span>
-<span class="lineno">  275 </span>addCC :: Color -&gt; Color -&gt; Color
-<span class="lineno">  276 </span><span class="decl"><span class="istickedoff">addCC (C a b c) (C d e f) = C (a+d) (b+e) (c+f)</span></span>
-<span class="lineno">  277 </span>
-<span class="lineno">  278 </span>subCC :: Color -&gt; Color -&gt; Color
-<span class="lineno">  279 </span><span class="decl"><span class="nottickedoff">subCC (C a b c) (C d e f) = C (a-d) (b-e) (c-f)</span></span>
-<span class="lineno">  280 </span>
-<span class="lineno">  281 </span>sumCC :: [Color] -&gt; Color
-<span class="lineno">  282 </span><span class="decl"><span class="istickedoff">sumCC = foldr addCC black</span></span>
-<span class="lineno">  283 </span>
-<span class="lineno">  284 </span>multCC :: Color -&gt; Color -&gt; Color
-<span class="lineno">  285 </span><span class="decl"><span class="istickedoff">multCC (C a b c) (C d e f) = C (a*d) (b*e) (c*f)</span></span>
-<span class="lineno">  286 </span>
-<span class="lineno">  287 </span>multSC :: Double -&gt; Color -&gt; Color
-<span class="lineno">  288 </span><span class="decl"><span class="istickedoff">multSC k       (C a b c) = C (a*k) (b*k) (c*k)</span></span>
-<span class="lineno">  289 </span>
-<span class="lineno">  290 </span>nearC :: Color -&gt; Color -&gt; Bool
-<span class="lineno">  291 </span><span class="decl"><span class="istickedoff">nearC (C a b c) (C d e f) = a `near` d &amp;&amp; b `near` e &amp;&amp; c `near` f</span></span>
-<span class="lineno">  292 </span>
-<span class="lineno">  293 </span>offsetToPoint :: Ray -&gt; Double -&gt; Point
-<span class="lineno">  294 </span><span class="decl"><span class="istickedoff">offsetToPoint (r,v) i = r `addPV` (i `multSV` v)</span></span>
-<span class="lineno">  295 </span>
-<span class="lineno">  296 </span>--
-<span class="lineno">  297 </span>
-<span class="lineno">  298 </span>epsilon, inf :: Double      -- aproximate zero and infinity
-<span class="lineno">  299 </span><span class="decl"><span class="istickedoff">epsilon = 1.0e-10</span></span>
-<span class="lineno">  300 </span><span class="decl"><span class="istickedoff">inf = 1.0e20</span></span>
-<span class="lineno">  301 </span>
-<span class="lineno">  302 </span>nonZero :: Double -&gt; Double         -- Use before a division. It makes definitions
-<span class="lineno">  303 </span><span class="decl"><span class="istickedoff">nonZero x | <span class="tickonlytrue">x &gt; epsilon</span>  = x        -- more complete and I bet the errors that get </span>
-<span class="lineno">  304 </span><span class="spaces">          </span><span class="istickedoff">| <span class="nottickedoff">x &lt; -epsilon</span> = <span class="nottickedoff">x</span>        -- introduced will be undetectable if epsilon</span>
-<span class="lineno">  305 </span><span class="spaces">          </span><span class="istickedoff">| <span class="nottickedoff">otherwise</span>    = <span class="nottickedoff">epsilon</span></span></span>  -- is small enough
-<span class="lineno">  306 </span>
-<span class="lineno">  307 </span>
-<span class="lineno">  308 </span><span class="decl"><span class="istickedoff">eqEps x y = abs (x-y) &lt; epsilon</span></span>
-<span class="lineno">  309 </span><span class="decl"><span class="istickedoff">near = eqEps</span></span>
-<span class="lineno">  310 </span>
-<span class="lineno">  311 </span>clampf :: Double -&gt; Double
-<span class="lineno">  312 </span><span class="decl"><span class="istickedoff">clampf p | <span class="tickonlyfalse">p &lt; 0</span> = <span class="nottickedoff">0</span></span>
-<span class="lineno">  313 </span><span class="spaces">         </span><span class="istickedoff">| p &gt; 1 = 1</span>
-<span class="lineno">  314 </span><span class="spaces">         </span><span class="istickedoff">| <span class="tickonlytrue">True</span>  = p</span></span>
+<span class="lineno">  245 </span><span class="decl"><span class="nottickedoff">mergeBox (B x11  x12  y11  y12  z11  z12) (B x21  x22  y21  y22  z21  z22) =</span>
+<span class="lineno">  246 </span><span class="spaces">    </span><span class="nottickedoff">B (x11 `min` x21) (x12 `max` x22)</span>
+<span class="lineno">  247 </span><span class="spaces">      </span><span class="nottickedoff">(y11 `min` y21) (y12 `max` y22)</span>
+<span class="lineno">  248 </span><span class="spaces">      </span><span class="nottickedoff">(z11 `min` z21) (z12 `max` z22)</span></span>
+<span class="lineno">  249 </span>
+<span class="lineno">  250 </span><span class="decl"><span class="istickedoff">transformBox t (B x1  x2  y1  y2  z1  z2)</span>
+<span class="lineno">  251 </span><span class="spaces">  </span><span class="istickedoff">= (B (foldr1 min (map xCoord pts'))</span>
+<span class="lineno">  252 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 max (map xCoord pts'))</span>
+<span class="lineno">  253 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 min (map yCoord pts'))</span>
+<span class="lineno">  254 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 max (map yCoord pts'))</span>
+<span class="lineno">  255 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 min (map zCoord pts'))</span>
+<span class="lineno">  256 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 max (map zCoord pts')))</span>
+<span class="lineno">  257 </span><span class="spaces">  </span><span class="istickedoff">where pts' = map (multMP t) pts</span>
+<span class="lineno">  258 </span><span class="spaces">        </span><span class="istickedoff">pts =  [point x1 y1 z1,</span>
+<span class="lineno">  259 </span><span class="spaces">                </span><span class="istickedoff">point x1 y1 z2,</span>
+<span class="lineno">  260 </span><span class="spaces">                </span><span class="istickedoff">point x1 y2 z1,</span>
+<span class="lineno">  261 </span><span class="spaces">                </span><span class="istickedoff">point x1 y2 z2,</span>
+<span class="lineno">  262 </span><span class="spaces">                </span><span class="istickedoff">point x2 y1 z1,</span>
+<span class="lineno">  263 </span><span class="spaces">                </span><span class="istickedoff">point x2 y1 z2,</span>
+<span class="lineno">  264 </span><span class="spaces">                </span><span class="istickedoff">point x2 y2 z1,</span>
+<span class="lineno">  265 </span><span class="spaces">                </span><span class="istickedoff">point x2 y2 z2]</span></span>
 
 </pre>
 </html>
@@ -2311,7 +2042,169 @@ span.spaces    { background: white }
 
 </pre>
 </html>
-Writing: Construct.hs.html
+Writing: Misc.hs.html
+<html><style type="text/css">
+span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
+span.nottickedoff { background: yellow}
+span.istickedoff { background: white }
+span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
+span.tickonlytrue  { margin: -1px; border: 1px solid #60de51; background: #60de51 }
+span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
+span.decl { font-weight: bold }
+span.spaces    { background: white }
+</style>
+<pre>
+<span class="lineno">    1 </span>-- Copyright (c) 2000 Galois Connections, Inc.
+<span class="lineno">    2 </span>-- All rights reserved.  This software is distributed as
+<span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
+<span class="lineno">    4 </span>-- which is included in the distribution.
+<span class="lineno">    5 </span>
+<span class="lineno">    6 </span>module Misc where
+<span class="lineno">    7 </span>
+<span class="lineno">    8 </span>import Debug.Trace
+<span class="lineno">    9 </span>
+<span class="lineno">   10 </span><span class="decl"><span class="nottickedoff">debug s v = trace (s ++&quot; : &quot;++ show v ++ &quot;\n&quot;) v</span></span>
+<span class="lineno">   11 </span>-- debug s v = v
+
+</pre>
+</html>
+Writing: Interval.hs.html
+<html><style type="text/css">
+span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
+span.nottickedoff { background: yellow}
+span.istickedoff { background: white }
+span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
+span.tickonlytrue  { margin: -1px; border: 1px solid #60de51; background: #60de51 }
+span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
+span.decl { font-weight: bold }
+span.spaces    { background: white }
+</style>
+<pre>
+<span class="lineno">    1 </span>-- Copyright (c) 2000 Galois Connections, Inc.
+<span class="lineno">    2 </span>-- All rights reserved.  This software is distributed as
+<span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
+<span class="lineno">    4 </span>-- which is included in the distribution.
+<span class="lineno">    5 </span>
+<span class="lineno">    6 </span>module Interval
+<span class="lineno">    7 </span>    ( IList
+<span class="lineno">    8 </span>    , Intersection
+<span class="lineno">    9 </span>    , emptyIList, openIList
+<span class="lineno">   10 </span>    , mkEntry, mkExit
+<span class="lineno">   11 </span>    , entryexit, exitentry
+<span class="lineno">   12 </span>    , mapI
+<span class="lineno">   13 </span>    , unionIntervals, intersectIntervals, differenceIntervals
+<span class="lineno">   14 </span>    , complementIntervals
+<span class="lineno">   15 </span>    ) where
+<span class="lineno">   16 </span>
+<span class="lineno">   17 </span>import Geometry
+<span class="lineno">   18 </span>
+<span class="lineno">   19 </span>-- The result of a ray trace is represented as a list of surface
+<span class="lineno">   20 </span>-- intersections.  Each intersection is a point along the ray with
+<span class="lineno">   21 </span>-- a flag indicating whether this intersection is an entry or an
+<span class="lineno">   22 </span>-- exit from the solid.  Each intersection also carries unspecified
+<span class="lineno">   23 </span>-- surface data for use by the illumination model.
+<span class="lineno">   24 </span>
+<span class="lineno">   25 </span>-- Just the list of intersections isn't enough, however.  An empty
+<span class="lineno">   26 </span>-- list can denote either a trace that is always within the solid
+<span class="lineno">   27 </span>-- or never in the solid.  To dissambiguate, an extra flag is kept
+<span class="lineno">   28 </span>-- that indicates whether we are starting inside or outside of the
+<span class="lineno">   29 </span>-- solid.  As a convenience, we also keep an additional flag that
+<span class="lineno">   30 </span>-- indicates whether the last intersection ends inside or outside.
+<span class="lineno">   31 </span>
+<span class="lineno">   32 </span>type IList a       = (Bool, [Intersection a], Bool)
+<span class="lineno">   33 </span>type Intersection a     = (Double, Bool, a)
+<span class="lineno">   34 </span>
+<span class="lineno">   35 </span><span class="decl"><span class="istickedoff">emptyIList = (False, [], False)</span></span>
+<span class="lineno">   36 </span><span class="decl"><span class="nottickedoff">openIList = (True, [], True)</span></span>
+<span class="lineno">   37 </span>
+<span class="lineno">   38 </span><span class="decl"><span class="istickedoff">mapI f (b1, is, b2) = (b1, map f is, b2)</span></span>
+<span class="lineno">   39 </span>
+<span class="lineno">   40 </span><span class="decl"><span class="istickedoff">isEntry (_, entry, _) = entry</span></span>
+<span class="lineno">   41 </span><span class="decl"><span class="nottickedoff">isExit  (_, entry, _) = not entry</span></span>
+<span class="lineno">   42 </span>
+<span class="lineno">   43 </span><span class="decl"><span class="istickedoff">mkEntry (t, a) = (t, True,  a)</span></span>
+<span class="lineno">   44 </span><span class="decl"><span class="istickedoff">mkExit  (t, a) = (t, False, a)</span></span>
+<span class="lineno">   45 </span>
+<span class="lineno">   46 </span><span class="decl"><span class="istickedoff">entryexit w1 w2 = (False, [mkEntry w1, mkExit w2], False)</span></span>
+<span class="lineno">   47 </span><span class="decl"><span class="nottickedoff">exitentry w1 w2 = (True, [mkExit w1, mkEntry w2], True)</span></span>
+<span class="lineno">   48 </span><span class="decl"><span class="nottickedoff">arrange   w1@(t1, _) w2@(t2, _) | t1 &lt; t2   = entryexit w1 w2</span>
+<span class="lineno">   49 </span><span class="spaces">                                </span><span class="nottickedoff">| otherwise = entryexit w2 w1</span></span>
+<span class="lineno">   50 </span>
+<span class="lineno">   51 </span>
+<span class="lineno">   52 </span>cmpI :: Intersection a -&gt; Intersection a -&gt; Ordering
+<span class="lineno">   53 </span><span class="decl"><span class="istickedoff">cmpI (i, _, _) (j, _, _)</span>
+<span class="lineno">   54 </span><span class="spaces">  </span><span class="istickedoff">| <span class="tickonlyfalse">i `near` j</span> = <span class="nottickedoff">EQ</span></span>
+<span class="lineno">   55 </span><span class="spaces">  </span><span class="istickedoff">| i   &lt;    j = LT</span>
+<span class="lineno">   56 </span><span class="spaces">  </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span>  = GT</span></span>
+<span class="lineno">   57 </span>
+<span class="lineno">   58 </span><span class="decl"><span class="nottickedoff">bad (b1, [], b2) = b1 /= b2</span>
+<span class="lineno">   59 </span><span class="spaces"></span><span class="nottickedoff">bad (b1, is, b2) = bad' b1 is || b2 /= b3</span>
+<span class="lineno">   60 </span><span class="spaces">  </span><span class="nottickedoff">where (_, b3, _) = last is</span></span>
+<span class="lineno">   61 </span>
+<span class="lineno">   62 </span><span class="decl"><span class="nottickedoff">bad' b [] = False</span>
+<span class="lineno">   63 </span><span class="spaces"></span><span class="nottickedoff">bad' b ((_, c, _) : is) = b == c || bad' c is</span></span>
+<span class="lineno">   64 </span>
+<span class="lineno">   65 </span>unionIntervals :: IList a -&gt; IList a -&gt; IList a
+<span class="lineno">   66 </span><span class="decl"><span class="istickedoff">unionIntervals (isStartOpen, is, isEndOpen) (jsStartOpen, js, jsEndOpen)</span>
+<span class="lineno">   67 </span><span class="spaces">  </span><span class="istickedoff">= (isStartOpen || jsStartOpen, uniIntervals is js, isEndOpen || jsEndOpen)</span>
+<span class="lineno">   68 </span><span class="spaces">  </span><span class="istickedoff">where uniIntervals is [] | <span class="tickonlyfalse">jsEndOpen</span> = <span class="nottickedoff">[]</span></span>
+<span class="lineno">   69 </span><span class="spaces">                           </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span> = is</span>
+<span class="lineno">   70 </span><span class="spaces">        </span><span class="istickedoff">uniIntervals [] js | <span class="tickonlyfalse">isEndOpen</span> = <span class="nottickedoff">[]</span></span>
+<span class="lineno">   71 </span><span class="spaces">                           </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span> = js</span>
+<span class="lineno">   72 </span><span class="spaces">        </span><span class="istickedoff">uniIntervals is@(i : is') js@(j : js')</span>
+<span class="lineno">   73 </span><span class="spaces">          </span><span class="istickedoff">= case cmpI i j of</span>
+<span class="lineno">   74 </span><span class="spaces">            </span><span class="istickedoff">EQ -&gt; <span class="nottickedoff">if isEntry i == isEntry j then i : uniIntervals is' js'</span></span>
+<span class="lineno">   75 </span><span class="spaces">                                            </span><span class="istickedoff"><span class="nottickedoff">else uniIntervals is' js'</span></span>
+<span class="lineno">   76 </span><span class="spaces">            </span><span class="istickedoff">LT -&gt; if <span class="tickonlytrue">isEntry j</span> then i : <span class="nottickedoff">uniIntervals is' js</span></span>
+<span class="lineno">   77 </span><span class="spaces">                               </span><span class="istickedoff">else     <span class="nottickedoff">uniIntervals is' js</span></span>
+<span class="lineno">   78 </span><span class="spaces">            </span><span class="istickedoff">GT -&gt; if <span class="tickonlytrue">isEntry i</span> then j : uniIntervals is js'</span>
+<span class="lineno">   79 </span><span class="spaces">                               </span><span class="istickedoff">else     <span class="nottickedoff">uniIntervals is js'</span></span></span>
+<span class="lineno">   80 </span>
+<span class="lineno">   81 </span>intersectIntervals :: IList a -&gt; IList a -&gt; IList a
+<span class="lineno">   82 </span><span class="decl"><span class="nottickedoff">intersectIntervals is js</span>
+<span class="lineno">   83 </span><span class="spaces">  </span><span class="nottickedoff">= complementIntervals (unionIntervals is' js')</span>
+<span class="lineno">   84 </span><span class="spaces">  </span><span class="nottickedoff">where is' = complementIntervals is</span>
+<span class="lineno">   85 </span><span class="spaces">        </span><span class="nottickedoff">js' = complementIntervals js</span></span>
+<span class="lineno">   86 </span>
+<span class="lineno">   87 </span>differenceIntervals :: IList a -&gt; IList a -&gt; IList a
+<span class="lineno">   88 </span><span class="decl"><span class="nottickedoff">differenceIntervals is js</span>
+<span class="lineno">   89 </span><span class="spaces">  </span><span class="nottickedoff">= complementIntervals (unionIntervals is' js)</span>
+<span class="lineno">   90 </span><span class="spaces">  </span><span class="nottickedoff">where is' = complementIntervals is</span></span>
+<span class="lineno">   91 </span>
+<span class="lineno">   92 </span>complementIntervals :: IList a -&gt; IList a
+<span class="lineno">   93 </span><span class="decl"><span class="nottickedoff">complementIntervals (o1, is, o2)</span>
+<span class="lineno">   94 </span><span class="spaces">  </span><span class="nottickedoff">= (not o1, [ (i, not isentry, a) | (i, isentry, a) &lt;- is ], not o2)</span></span>
+<span class="lineno">   95 </span>
+<span class="lineno">   96 </span>-- tests...
+<span class="lineno">   97 </span>
+<span class="lineno">   98 </span>{-
+<span class="lineno">   99 </span>mkIn, mkOut :: Double -&gt; Intersection a
+<span class="lineno">  100 </span>mkIn x = (x, True, undefined)
+<span class="lineno">  101 </span>mkOut x = (x, False, undefined)
+<span class="lineno">  102 </span>
+<span class="lineno">  103 </span>i1 =  (False, [ mkIn 2, mkOut 7 ], False)
+<span class="lineno">  104 </span>i1' = (True, [ mkOut 2, mkIn 7 ], True)
+<span class="lineno">  105 </span>i2 =  (False, [ mkIn 1, mkOut 3, mkIn 4, mkOut 5, mkIn 6, mkOut 8 ], False)
+<span class="lineno">  106 </span>
+<span class="lineno">  107 </span>t1 = unionIntervals i1 i2
+<span class="lineno">  108 </span>t2 = intersectIntervals i1 i2
+<span class="lineno">  109 </span>t3 = intersectIntervals i2 i1
+<span class="lineno">  110 </span>t4 = complementIntervals i1
+<span class="lineno">  111 </span>t5 = intersectIntervals i2 i1'
+<span class="lineno">  112 </span>t6 = differenceIntervals i2 i1
+<span class="lineno">  113 </span>t7 = differenceIntervals i2 i2
+<span class="lineno">  114 </span>
+<span class="lineno">  115 </span>sh (o1,is,o2) =
+<span class="lineno">  116 </span>    do  if o1 then putStr &quot;...&quot; else return ()
+<span class="lineno">  117 </span>        putStr $ foldr1 (++) (map si is)
+<span class="lineno">  118 </span>        if o2 then putStr &quot;...&quot; else return ()
+<span class="lineno">  119 </span>si (i, True, _, _) = &quot;&lt;&quot; ++ show i
+<span class="lineno">  120 </span>si (i, False, _, _) = &quot; &quot; ++ show i ++ &quot;&gt;&quot;
+<span class="lineno">  121 </span>-}
+
+</pre>
+</html>
+Writing: Surface.hs.html
 <html><style type="text/css">
 span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
 span.nottickedoff { background: yellow}
@@ -2328,270 +2221,159 @@ span.spaces    { background: white }
 <span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
 <span class="lineno">    4 </span>-- which is included in the distribution.
 <span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Construct
-<span class="lineno">    7 </span>    ( Surface (..)
-<span class="lineno">    8 </span>    , Face (..)
-<span class="lineno">    9 </span>    , CSG (..)
-<span class="lineno">   10 </span>    , Texture
-<span class="lineno">   11 </span>    , Transform
-<span class="lineno">   12 </span>    , union, intersect, difference
-<span class="lineno">   13 </span>    , plane, sphere, cube, cylinder, cone
-<span class="lineno">   14 </span>    , transform
-<span class="lineno">   15 </span>    , translate, translateX, translateY, translateZ
-<span class="lineno">   16 </span>    , scale, scaleX, scaleY, scaleZ, uscale
-<span class="lineno">   17 </span>    , rotateX, rotateY, rotateZ
-<span class="lineno">   18 </span>    , eye, translateEye
-<span class="lineno">   19 </span>    , rotateEyeX, rotateEyeY, rotateEyeZ
-<span class="lineno">   20 </span>    ) where
-<span class="lineno">   21 </span>
-<span class="lineno">   22 </span>import Geometry
+<span class="lineno">    6 </span>module Surface
+<span class="lineno">    7 </span>    ( SurfaceFn (..)
+<span class="lineno">    8 </span>    , Properties
+<span class="lineno">    9 </span>    , sfun, sconst
+<span class="lineno">   10 </span>    , prop
+<span class="lineno">   11 </span>    , matte, shiny
+<span class="lineno">   12 </span>    , chgColor
+<span class="lineno">   13 </span>    , surface
+<span class="lineno">   14 </span>    ) where
+<span class="lineno">   15 </span>
+<span class="lineno">   16 </span>import Geometry
+<span class="lineno">   17 </span>import CSG
+<span class="lineno">   18 </span>import Misc
+<span class="lineno">   19 </span>
+<span class="lineno">   20 </span>-- the surface gets passed face then u then v.
+<span class="lineno">   21 </span>data SurfaceFn c v = SFun (Int -&gt; Double -&gt; Double -&gt; Properties c v)
+<span class="lineno">   22 </span>                   | SConst (Properties c v)
 <span class="lineno">   23 </span>
-<span class="lineno">   24 </span>-- In each case, we model the surface by a point and a pair of tangent vectors.
-<span class="lineno">   25 </span>-- This gives us enough information to determine the surface
-<span class="lineno">   26 </span>-- normal at that point, which is all that is required by the current
-<span class="lineno">   27 </span>-- illumination model.  We can't just save the surface normal because
-<span class="lineno">   28 </span>-- that isn't preserved by transformations.
-<span class="lineno">   29 </span>
-<span class="lineno">   30 </span>data Surface
-<span class="lineno">   31 </span>  = Planar Point Vector Vector
-<span class="lineno">   32 </span>  | Spherical Point Vector Vector
-<span class="lineno">   33 </span>  | Cylindrical Point Vector Vector
-<span class="lineno">   34 </span>  | Conic Point Vector Vector
-<span class="lineno">   35 </span>  deriving <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>
-<span class="lineno">   36 </span>
-<span class="lineno">   37 </span>data Face
-<span class="lineno">   38 </span>  = PlaneFace
-<span class="lineno">   39 </span>  | SphereFace
-<span class="lineno">   40 </span>  | CubeFront
-<span class="lineno">   41 </span>  | CubeBack
-<span class="lineno">   42 </span>  | CubeLeft
-<span class="lineno">   43 </span>  | CubeRight
-<span class="lineno">   44 </span>  | CubeTop
-<span class="lineno">   45 </span>  | CubeBottom
-<span class="lineno">   46 </span>  | CylinderSide
-<span class="lineno">   47 </span>  | CylinderTop
-<span class="lineno">   48 </span>  | CylinderBottom
-<span class="lineno">   49 </span>  | ConeSide
-<span class="lineno">   50 </span>  | ConeBase
-<span class="lineno">   51 </span>  deriving <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>
-<span class="lineno">   52 </span>
-<span class="lineno">   53 </span>data CSG a
-<span class="lineno">   54 </span>  = Plane a
-<span class="lineno">   55 </span>  | Sphere a
-<span class="lineno">   56 </span>  | Cylinder a
-<span class="lineno">   57 </span>  | Cube a
-<span class="lineno">   58 </span>  | Cone a
-<span class="lineno">   59 </span>  | Transform Matrix Matrix (CSG a)
-<span class="lineno">   60 </span>  | Union (CSG a) (CSG a)
-<span class="lineno">   61 </span>  | Intersect (CSG a) (CSG a)
-<span class="lineno">   62 </span>  | Difference (CSG a) (CSG a)
-<span class="lineno">   63 </span>  | Box Box (CSG a)
-<span class="lineno">   64 </span>  deriving (<span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>)
-<span class="lineno">   65 </span>
-<span class="lineno">   66 </span>-- the data returned for determining surface texture
-<span class="lineno">   67 </span>-- the Face tells which face of a primitive this is
-<span class="lineno">   68 </span>-- the Point is the point of intersection in object coordinates
-<span class="lineno">   69 </span>-- the a is application-specific texture information
-<span class="lineno">   70 </span>type Texture a = (Face, Point, a)
-<span class="lineno">   71 </span>
-<span class="lineno">   72 </span>union, intersect, difference       :: CSG a -&gt; CSG a -&gt; CSG a
-<span class="lineno">   73 </span>
-<span class="lineno">   74 </span><span class="decl"><span class="istickedoff">union p@(Box b1 _) q@(Box b2 _) = <span class="nottickedoff">Box (mergeBox b1 b2) (Union p q)</span></span>
-<span class="lineno">   75 </span><span class="spaces"></span><span class="istickedoff">union p q = Union p q</span></span>
-<span class="lineno">   76 </span>
-<span class="lineno">   77 </span>-- rather pessimistic
-<span class="lineno">   78 </span><span class="decl"><span class="nottickedoff">intersect p@(Box b1 _) q@(Box b2 _) = Box (mergeBox b1 b2) (Intersect p q)</span>
-<span class="lineno">   79 </span><span class="spaces"></span><span class="nottickedoff">intersect p q = Intersect p q</span></span>
-<span class="lineno">   80 </span>
-<span class="lineno">   81 </span><span class="decl"><span class="nottickedoff">difference (Box b1 p) q = Box b1 (Difference p q)</span>
-<span class="lineno">   82 </span><span class="spaces"></span><span class="nottickedoff">-- no need to box again inside</span>
-<span class="lineno">   83 </span><span class="spaces"></span><span class="nottickedoff">-- difference p@(Box b1 _) q = Box b1 (Difference p q)</span>
-<span class="lineno">   84 </span><span class="spaces"></span><span class="nottickedoff">difference p q = Difference p q</span></span>
-<span class="lineno">   85 </span>
-<span class="lineno">   86 </span><span class="decl"><span class="istickedoff">mkBox b p = Box b p</span></span>
-<span class="lineno">   87 </span>
-<span class="lineno">   88 </span>plane, sphere, cube, cylinder, cone     :: a -&gt; CSG a
-<span class="lineno">   89 </span>
-<span class="lineno">   90 </span><span class="decl"><span class="istickedoff">plane = Plane</span></span>
-<span class="lineno">   91 </span><span class="decl"><span class="nottickedoff">sphere s =</span>
-<span class="lineno">   92 </span><span class="spaces">    </span><span class="nottickedoff">mkBox (B (-1 - epsilon) (1 + epsilon)</span>
-<span class="lineno">   93 </span><span class="spaces">             </span><span class="nottickedoff">(-1 - epsilon) (1 + epsilon)</span>
-<span class="lineno">   94 </span><span class="spaces">             </span><span class="nottickedoff">(-1 - epsilon) (1 + epsilon)) (Sphere s)</span></span>
-<span class="lineno">   95 </span><span class="decl"><span class="nottickedoff">cone s =</span>
-<span class="lineno">   96 </span><span class="spaces">    </span><span class="nottickedoff">mkBox (B (-1 - epsilon) (1 + epsilon)</span>
-<span class="lineno">   97 </span><span class="spaces">             </span><span class="nottickedoff">(   - epsilon) (1 + epsilon)</span>
-<span class="lineno">   98 </span><span class="spaces">             </span><span class="nottickedoff">(-1 - epsilon) (1 + epsilon)) (Cone s)</span></span>
-<span class="lineno">   99 </span><span class="decl"><span class="istickedoff">cube s =</span>
-<span class="lineno">  100 </span><span class="spaces">    </span><span class="istickedoff">mkBox (B (- epsilon) (1 + epsilon)</span>
-<span class="lineno">  101 </span><span class="spaces">             </span><span class="istickedoff">(- epsilon) (1 + epsilon)</span>
-<span class="lineno">  102 </span><span class="spaces">             </span><span class="istickedoff">(- epsilon) (1 + epsilon)) (Cube s)</span></span>
-<span class="lineno">  103 </span><span class="decl"><span class="nottickedoff">cylinder s =</span>
-<span class="lineno">  104 </span><span class="spaces">    </span><span class="nottickedoff">mkBox (B (-1 - epsilon) (1 + epsilon)</span>
-<span class="lineno">  105 </span><span class="spaces">             </span><span class="nottickedoff">(   - epsilon) (1 + epsilon)</span>
-<span class="lineno">  106 </span><span class="spaces">             </span><span class="nottickedoff">(-1 - epsilon) (1 + epsilon)) (Cylinder s)</span></span>
-<span class="lineno">  107 </span>
-<span class="lineno">  108 </span>----------------------------
-<span class="lineno">  109 </span>-- Object transformations
-<span class="lineno">  110 </span>----------------------------
+<span class="lineno">   24 </span>sfun :: (Int -&gt; Double -&gt; Double -&gt; Properties c v) -&gt; SurfaceFn c v
+<span class="lineno">   25 </span><span class="decl"><span class="nottickedoff">sfun = SFun</span></span>
+<span class="lineno">   26 </span>sconst :: Properties c v -&gt; SurfaceFn c v
+<span class="lineno">   27 </span><span class="decl"><span class="nottickedoff">sconst = SConst</span></span>
+<span class="lineno">   28 </span>
+<span class="lineno">   29 </span>type Properties c v = (c, v, v, v)
+<span class="lineno">   30 </span>
+<span class="lineno">   31 </span><span class="decl"><span class="istickedoff">prop c d s p = (c, d, s, p)</span></span>
+<span class="lineno">   32 </span>
+<span class="lineno">   33 </span><span class="decl"><span class="nottickedoff">matte = (white, 1.0, 0.0, 1.0)</span></span>
+<span class="lineno">   34 </span><span class="decl"><span class="nottickedoff">shiny = (white, 0.0, 1.0, 1.0)</span></span>
+<span class="lineno">   35 </span>
+<span class="lineno">   36 </span>chgColor :: c -&gt; Properties d v -&gt; Properties c v
+<span class="lineno">   37 </span><span class="decl"><span class="nottickedoff">chgColor c (_, d, s, p) = (c, d, s, p)</span></span>
+<span class="lineno">   38 </span>
+<span class="lineno">   39 </span>instance (Show c, Show v) =&gt; Show (SurfaceFn c v) where
+<span class="lineno">   40 </span>  <span class="decl"><span class="nottickedoff">show (SFun _)   = &quot;Surface function&quot;</span>
+<span class="lineno">   41 </span><span class="spaces">  </span><span class="nottickedoff">-- show (SConst p) = &quot;Surface constant: &quot; ++ show p</span>
+<span class="lineno">   42 </span><span class="spaces">  </span><span class="nottickedoff">show (SConst p) = &quot;Surface constant&quot;</span></span>
+<span class="lineno">   43 </span>
+<span class="lineno">   44 </span>evalSurface :: SurfaceFn Color Double -&gt; Int -&gt; Double -&gt; Double -&gt; Properties Color Double
+<span class="lineno">   45 </span><span class="decl"><span class="istickedoff">evalSurface (SConst p) = <span class="nottickedoff">\_ _ _ -&gt; p</span></span>
+<span class="lineno">   46 </span><span class="spaces"></span><span class="istickedoff">evalSurface (SFun f)   = f</span></span>
+<span class="lineno">   47 </span>
+<span class="lineno">   48 </span>-- calculate surface properties, given the type of
+<span class="lineno">   49 </span>-- surface, and intersection point in object coordinates
+<span class="lineno">   50 </span>
+<span class="lineno">   51 </span>-- surface :: Surface SurfaceFn -&gt; (Int, Point) -&gt; (Vector, Properties)
+<span class="lineno">   52 </span>
+<span class="lineno">   53 </span><span class="decl"><span class="istickedoff">surface (Planar _ v0 v1) (n, p0, fn)</span>
+<span class="lineno">   54 </span><span class="spaces">  </span><span class="istickedoff">= (norm, evalSurface fn <span class="nottickedoff">n'</span> u v)</span>
+<span class="lineno">   55 </span><span class="spaces">  </span><span class="istickedoff">where norm = normalize $ cross v0 v1</span>
+<span class="lineno">   56 </span><span class="spaces">        </span><span class="istickedoff">(n', u, v) = planarUV n p0</span>
+<span class="lineno">   57 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">   58 </span><span class="spaces"></span><span class="istickedoff">surface (Spherical _ v0 v1) (_, p0, fn)</span>
+<span class="lineno">   59 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">(norm, evalSurface fn 0 u v)</span></span>
+<span class="lineno">   60 </span><span class="spaces">  </span><span class="istickedoff">where <span class="nottickedoff">x = xCoord p0</span></span>
+<span class="lineno">   61 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">y = yCoord p0</span></span>
+<span class="lineno">   62 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">z = zCoord p0</span></span>
+<span class="lineno">   63 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">k = sqrt (1 - sq y)</span></span>
+<span class="lineno">   64 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">theta = adjustRadian (atan2 (x / k) (z / k))</span></span>
+<span class="lineno">   65 </span><span class="spaces">        </span><span class="istickedoff">-- correct so that the image grows left-to-right</span>
+<span class="lineno">   66 </span><span class="spaces">        </span><span class="istickedoff">-- instead of right-to-left</span>
+<span class="lineno">   67 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">u = 1.0 - clampf (theta / (2 * pi))</span></span>
+<span class="lineno">   68 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">v =       clampf ((y + 1) / 2)</span></span>
+<span class="lineno">   69 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">norm = normalize $ cross v0 v1</span></span>
+<span class="lineno">   70 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">   71 </span><span class="spaces"></span><span class="istickedoff">-- ZZ ignore the (incorrect) surface model, and estimate the normal</span>
+<span class="lineno">   72 </span><span class="spaces"></span><span class="istickedoff">-- from the intersection in object space</span>
+<span class="lineno">   73 </span><span class="spaces"></span><span class="istickedoff">surface (Cylindrical _ v0 v1) (_, p0, fn)</span>
+<span class="lineno">   74 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">(norm, evalSurface fn 0 u v)</span></span>
+<span class="lineno">   75 </span><span class="spaces">  </span><span class="istickedoff">where <span class="nottickedoff">x = xCoord p0</span></span>
+<span class="lineno">   76 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">y = yCoord p0</span></span>
+<span class="lineno">   77 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">z = zCoord p0</span></span>
+<span class="lineno">   78 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">u = clampf $ adjustRadian (atan2 x z) / (2 * pi)</span></span>
+<span class="lineno">   79 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">v = y</span></span>
+<span class="lineno">   80 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">norm = normalize $ cross v0 v1</span></span>
+<span class="lineno">   81 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">   82 </span><span class="spaces"></span><span class="istickedoff">-- ZZ ignore the (incorrect) surface model, and estimate the normal</span>
+<span class="lineno">   83 </span><span class="spaces"></span><span class="istickedoff">-- from the intersection in object space</span>
+<span class="lineno">   84 </span><span class="spaces"></span><span class="istickedoff">surface (Conic _ v0 v1) (_, p0, fn)</span>
+<span class="lineno">   85 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">(norm, evalSurface fn 0 u v)</span></span>
+<span class="lineno">   86 </span><span class="spaces">  </span><span class="istickedoff">where <span class="nottickedoff">x = xCoord p0</span></span>
+<span class="lineno">   87 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">y = yCoord p0</span></span>
+<span class="lineno">   88 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">z = zCoord p0</span></span>
+<span class="lineno">   89 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">u = clampf $ adjustRadian (atan2 (x / y) (z / y)) / (2 * pi)</span></span>
+<span class="lineno">   90 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">v = y</span></span>
+<span class="lineno">   91 </span><span class="spaces">        </span><span class="istickedoff"><span class="nottickedoff">norm = normalize $ cross v0 v1</span></span></span>
+<span class="lineno">   92 </span>
+<span class="lineno">   93 </span><span class="decl"><span class="istickedoff">planarUV face p0</span>
+<span class="lineno">   94 </span><span class="spaces">  </span><span class="istickedoff">= case face of</span>
+<span class="lineno">   95 </span><span class="spaces">    </span><span class="istickedoff">PlaneFace      -&gt; (<span class="nottickedoff">0</span>, x, z)</span>
+<span class="lineno">   96 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">   97 </span><span class="spaces">    </span><span class="istickedoff">CubeFront      -&gt; (<span class="nottickedoff">0</span>, x, y)</span>
+<span class="lineno">   98 </span><span class="spaces">    </span><span class="istickedoff">CubeBack       -&gt; <span class="nottickedoff">(1, x, y)</span></span>
+<span class="lineno">   99 </span><span class="spaces">    </span><span class="istickedoff">CubeLeft       -&gt; (<span class="nottickedoff">2</span>, z, y)</span>
+<span class="lineno">  100 </span><span class="spaces">    </span><span class="istickedoff">CubeRight      -&gt; <span class="nottickedoff">(3, z, y)</span></span>
+<span class="lineno">  101 </span><span class="spaces">    </span><span class="istickedoff">CubeTop        -&gt; (<span class="nottickedoff">4</span>, x, z)</span>
+<span class="lineno">  102 </span><span class="spaces">    </span><span class="istickedoff">CubeBottom     -&gt; (<span class="nottickedoff">5</span>, x, z)</span>
+<span class="lineno">  103 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  104 </span><span class="spaces">    </span><span class="istickedoff">CylinderTop    -&gt; <span class="nottickedoff">(1, (x + 1) / 2, (z + 1) / 2)</span></span>
+<span class="lineno">  105 </span><span class="spaces">    </span><span class="istickedoff">CylinderBottom -&gt; <span class="nottickedoff">(2, (x + 1) / 2, (z + 1) / 2)</span></span>
+<span class="lineno">  106 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  107 </span><span class="spaces">    </span><span class="istickedoff">ConeBase       -&gt; <span class="nottickedoff">(1, (x + 1) / 2, (z + 1) / 2)</span></span>
+<span class="lineno">  108 </span><span class="spaces">  </span><span class="istickedoff">where x = xCoord p0</span>
+<span class="lineno">  109 </span><span class="spaces">        </span><span class="istickedoff">y = yCoord p0</span>
+<span class="lineno">  110 </span><span class="spaces">        </span><span class="istickedoff">z = zCoord p0</span></span>
 <span class="lineno">  111 </span>
-<span class="lineno">  112 </span>type Transform = (Matrix, Matrix)
+<span class="lineno">  112 </span>-- misc
 <span class="lineno">  113 </span>
-<span class="lineno">  114 </span>transform :: Transform -&gt; CSG a -&gt; CSG a
-<span class="lineno">  115 </span>
-<span class="lineno">  116 </span><span class="decl"><span class="istickedoff">transform (m, m')   (Transform mp mp' p) = Transform  (multMM m mp)       (multMM mp' m') p</span>
-<span class="lineno">  117 </span><span class="spaces"></span><span class="istickedoff">transform mm'       (Union p q)          = Union      (transform mm' p)   (transform mm' q)</span>
-<span class="lineno">  118 </span><span class="spaces"></span><span class="istickedoff">transform mm'       (Intersect p q)      = <span class="nottickedoff">Intersect  (transform mm' p)   (transform mm' q)</span></span>
-<span class="lineno">  119 </span><span class="spaces"></span><span class="istickedoff">transform mm'       (Difference p q)     = <span class="nottickedoff">Difference (transform mm' p)   (transform mm' q)</span></span>
-<span class="lineno">  120 </span><span class="spaces"></span><span class="istickedoff">transform mm'@(m,_) (Box box p)          = Box        (transformBox m box) (transform mm' p)</span>
-<span class="lineno">  121 </span><span class="spaces"></span><span class="istickedoff">transform (m, m')   prim                 = Transform  m m' prim</span></span>
-<span class="lineno">  122 </span>
-<span class="lineno">  123 </span>translate                      :: Coords -&gt; CSG a -&gt; CSG a
-<span class="lineno">  124 </span>translateX, translateY, translateZ      :: Double -&gt; CSG a -&gt; CSG a
-<span class="lineno">  125 </span>
-<span class="lineno">  126 </span><span class="decl"><span class="istickedoff">translate xyz = transform $ transM xyz</span></span>
-<span class="lineno">  127 </span><span class="decl"><span class="nottickedoff">translateX x = translate (x, 0, 0)</span></span>
-<span class="lineno">  128 </span><span class="decl"><span class="nottickedoff">translateY y = translate (0, y, 0)</span></span>
-<span class="lineno">  129 </span><span class="decl"><span class="nottickedoff">translateZ z = translate (0, 0, z)</span></span>
-<span class="lineno">  130 </span>
-<span class="lineno">  131 </span>scale                    :: Coords -&gt; CSG a -&gt; CSG a
-<span class="lineno">  132 </span>scaleX, scaleY, scaleZ, uscale   :: Double -&gt; CSG a -&gt; CSG a
-<span class="lineno">  133 </span>
-<span class="lineno">  134 </span><span class="decl"><span class="istickedoff">scale xyz = transform $ scaleM xyz</span></span>
-<span class="lineno">  135 </span><span class="decl"><span class="nottickedoff">scaleX x = scale (x, 1, 1)</span></span>
-<span class="lineno">  136 </span><span class="decl"><span class="nottickedoff">scaleY y = scale (1, y, 1)</span></span>
-<span class="lineno">  137 </span><span class="decl"><span class="nottickedoff">scaleZ z = scale (1, 1, z)</span></span>
-<span class="lineno">  138 </span><span class="decl"><span class="istickedoff">uscale u = scale (u,u,u)</span></span>
-<span class="lineno">  139 </span>
-<span class="lineno">  140 </span>rotateX, rotateY, rotateZ             :: Radian -&gt; CSG a -&gt; CSG a
-<span class="lineno">  141 </span>
-<span class="lineno">  142 </span><span class="decl"><span class="istickedoff">rotateX a = transform $ rotxM a</span></span>
-<span class="lineno">  143 </span><span class="decl"><span class="istickedoff">rotateY a = transform $ rotyM a</span></span>
-<span class="lineno">  144 </span><span class="decl"><span class="nottickedoff">rotateZ a = transform $ rotzM a</span></span>
-<span class="lineno">  145 </span>
-<span class="lineno">  146 </span><span class="decl"><span class="istickedoff">unit = matrix</span>
-<span class="lineno">  147 </span><span class="spaces">      </span><span class="istickedoff">( ( 1.0, 0.0, 0.0, 0.0 ),</span>
-<span class="lineno">  148 </span><span class="spaces">        </span><span class="istickedoff">( 0.0, 1.0, 0.0, 0.0 ),</span>
-<span class="lineno">  149 </span><span class="spaces">        </span><span class="istickedoff">( 0.0, 0.0, 1.0, 0.0 ),</span>
-<span class="lineno">  150 </span><span class="spaces">        </span><span class="istickedoff">( 0.0, 0.0, 0.0, 1.0 ) )</span></span>
-<span class="lineno">  151 </span>
-<span class="lineno">  152 </span><span class="decl"><span class="istickedoff">transM (x, y, z)</span>
-<span class="lineno">  153 </span><span class="spaces">  </span><span class="istickedoff">= ( matrix</span>
-<span class="lineno">  154 </span><span class="spaces">      </span><span class="istickedoff">( ( 1, 0, 0, x ),</span>
-<span class="lineno">  155 </span><span class="spaces">        </span><span class="istickedoff">( 0, 1, 0, y ),</span>
-<span class="lineno">  156 </span><span class="spaces">        </span><span class="istickedoff">( 0, 0, 1, z ),</span>
-<span class="lineno">  157 </span><span class="spaces">        </span><span class="istickedoff">( 0, 0, 0, 1 ) ),</span>
-<span class="lineno">  158 </span><span class="spaces">      </span><span class="istickedoff">matrix</span>
-<span class="lineno">  159 </span><span class="spaces">      </span><span class="istickedoff">( ( 1, 0, 0, -x ),</span>
-<span class="lineno">  160 </span><span class="spaces">        </span><span class="istickedoff">( 0, 1, 0, -y ),</span>
-<span class="lineno">  161 </span><span class="spaces">        </span><span class="istickedoff">( 0, 0, 1, -z ),</span>
-<span class="lineno">  162 </span><span class="spaces">        </span><span class="istickedoff">( 0, 0, 0,  1 ) ) )</span></span>
-<span class="lineno">  163 </span>
-<span class="lineno">  164 </span><span class="decl"><span class="istickedoff">scaleM (x, y, z)</span>
-<span class="lineno">  165 </span><span class="spaces">  </span><span class="istickedoff">= ( matrix</span>
-<span class="lineno">  166 </span><span class="spaces">      </span><span class="istickedoff">( (   x',    0,    0, 0 ),</span>
-<span class="lineno">  167 </span><span class="spaces">        </span><span class="istickedoff">(    0,   y',    0, 0 ),</span>
-<span class="lineno">  168 </span><span class="spaces">        </span><span class="istickedoff">(    0,    0,   z', 0 ),</span>
-<span class="lineno">  169 </span><span class="spaces">        </span><span class="istickedoff">(    0,    0,    0, 1 ) ),</span>
-<span class="lineno">  170 </span><span class="spaces">      </span><span class="istickedoff">matrix</span>
-<span class="lineno">  171 </span><span class="spaces">      </span><span class="istickedoff">( ( 1/x',    0,    0, 0 ),</span>
-<span class="lineno">  172 </span><span class="spaces">        </span><span class="istickedoff">(    0, 1/y',    0, 0 ),</span>
-<span class="lineno">  173 </span><span class="spaces">        </span><span class="istickedoff">(    0,    0, 1/z', 0 ),</span>
-<span class="lineno">  174 </span><span class="spaces">        </span><span class="istickedoff">(    0,    0,    0, 1 ) ) )</span>
-<span class="lineno">  175 </span><span class="spaces">  </span><span class="istickedoff">where x' = nonZero x</span>
-<span class="lineno">  176 </span><span class="spaces">        </span><span class="istickedoff">y' = nonZero y</span>
-<span class="lineno">  177 </span><span class="spaces">        </span><span class="istickedoff">z' = nonZero z</span></span>
-<span class="lineno">  178 </span>
-<span class="lineno">  179 </span><span class="decl"><span class="istickedoff">rotxM t</span>
-<span class="lineno">  180 </span><span class="spaces">  </span><span class="istickedoff">= ( matrix</span>
-<span class="lineno">  181 </span><span class="spaces">      </span><span class="istickedoff">( (      1,      0,      0, 0 ),</span>
-<span class="lineno">  182 </span><span class="spaces">        </span><span class="istickedoff">(      0,  cos t, -sin t, 0 ),</span>
-<span class="lineno">  183 </span><span class="spaces">        </span><span class="istickedoff">(      0,  sin t,  cos t, 0 ),</span>
-<span class="lineno">  184 </span><span class="spaces">        </span><span class="istickedoff">(      0,      0,      0, 1 ) ),</span>
-<span class="lineno">  185 </span><span class="spaces">      </span><span class="istickedoff">matrix</span>
-<span class="lineno">  186 </span><span class="spaces">      </span><span class="istickedoff">( (      1,      0,      0, 0 ),</span>
-<span class="lineno">  187 </span><span class="spaces">        </span><span class="istickedoff">(      0,  cos t,  sin t, 0 ),</span>
-<span class="lineno">  188 </span><span class="spaces">        </span><span class="istickedoff">(      0, -sin t,  cos t, 0 ),</span>
-<span class="lineno">  189 </span><span class="spaces">        </span><span class="istickedoff">(      0,      0,      0, 1 ) ) )</span></span>
-<span class="lineno">  190 </span>
-<span class="lineno">  191 </span><span class="decl"><span class="istickedoff">rotyM t</span>
-<span class="lineno">  192 </span><span class="spaces">  </span><span class="istickedoff">= ( matrix</span>
-<span class="lineno">  193 </span><span class="spaces">      </span><span class="istickedoff">( (  cos t,      0,  sin t, 0 ),</span>
-<span class="lineno">  194 </span><span class="spaces">        </span><span class="istickedoff">(      0,      1,      0, 0 ),</span>
-<span class="lineno">  195 </span><span class="spaces">        </span><span class="istickedoff">( -sin t,      0,  cos t, 0 ),</span>
-<span class="lineno">  196 </span><span class="spaces">        </span><span class="istickedoff">(      0,      0,      0, 1 ) ),</span>
-<span class="lineno">  197 </span><span class="spaces">      </span><span class="istickedoff">matrix</span>
-<span class="lineno">  198 </span><span class="spaces">      </span><span class="istickedoff">( (  cos t,      0, -sin t, 0 ),</span>
-<span class="lineno">  199 </span><span class="spaces">        </span><span class="istickedoff">(      0,      1,      0, 0 ),</span>
-<span class="lineno">  200 </span><span class="spaces">        </span><span class="istickedoff">(  sin t,      0,  cos t, 0 ),</span>
-<span class="lineno">  201 </span><span class="spaces">        </span><span class="istickedoff">(      0,      0,      0, 1 ) ) )</span></span>
-<span class="lineno">  202 </span>
-<span class="lineno">  203 </span><span class="decl"><span class="nottickedoff">rotzM t</span>
-<span class="lineno">  204 </span><span class="spaces">  </span><span class="nottickedoff">= ( matrix</span>
-<span class="lineno">  205 </span><span class="spaces">      </span><span class="nottickedoff">( (  cos t, -sin t,      0, 0 ),</span>
-<span class="lineno">  206 </span><span class="spaces">        </span><span class="nottickedoff">(  sin t,  cos t,      0, 0 ),</span>
-<span class="lineno">  207 </span><span class="spaces">        </span><span class="nottickedoff">(      0,      0,      1, 0 ),</span>
-<span class="lineno">  208 </span><span class="spaces">        </span><span class="nottickedoff">(      0,      0,      0, 1 ) ),</span>
-<span class="lineno">  209 </span><span class="spaces">      </span><span class="nottickedoff">matrix</span>
-<span class="lineno">  210 </span><span class="spaces">      </span><span class="nottickedoff">( (  cos t,  sin t,      0, 0 ),</span>
-<span class="lineno">  211 </span><span class="spaces">        </span><span class="nottickedoff">( -sin t,  cos t,      0, 0 ),</span>
-<span class="lineno">  212 </span><span class="spaces">        </span><span class="nottickedoff">(      0,      0,      1, 0 ),</span>
-<span class="lineno">  213 </span><span class="spaces">        </span><span class="nottickedoff">(      0,      0,      0, 1 ) ) )</span></span>
-<span class="lineno">  214 </span>
-<span class="lineno">  215 </span>-------------------
-<span class="lineno">  216 </span>-- Eye transformations
-<span class="lineno">  217 </span>
-<span class="lineno">  218 </span>-- These are used to specify placement of the eye.
-<span class="lineno">  219 </span>-- `eye' starts out at (0, 0, -1).
-<span class="lineno">  220 </span>-- These are implemented as inverse transforms of the model.
-<span class="lineno">  221 </span>-------------------
-<span class="lineno">  222 </span>
-<span class="lineno">  223 </span>eye                       :: Transform
-<span class="lineno">  224 </span>translateEye          :: Coords -&gt; Transform -&gt; Transform
-<span class="lineno">  225 </span>rotateEyeX, rotateEyeY, rotateEyeZ      :: Radian -&gt; Transform -&gt; Transform
-<span class="lineno">  226 </span>
-<span class="lineno">  227 </span><span class="decl"><span class="istickedoff">eye = (unit, unit)</span></span>
-<span class="lineno">  228 </span><span class="decl"><span class="nottickedoff">translateEye xyz (eye1, eye2)</span>
-<span class="lineno">  229 </span><span class="spaces">  </span><span class="nottickedoff">= (multMM m1 eye1, multMM eye2 m2)</span>
-<span class="lineno">  230 </span><span class="spaces">  </span><span class="nottickedoff">where (m1, m2) = transM xyz</span></span>
-<span class="lineno">  231 </span><span class="decl"><span class="nottickedoff">rotateEyeX t (eye1, eye2)</span>
-<span class="lineno">  232 </span><span class="spaces">  </span><span class="nottickedoff">= (multMM m1 eye1, multMM eye2 m2)</span>
-<span class="lineno">  233 </span><span class="spaces">  </span><span class="nottickedoff">where (m1, m2) = rotxM t</span></span>
-<span class="lineno">  234 </span><span class="decl"><span class="nottickedoff">rotateEyeY t (eye1, eye2)</span>
-<span class="lineno">  235 </span><span class="spaces">  </span><span class="nottickedoff">= (multMM m1 eye1, multMM eye2 m2)</span>
-<span class="lineno">  236 </span><span class="spaces">  </span><span class="nottickedoff">where (m1, m2) = rotyM t</span></span>
-<span class="lineno">  237 </span><span class="decl"><span class="nottickedoff">rotateEyeZ t (eye1, eye2)</span>
-<span class="lineno">  238 </span><span class="spaces">  </span><span class="nottickedoff">= (multMM m1 eye1, multMM eye2 m2)</span>
-<span class="lineno">  239 </span><span class="spaces">  </span><span class="nottickedoff">where (m1, m2) = rotzM t</span></span>
-<span class="lineno">  240 </span>
-<span class="lineno">  241 </span>-------------------
-<span class="lineno">  242 </span>-- Bounding boxes
-<span class="lineno">  243 </span>-------------------
-<span class="lineno">  244 </span>
-<span class="lineno">  245 </span><span class="decl"><span class="nottickedoff">mergeBox (B x11  x12  y11  y12  z11  z12) (B x21  x22  y21  y22  z21  z22) =</span>
-<span class="lineno">  246 </span><span class="spaces">    </span><span class="nottickedoff">B (x11 `min` x21) (x12 `max` x22)</span>
-<span class="lineno">  247 </span><span class="spaces">      </span><span class="nottickedoff">(y11 `min` y21) (y12 `max` y22)</span>
-<span class="lineno">  248 </span><span class="spaces">      </span><span class="nottickedoff">(z11 `min` z21) (z12 `max` z22)</span></span>
-<span class="lineno">  249 </span>
-<span class="lineno">  250 </span><span class="decl"><span class="istickedoff">transformBox t (B x1  x2  y1  y2  z1  z2)</span>
-<span class="lineno">  251 </span><span class="spaces">  </span><span class="istickedoff">= (B (foldr1 min (map xCoord pts'))</span>
-<span class="lineno">  252 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 max (map xCoord pts'))</span>
-<span class="lineno">  253 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 min (map yCoord pts'))</span>
-<span class="lineno">  254 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 max (map yCoord pts'))</span>
-<span class="lineno">  255 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 min (map zCoord pts'))</span>
-<span class="lineno">  256 </span><span class="spaces">       </span><span class="istickedoff">(foldr1 max (map zCoord pts')))</span>
-<span class="lineno">  257 </span><span class="spaces">  </span><span class="istickedoff">where pts' = map (multMP t) pts</span>
-<span class="lineno">  258 </span><span class="spaces">        </span><span class="istickedoff">pts =  [point x1 y1 z1,</span>
-<span class="lineno">  259 </span><span class="spaces">                </span><span class="istickedoff">point x1 y1 z2,</span>
-<span class="lineno">  260 </span><span class="spaces">                </span><span class="istickedoff">point x1 y2 z1,</span>
-<span class="lineno">  261 </span><span class="spaces">                </span><span class="istickedoff">point x1 y2 z2,</span>
-<span class="lineno">  262 </span><span class="spaces">                </span><span class="istickedoff">point x2 y1 z1,</span>
-<span class="lineno">  263 </span><span class="spaces">                </span><span class="istickedoff">point x2 y1 z2,</span>
-<span class="lineno">  264 </span><span class="spaces">                </span><span class="istickedoff">point x2 y2 z1,</span>
-<span class="lineno">  265 </span><span class="spaces">                </span><span class="istickedoff">point x2 y2 z2]</span></span>
+<span class="lineno">  114 </span>adjustRadian :: Radian -&gt; Radian
+<span class="lineno">  115 </span><span class="decl"><span class="nottickedoff">adjustRadian r = if r &gt; 0 then r else r + 2 * pi</span></span>
+
+</pre>
+</html>
+Writing: Primitives.hs.html
+<html><style type="text/css">
+span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
+span.nottickedoff { background: yellow}
+span.istickedoff { background: white }
+span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
+span.tickonlytrue  { margin: -1px; border: 1px solid #60de51; background: #60de51 }
+span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
+span.decl { font-weight: bold }
+span.spaces    { background: white }
+</style>
+<pre>
+<span class="lineno">    1 </span>-- Copyright (c) 2000 Galois Connections, Inc.
+<span class="lineno">    2 </span>-- All rights reserved.  This software is distributed as
+<span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
+<span class="lineno">    4 </span>-- which is included in the distribution.
+<span class="lineno">    5 </span>
+<span class="lineno">    6 </span>module Primitives where
+<span class="lineno">    7 </span>
+<span class="lineno">    8 </span>rad2deg :: Double -&gt; Double
+<span class="lineno">    9 </span><span class="decl"><span class="nottickedoff">rad2deg r = r * 180 / pi</span></span>
+<span class="lineno">   10 </span>
+<span class="lineno">   11 </span>deg2rad :: Double -&gt; Double
+<span class="lineno">   12 </span><span class="decl"><span class="istickedoff">deg2rad d = d * pi / 180</span></span>
+<span class="lineno">   13 </span>
+<span class="lineno">   14 </span>addi :: Int -&gt; Int -&gt; Int
+<span class="lineno">   15 </span><span class="decl"><span class="nottickedoff">addi = (+)</span></span>
+<span class="lineno">   16 </span>
+<span class="lineno">   17 </span>addf :: Double -&gt; Double -&gt; Double
+<span class="lineno">   18 </span><span class="decl"><span class="nottickedoff">addf = (+)</span></span>
+<span class="lineno">   19 </span>
+<span class="lineno">   20 </span>acosD :: Double -&gt; Double
+<span class="lineno">   21 </span><span class="decl"><span class="nottickedoff">acosD x = acos x * 180 / pi</span></span>
+<span class="lineno">   22 </span>
+<span class="lineno">   23 </span>asinD :: Double -&gt; Double
+<span class="lineno">   24 </span><span class="decl"><span class="nottickedoff">asinD x = asin x * 180 / pi</span></span>
 
 </pre>
 </html>
-Writing: Parse.hs.html
+Writing: Eval.hs.html
 <html><style type="text/css">
 span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
 span.nottickedoff { background: yellow}
@@ -2608,138 +2390,356 @@ span.spaces    { background: white }
 <span class="lineno">    3 </span>-- free software under the license in the file &quot;LICENSE&quot;,
 <span class="lineno">    4 </span>-- which is included in the distribution.
 <span class="lineno">    5 </span>
-<span class="lineno">    6 </span>module Parse where
+<span class="lineno">    6 </span>module Eval where
 <span class="lineno">    7 </span>
-<span class="lineno">    8 </span>import Char
-<span class="lineno">    9 </span>import Text.ParserCombinators.Parsec hiding (token)
-<span class="lineno">   10 </span>
-<span class="lineno">   11 </span>import Data
-<span class="lineno">   12 </span>
-<span class="lineno">   13 </span>
-<span class="lineno">   14 </span>program :: Parser Code
-<span class="lineno">   15 </span><span class="decl"><span class="istickedoff">program =</span>
-<span class="lineno">   16 </span><span class="spaces">  </span><span class="istickedoff">do { whiteSpace</span>
-<span class="lineno">   17 </span><span class="spaces">     </span><span class="istickedoff">; ts &lt;- tokenList</span>
-<span class="lineno">   18 </span><span class="spaces">     </span><span class="istickedoff">; eof</span>
-<span class="lineno">   19 </span><span class="spaces">     </span><span class="istickedoff">; return ts</span>
-<span class="lineno">   20 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
-<span class="lineno">   21 </span>
-<span class="lineno">   22 </span>tokenList :: Parser Code
-<span class="lineno">   23 </span><span class="decl"><span class="istickedoff">tokenList = many token &lt;?&gt; <span class="nottickedoff">&quot;list of tokens&quot;</span></span></span>
+<span class="lineno">    8 </span>import Array
+<span class="lineno">    9 </span>
+<span class="lineno">   10 </span>import Geometry
+<span class="lineno">   11 </span>import CSG
+<span class="lineno">   12 </span>import Surface
+<span class="lineno">   13 </span>import Data
+<span class="lineno">   14 </span>import Parse (rayParse, rayParseF)
+<span class="lineno">   15 </span>
+<span class="lineno">   16 </span>class Monad m =&gt; MonadEval m where
+<span class="lineno">   17 </span>  doOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; m Stack
+<span class="lineno">   18 </span>  tick :: m ()
+<span class="lineno">   19 </span>  err  :: String -&gt; m a
+<span class="lineno">   20 </span>
+<span class="lineno">   21 </span>  <span class="decl"><span class="istickedoff">tick = return <span class="nottickedoff">()</span></span></span>
+<span class="lineno">   22 </span>
+<span class="lineno">   23 </span>newtype Pure a = Pure a deriving <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>
 <span class="lineno">   24 </span>
-<span class="lineno">   25 </span>token :: Parser GMLToken
-<span class="lineno">   26 </span><span class="decl"><span class="istickedoff">token =</span>
-<span class="lineno">   27 </span><span class="spaces">       </span><span class="istickedoff">do { ts &lt;- braces   tokenList          ; return (TBody ts) } </span>
-<span class="lineno">   28 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt;  do { ts &lt;- brackets tokenList          ; return (TArray ts) }</span>
-<span class="lineno">   29 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt; (do { s  &lt;- gmlString                   ; return (TString <span class="nottickedoff">s</span>) } &lt;?&gt; <span class="nottickedoff">&quot;string&quot;</span>)</span>
-<span class="lineno">   30 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt; (do { t &lt;- pident False                 ; return t }           &lt;?&gt; <span class="nottickedoff">&quot;identifier&quot;</span>)</span>
-<span class="lineno">   31 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt; (do { char '/'   -- No whitespace after slash</span>
-<span class="lineno">   32 </span><span class="spaces">          </span><span class="istickedoff">; t &lt;- pident True                  ; return t } &lt;?&gt; <span class="nottickedoff">&quot;binding identifier&quot;</span>)</span>
-<span class="lineno">   33 </span><span class="spaces">  </span><span class="istickedoff">&lt;|&gt; (do { n &lt;- number                       ; return n } &lt;?&gt; <span class="nottickedoff">&quot;number&quot;</span>)</span></span>
-<span class="lineno">   34 </span>
-<span class="lineno">   35 </span>pident :: Bool -&gt; Parser GMLToken
-<span class="lineno">   36 </span><span class="decl"><span class="istickedoff">pident rebind =</span>
-<span class="lineno">   37 </span><span class="spaces">  </span><span class="istickedoff">do { id &lt;- ident</span>
-<span class="lineno">   38 </span><span class="spaces">     </span><span class="istickedoff">; case (lookup id opTable) of</span>
-<span class="lineno">   39 </span><span class="spaces">       </span><span class="istickedoff">Nothing -&gt; if rebind then return (TBind id) else return (TId id)</span>
-<span class="lineno">   40 </span><span class="spaces">       </span><span class="istickedoff">Just t  -&gt; if <span class="tickonlyfalse">rebind</span> then <span class="nottickedoff">error (&quot;Attempted rebinding of identifier &quot; ++ id)</span> else return t</span>
-<span class="lineno">   41 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
-<span class="lineno">   42 </span>
-<span class="lineno">   43 </span>ident :: Parser String
-<span class="lineno">   44 </span><span class="decl"><span class="istickedoff">ident = lexeme $</span>
-<span class="lineno">   45 </span><span class="spaces">  </span><span class="istickedoff">do { l &lt;- letter</span>
-<span class="lineno">   46 </span><span class="spaces">     </span><span class="istickedoff">; ls &lt;- many (satisfy (\x -&gt; isAlphaNum x || x == '-' || x == '_'))</span>
-<span class="lineno">   47 </span><span class="spaces">     </span><span class="istickedoff">; return (l:ls)</span>
-<span class="lineno">   48 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
-<span class="lineno">   49 </span>
-<span class="lineno">   50 </span>gmlString :: Parser String
-<span class="lineno">   51 </span><span class="decl"><span class="istickedoff">gmlString = lexeme $ between (char '&quot;') (char '&quot;') (many (satisfy (\x -&gt; isPrint x &amp;&amp; x /= '&quot;')))</span></span>
-<span class="lineno">   52 </span>
-<span class="lineno">   53 </span>-- Tests for numbers
-<span class="lineno">   54 </span>-- Hugs breaks on big exponents (&gt; ~40)
-<span class="lineno">   55 </span><span class="decl"><span class="nottickedoff">test_number = &quot;1234 -1234 1 -0 0&quot; ++</span>
-<span class="lineno">   56 </span><span class="spaces">              </span><span class="nottickedoff">&quot; 1234.5678 -1234.5678 1234.5678e12 1234.5678e-12 -1234.5678e-12&quot; ++</span>
-<span class="lineno">   57 </span><span class="spaces">              </span><span class="nottickedoff">&quot; -1234.5678e12 -1234.5678E-12 -1234.5678E12&quot; ++</span>
-<span class="lineno">   58 </span><span class="spaces">              </span><span class="nottickedoff">&quot; 1234e11 1234E33 -1234e33 1234e-33&quot; ++</span>
-<span class="lineno">   59 </span><span class="spaces">              </span><span class="nottickedoff">&quot; 123e 123.4e 123ee 123.4ee 123E 123.4E 123EE 123.4EE&quot;</span></span>
-<span class="lineno">   60 </span>              
-<span class="lineno">   61 </span>
-<span class="lineno">   62 </span>-- Always int or real
-<span class="lineno">   63 </span>number :: Parser GMLToken
-<span class="lineno">   64 </span><span class="decl"><span class="istickedoff">number = lexeme $</span>
-<span class="lineno">   65 </span><span class="spaces">  </span><span class="istickedoff">do { s &lt;- optSign</span>
-<span class="lineno">   66 </span><span class="spaces">     </span><span class="istickedoff">; n &lt;- decimal</span>
-<span class="lineno">   67 </span><span class="spaces">     </span><span class="istickedoff">;     do { string &quot;.&quot;</span>
-<span class="lineno">   68 </span><span class="spaces">              </span><span class="istickedoff">; m &lt;- decimal</span>
-<span class="lineno">   69 </span><span class="spaces">              </span><span class="istickedoff">; e &lt;- option &quot;&quot; exponent'</span>
-<span class="lineno">   70 </span><span class="spaces">              </span><span class="istickedoff">; return (TReal (read (s ++ n ++ &quot;.&quot; ++ m ++ e)))  -- FIXME: Handle error conditions</span>
-<span class="lineno">   71 </span><span class="spaces">              </span><span class="istickedoff">}</span>
-<span class="lineno">   72 </span><span class="spaces">       </span><span class="istickedoff">&lt;|&gt; do { e &lt;- exponent'</span>
-<span class="lineno">   73 </span><span class="spaces">              </span><span class="istickedoff">; <span class="nottickedoff">return (TReal (read (s ++ n ++ &quot;.0&quot; ++ e)))</span></span>
-<span class="lineno">   74 </span><span class="spaces">              </span><span class="istickedoff">}</span>
-<span class="lineno">   75 </span><span class="spaces">       </span><span class="istickedoff">&lt;|&gt; do { return (TInt (read (s ++ n))) }</span>
-<span class="lineno">   76 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
-<span class="lineno">   77 </span>
-<span class="lineno">   78 </span>exponent' :: Parser String
-<span class="lineno">   79 </span><span class="decl"><span class="istickedoff">exponent' = try $</span>
-<span class="lineno">   80 </span><span class="spaces">  </span><span class="istickedoff">do { e &lt;- oneOf &quot;eE&quot;</span>
-<span class="lineno">   81 </span><span class="spaces">     </span><span class="istickedoff">; s &lt;- <span class="nottickedoff">optSign</span></span>
-<span class="lineno">   82 </span><span class="spaces">     </span><span class="istickedoff">; n &lt;- <span class="nottickedoff">decimal</span></span>
-<span class="lineno">   83 </span><span class="spaces">     </span><span class="istickedoff">; <span class="nottickedoff">return (e:s ++ n)</span></span>
-<span class="lineno">   84 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
-<span class="lineno">   85 </span>
-<span class="lineno">   86 </span><span class="decl"><span class="istickedoff">decimal = many1 digit</span></span>
-<span class="lineno">   87 </span>
-<span class="lineno">   88 </span>optSign :: Parser String
-<span class="lineno">   89 </span><span class="decl"><span class="istickedoff">optSign = option &quot;&quot; (string &quot;-&quot;)</span></span>
-<span class="lineno">   90 </span>
-<span class="lineno">   91 </span>
-<span class="lineno">   92 </span>------------------------------------------------------
-<span class="lineno">   93 </span>-- Library for tokenizing.
-<span class="lineno">   94 </span>
-<span class="lineno">   95 </span><span class="decl"><span class="istickedoff">braces   p = between (symbol &quot;{&quot;) (symbol &quot;}&quot;) p</span></span>
-<span class="lineno">   96 </span><span class="decl"><span class="istickedoff">brackets p = between (symbol &quot;[&quot;) (symbol &quot;]&quot;) p</span></span>
-<span class="lineno">   97 </span>
-<span class="lineno">   98 </span><span class="decl"><span class="istickedoff">symbol name = lexeme (string name)</span></span>
-<span class="lineno">   99 </span>
-<span class="lineno">  100 </span><span class="decl"><span class="istickedoff">lexeme p = do{ x &lt;- p; whiteSpace; return x  }</span></span>
-<span class="lineno">  101 </span>
-<span class="lineno">  102 </span><span class="decl"><span class="istickedoff">whiteSpace  = skipMany (simpleSpace &lt;|&gt; oneLineComment &lt;?&gt; <span class="nottickedoff">&quot;&quot;</span>)</span>
-<span class="lineno">  103 </span><span class="spaces">  </span><span class="istickedoff">where simpleSpace = skipMany1 (oneOf &quot; \t\n\r\v&quot;)    </span>
-<span class="lineno">  104 </span><span class="spaces">        </span><span class="istickedoff">oneLineComment =</span>
-<span class="lineno">  105 </span><span class="spaces">            </span><span class="istickedoff">do{ string &quot;%&quot;</span>
-<span class="lineno">  106 </span><span class="spaces">              </span><span class="istickedoff">; skipMany (noneOf &quot;\n\r\v&quot;)</span>
-<span class="lineno">  107 </span><span class="spaces">              </span><span class="istickedoff">; return ()</span>
-<span class="lineno">  108 </span><span class="spaces">              </span><span class="istickedoff">}</span></span>
-<span class="lineno">  109 </span>
-<span class="lineno">  110 </span>
-<span class="lineno">  111 </span>------------------------------------------------------------------------------
-<span class="lineno">  112 </span>
-<span class="lineno">  113 </span>rayParse :: String -&gt; Code
-<span class="lineno">  114 </span><span class="decl"><span class="istickedoff">rayParse is = case (parse program <span class="nottickedoff">&quot;&lt;stdin&gt;&quot;</span> is) of</span>
-<span class="lineno">  115 </span><span class="spaces">              </span><span class="istickedoff">Left err -&gt; <span class="nottickedoff">error (show err)</span></span>
-<span class="lineno">  116 </span><span class="spaces">              </span><span class="istickedoff">Right x  -&gt; x</span></span>
-<span class="lineno">  117 </span>
-<span class="lineno">  118 </span>rayParseF :: String -&gt; IO Code
-<span class="lineno">  119 </span><span class="decl"><span class="nottickedoff">rayParseF file =</span>
-<span class="lineno">  120 </span><span class="spaces">  </span><span class="nottickedoff">do { r &lt;- parseFromFile program file</span>
-<span class="lineno">  121 </span><span class="spaces">     </span><span class="nottickedoff">; case r of</span>
-<span class="lineno">  122 </span><span class="spaces">       </span><span class="nottickedoff">Left err -&gt; error (show err)</span>
-<span class="lineno">  123 </span><span class="spaces">       </span><span class="nottickedoff">Right x  -&gt; return x</span>
-<span class="lineno">  124 </span><span class="spaces">     </span><span class="nottickedoff">}</span></span>
-<span class="lineno">  125 </span>
-<span class="lineno">  126 </span>run :: String -&gt; IO ()
-<span class="lineno">  127 </span><span class="decl"><span class="nottickedoff">run is = case (parse program &quot;&quot; is) of</span>
-<span class="lineno">  128 </span><span class="spaces">         </span><span class="nottickedoff">Left err -&gt; print err</span>
-<span class="lineno">  129 </span><span class="spaces">         </span><span class="nottickedoff">Right x  -&gt; print x</span></span>
-<span class="lineno">  130 </span>
-<span class="lineno">  131 </span>runF :: IO ()
-<span class="lineno">  132 </span><span class="decl"><span class="nottickedoff">runF =</span>
-<span class="lineno">  133 </span><span class="spaces">  </span><span class="nottickedoff">do { r &lt;- parseFromFile program &quot;simple.gml&quot;</span>
-<span class="lineno">  134 </span><span class="spaces">     </span><span class="nottickedoff">; case r of</span>
-<span class="lineno">  135 </span><span class="spaces">       </span><span class="nottickedoff">Left err -&gt; print err</span>
-<span class="lineno">  136 </span><span class="spaces">       </span><span class="nottickedoff">Right x  -&gt; print x</span>
-<span class="lineno">  137 </span><span class="spaces">     </span><span class="nottickedoff">}</span></span>
+<span class="lineno">   25 </span>instance Monad Pure where
+<span class="lineno">   26 </span>    <span class="decl"><span class="istickedoff">Pure x &gt;&gt;= k = k x</span></span>
+<span class="lineno">   27 </span>    <span class="decl"><span class="istickedoff">return       = Pure</span></span>
+<span class="lineno">   28 </span>    <span class="decl"><span class="nottickedoff">fail s       = error s</span></span>
+<span class="lineno">   29 </span>
+<span class="lineno">   30 </span>instance MonadEval Pure where
+<span class="lineno">   31 </span>  <span class="decl"><span class="istickedoff">doOp   = doPureOp</span></span> 
+<span class="lineno">   32 </span>  <span class="decl"><span class="nottickedoff">err  s = error s</span></span>
+<span class="lineno">   33 </span>
+<span class="lineno">   34 </span>instance MonadEval IO where
+<span class="lineno">   35 </span>  <span class="decl"><span class="istickedoff">doOp prim op stk = do { -- putStrLn (&quot;Calling &quot; ++ show op</span>
+<span class="lineno">   36 </span><span class="spaces">                          </span><span class="istickedoff">--           ++ &quot; &lt;&lt; &quot; ++ show stk ++ &quot; &gt;&gt;&quot;)</span>
+<span class="lineno">   37 </span><span class="spaces">                          </span><span class="istickedoff">doAllOp  prim op stk</span>
+<span class="lineno">   38 </span><span class="spaces">                        </span><span class="istickedoff">}</span></span>
+<span class="lineno">   39 </span>  <span class="decl"><span class="nottickedoff">err  s = error s</span></span>
+<span class="lineno">   40 </span>
+<span class="lineno">   41 </span>data State
+<span class="lineno">   42 </span>        = State { env   :: Env
+<span class="lineno">   43 </span>                , stack :: Stack
+<span class="lineno">   44 </span>                , code  :: Code
+<span class="lineno">   45 </span>                } deriving <span class="decl"><span class="nottickedoff"><span class="decl"><span class="nottickedoff">Show</span></span></span></span>
+<span class="lineno">   46 </span>
+<span class="lineno">   47 </span>callback :: Env -&gt; Code -&gt; Stack -&gt; Stack
+<span class="lineno">   48 </span><span class="decl"><span class="istickedoff">callback env code stk</span>
+<span class="lineno">   49 </span><span class="spaces">      </span><span class="istickedoff">= case eval (State { env = env, stack = stk, code = code}) of</span>
+<span class="lineno">   50 </span><span class="spaces">             </span><span class="istickedoff">Pure stk -&gt; stk</span></span>
+<span class="lineno">   51 </span>
+<span class="lineno">   52 </span>{-# SPECIALIZE eval ::  State -&gt; Pure Stack #-}
+<span class="lineno">   53 </span>{-# SPECIALIZE eval ::  State -&gt; IO Stack #-}
+<span class="lineno">   54 </span>
+<span class="lineno">   55 </span>eval :: MonadEval m =&gt; State -&gt; m Stack
+<span class="lineno">   56 </span><span class="decl"><span class="istickedoff">eval st =</span>
+<span class="lineno">   57 </span><span class="spaces">  </span><span class="istickedoff">do { () &lt;- return () -- $ unsafePerformIO (print st)   -- Functional debugger</span>
+<span class="lineno">   58 </span><span class="spaces">     </span><span class="istickedoff">; if moreCode st then</span>
+<span class="lineno">   59 </span><span class="spaces">       </span><span class="istickedoff">do { tick             -- tick first, so as to catch loops on new eval.</span>
+<span class="lineno">   60 </span><span class="spaces">            </span><span class="istickedoff">; st' &lt;- step st</span>
+<span class="lineno">   61 </span><span class="spaces">            </span><span class="istickedoff">; eval st'</span>
+<span class="lineno">   62 </span><span class="spaces">            </span><span class="istickedoff">}</span>
+<span class="lineno">   63 </span><span class="spaces">        </span><span class="istickedoff">else return (stack st)</span>
+<span class="lineno">   64 </span><span class="spaces">     </span><span class="istickedoff">}</span></span>
+<span class="lineno">   65 </span>     
+<span class="lineno">   66 </span>moreCode :: State -&gt; Bool
+<span class="lineno">   67 </span><span class="decl"><span class="istickedoff">moreCode (State {code = []}) = False</span>
+<span class="lineno">   68 </span><span class="spaces"></span><span class="istickedoff">moreCode _                   = True</span></span>
+<span class="lineno">   69 </span>
+<span class="lineno">   70 </span>-- Step has a precondition that there *is* code to run
+<span class="lineno">   71 </span>{-# SPECIALIZE step ::  State -&gt; Pure State #-}
+<span class="lineno">   72 </span>{-# SPECIALIZE step ::  State -&gt; IO State #-}
+<span class="lineno">   73 </span>step :: MonadEval m =&gt; State -&gt; m State
+<span class="lineno">   74 </span>
+<span class="lineno">   75 </span>-- Rule 1: Pushing BaseValues
+<span class="lineno">   76 </span><span class="decl"><span class="istickedoff">step st@(State{ stack = stack, code = (TBool b):cs })    </span>
+<span class="lineno">   77 </span><span class="spaces">    </span><span class="istickedoff">= <span class="nottickedoff">return (st { stack = (VBool b):stack,    code = cs })</span></span>
+<span class="lineno">   78 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ stack = stack, code = (TInt i):cs })     </span>
+<span class="lineno">   79 </span><span class="spaces">    </span><span class="istickedoff">= return (st { stack = (VInt i):stack,     code = cs })</span>
+<span class="lineno">   80 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ stack = stack, code = (TReal r):cs })    </span>
+<span class="lineno">   81 </span><span class="spaces">    </span><span class="istickedoff">= return (st { stack = (VReal r):stack,    code = cs })</span>
+<span class="lineno">   82 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ stack = stack, code = (TString s):cs })  </span>
+<span class="lineno">   83 </span><span class="spaces">    </span><span class="istickedoff">= return (st { stack = (VString <span class="nottickedoff">s</span>):stack,  code = cs })</span>
+<span class="lineno">   84 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">   85 </span><span class="spaces"></span><span class="istickedoff">-- Rule 2: Name binding</span>
+<span class="lineno">   86 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = (v:stack), code = (TBind id):cs }) =</span>
+<span class="lineno">   87 </span><span class="spaces">  </span><span class="istickedoff">return (State { env = extendEnv env id v, stack = stack,  code = cs })</span>
+<span class="lineno">   88 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = [], code = (TBind id):cs }) =</span>
+<span class="lineno">   89 </span><span class="spaces">  </span><span class="istickedoff"><span class="nottickedoff">err &quot;Attempt to bind the top of an empty stack&quot;</span></span>
+<span class="lineno">   90 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">   91 </span><span class="spaces"></span><span class="istickedoff">-- Rule 3: Name lookup</span>
+<span class="lineno">   92 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = stack, code = (TId id):cs }) =</span>
+<span class="lineno">   93 </span><span class="spaces">  </span><span class="istickedoff">case (lookupEnv env id) of</span>
+<span class="lineno">   94 </span><span class="spaces">  </span><span class="istickedoff">Just v -&gt; return (st { stack = v:stack,  code = cs })</span>
+<span class="lineno">   95 </span><span class="spaces">  </span><span class="istickedoff">Nothing -&gt; <span class="nottickedoff">err (&quot;Cannot find value for identifier: &quot; ++ id)</span></span>
+<span class="lineno">   96 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">   97 </span><span class="spaces"></span><span class="istickedoff">-- Rule 4: Closure creation</span>
+<span class="lineno">   98 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = stack, code = (TBody body):cs }) =</span>
+<span class="lineno">   99 </span><span class="spaces">  </span><span class="istickedoff">return (st { stack = (VClosure env body):stack, code = cs })</span>
+<span class="lineno">  100 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  101 </span><span class="spaces"></span><span class="istickedoff">-- Rule 5: Application</span>
+<span class="lineno">  102 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = (VClosure env' code'):stack, code = TApply:cs }) =</span>
+<span class="lineno">  103 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- eval (State {env = <span class="nottickedoff">env'</span>, stack = stack, code = code'})</span>
+<span class="lineno">  104 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = stk, code = cs })</span>
+<span class="lineno">  105 </span><span class="spaces">     </span><span class="istickedoff">}</span>
+<span class="lineno">  106 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = [], code = TApply:cs }) =</span>
+<span class="lineno">  107 </span><span class="spaces">  </span><span class="istickedoff"><span class="nottickedoff">err &quot;Application with an empty stack&quot;</span></span>
+<span class="lineno">  108 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = _:_, code = TApply:cs }) =</span>
+<span class="lineno">  109 </span><span class="spaces">  </span><span class="istickedoff"><span class="nottickedoff">err &quot;Application of a non-closure&quot;</span></span>
+<span class="lineno">  110 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  111 </span><span class="spaces"></span><span class="istickedoff">-- Rule 6: Arrays</span>
+<span class="lineno">  112 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = stack, code = TArray code':cs }) =</span>
+<span class="lineno">  113 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- eval (State {env = env, stack = [], code = code'})</span>
+<span class="lineno">  114 </span><span class="spaces">     </span><span class="istickedoff">; let last = length stk-1</span>
+<span class="lineno">  115 </span><span class="spaces">     </span><span class="istickedoff">; let arr = array (0,last) (zip [last,last-1..] stk)</span>
+<span class="lineno">  116 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = (VArray arr):stack, code = cs })</span>
+<span class="lineno">  117 </span><span class="spaces">     </span><span class="istickedoff">}</span>
+<span class="lineno">  118 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  119 </span><span class="spaces"></span><span class="istickedoff">-- Rule 7 &amp; 8: If statement</span>
+<span class="lineno">  120 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = (VClosure e2 c2):(VClosure e1 c1):(VBool True):stack, code = TIf:cs }) =</span>
+<span class="lineno">  121 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- eval (State {env = e1, stack = stack, code = c1})</span>
+<span class="lineno">  122 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = stk, code = cs })</span>
+<span class="lineno">  123 </span><span class="spaces">     </span><span class="istickedoff">}</span>
+<span class="lineno">  124 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = (VClosure e2 c2):(VClosure e1 c1):(VBool False):stack, code = TIf:cs }) =</span>
+<span class="lineno">  125 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- eval (State {env = e2, stack = stack, code = c2})</span>
+<span class="lineno">  126 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = stk, code = cs })</span>
+<span class="lineno">  127 </span><span class="spaces">     </span><span class="istickedoff">}</span>
+<span class="lineno">  128 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = _, code = TIf:cs }) =</span>
+<span class="lineno">  129 </span><span class="spaces">  </span><span class="istickedoff"><span class="nottickedoff">err &quot;Incorrect use of if (bad and/or inappropriate values on the stack)&quot;</span></span>
+<span class="lineno">  130 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  131 </span><span class="spaces"></span><span class="istickedoff">-- Rule 9: Operators</span>
+<span class="lineno">  132 </span><span class="spaces"></span><span class="istickedoff">step st@(State{ env = env, stack = stack, code = (TOp op):cs }) =</span>
+<span class="lineno">  133 </span><span class="spaces">  </span><span class="istickedoff">do { stk &lt;- doOp (opFnTable ! op) op stack</span>
+<span class="lineno">  134 </span><span class="spaces">     </span><span class="istickedoff">; return (st { stack = stk, code = cs })</span>
+<span class="lineno">  135 </span><span class="spaces">     </span><span class="istickedoff">}</span>
+<span class="lineno">  136 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  137 </span><span class="spaces"></span><span class="istickedoff">-- Rule Opps</span>
+<span class="lineno">  138 </span><span class="spaces"></span><span class="istickedoff">step _ = <span class="nottickedoff">err &quot;Tripped on sidewalk while stepping.&quot;</span></span></span>
+<span class="lineno">  139 </span>
+<span class="lineno">  140 </span>
+<span class="lineno">  141 </span>--------------------------------------------------------------------------
+<span class="lineno">  142 </span>-- Operator code
+<span class="lineno">  143 </span>
+<span class="lineno">  144 </span>opFnTable :: Array GMLOp PrimOp
+<span class="lineno">  145 </span><span class="decl"><span class="istickedoff">opFnTable = array (minBound,maxBound) </span>
+<span class="lineno">  146 </span><span class="spaces">                  </span><span class="istickedoff">[ (op,prim) | (_,TOp op,prim) &lt;- opcodes ]</span></span>
+<span class="lineno">  147 </span>
+<span class="lineno">  148 </span>
+<span class="lineno">  149 </span>
+<span class="lineno">  150 </span>
+<span class="lineno">  151 </span>doPureOp :: (MonadEval m) =&gt; PrimOp -&gt; GMLOp -&gt; Stack -&gt; m Stack
+<span class="lineno">  152 </span><span class="decl"><span class="istickedoff">doPureOp _ Op_render _ = </span>
+<span class="lineno">  153 </span><span class="spaces">    </span><span class="istickedoff"><span class="nottickedoff">err (&quot;\nAttempting to call render from inside a purely functional callback.&quot;)</span></span>
+<span class="lineno">  154 </span><span class="spaces"></span><span class="istickedoff">doPureOp primOp op stk = doPrimOp primOp <span class="nottickedoff">op</span> stk</span></span> -- call the purely functional operators
+<span class="lineno">  155 </span>
+<span class="lineno">  156 </span>{-# SPECIALIZE doPrimOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; Pure Stack #-}
+<span class="lineno">  157 </span>{-# SPECIALIZE doPrimOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; IO Stack #-}
+<span class="lineno">  158 </span>{-# SPECIALIZE doPrimOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; Abs Stack #-}
+<span class="lineno">  159 </span>
+<span class="lineno">  160 </span>doPrimOp ::  (MonadEval m) =&gt; PrimOp -&gt; GMLOp -&gt; Stack -&gt; m Stack
+<span class="lineno">  161 </span>
+<span class="lineno">  162 </span>-- 1 argument.
+<span class="lineno">  163 </span>
+<span class="lineno">  164 </span><span class="decl"><span class="istickedoff">doPrimOp (Int_Int fn) _ (VInt i1:stk)</span>
+<span class="lineno">  165 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">return ((VInt (fn i1)) : stk)</span></span>
+<span class="lineno">  166 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Real fn) _ (VReal r1:stk)</span>
+<span class="lineno">  167 </span><span class="spaces">  </span><span class="istickedoff">= return ((VReal (fn r1)) : stk)</span>
+<span class="lineno">  168 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Point_Real fn) _ (VPoint x y z:stk)</span>
+<span class="lineno">  169 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">return ((VReal (fn x y z)) : stk)</span></span>
+<span class="lineno">  170 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  171 </span><span class="spaces"></span><span class="istickedoff">-- This is where the callbacks happen from...</span>
+<span class="lineno">  172 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Surface_Obj fn) _ (VClosure env code:stk)</span>
+<span class="lineno">  173 </span><span class="spaces">  </span><span class="istickedoff">= case absapply env code [<span class="nottickedoff">VAbsObj AbsFACE</span>,<span class="nottickedoff">VAbsObj AbsU</span>,<span class="nottickedoff">VAbsObj AbsV</span>] of</span>
+<span class="lineno">  174 </span><span class="spaces">      </span><span class="istickedoff">Just [VReal r3,VReal r2,VReal r1,VPoint c1 c2 c3] -&gt; </span>
+<span class="lineno">  175 </span><span class="spaces">           </span><span class="istickedoff"><span class="nottickedoff">let</span></span>
+<span class="lineno">  176 </span><span class="spaces">               </span><span class="istickedoff"><span class="nottickedoff">res = prop (color c1 c2 c3) r1 r2 r3</span></span>
+<span class="lineno">  177 </span><span class="spaces">           </span><span class="istickedoff"><span class="nottickedoff">in</span></span>
+<span class="lineno">  178 </span><span class="spaces">               </span><span class="istickedoff"><span class="nottickedoff">return ((VObject (fn (SConst res))) : stk)</span></span>
+<span class="lineno">  179 </span><span class="spaces">      </span><span class="istickedoff">_ -&gt; return ((VObject (fn (SFun call))) : stk)</span>
+<span class="lineno">  180 </span><span class="spaces">  </span><span class="istickedoff">where </span>
+<span class="lineno">  181 </span><span class="spaces">        </span><span class="istickedoff">-- The most general case</span>
+<span class="lineno">  182 </span><span class="spaces">        </span><span class="istickedoff">call i r1 r2 =</span>
+<span class="lineno">  183 </span><span class="spaces">          </span><span class="istickedoff">case callback env code [VReal r2,VReal r1,<span class="nottickedoff">VInt i</span>] of</span>
+<span class="lineno">  184 </span><span class="spaces">             </span><span class="istickedoff">[VReal r3,VReal r2,VReal r1,VPoint c1 c2 c3] </span>
+<span class="lineno">  185 </span><span class="spaces">                 </span><span class="istickedoff">-&gt; prop (color c1 c2 c3) r1 r2 r3</span>
+<span class="lineno">  186 </span><span class="spaces">             </span><span class="istickedoff">stk -&gt; <span class="nottickedoff">error (&quot;callback failed: incorrectly typed return arguments&quot;</span></span>
+<span class="lineno">  187 </span><span class="spaces">                         </span><span class="istickedoff"><span class="nottickedoff">++ show stk)</span></span>
+<span class="lineno">  188 </span><span class="spaces">       </span><span class="istickedoff"></span>
+<span class="lineno">  189 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Int fn) _ (VReal r1:stk)</span>
+<span class="lineno">  190 </span><span class="spaces">  </span><span class="istickedoff">= return ((VInt (fn r1)) : stk)</span>
+<span class="lineno">  191 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Int_Real fn) _ (VInt r1:stk)</span>
+<span class="lineno">  192 </span><span class="spaces">  </span><span class="istickedoff">= return ((VReal (fn r1)) : stk)</span>
+<span class="lineno">  193 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Arr_Int fn) _ (VArray arr:stk)</span>
+<span class="lineno">  194 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">return ((VInt (fn arr)) : stk)</span></span>
+<span class="lineno">  195 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  196 </span><span class="spaces"></span><span class="istickedoff">-- 2 arguments.</span>
+<span class="lineno">  197 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  198 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Int_Int_Int fn) _ (VInt i2:VInt i1:stk)</span>
+<span class="lineno">  199 </span><span class="spaces">  </span><span class="istickedoff">= return ((VInt (fn i1 i2)) : stk)</span>
+<span class="lineno">  200 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Int_Int_Bool fn) _ (VInt i2:VInt i1:stk)</span>
+<span class="lineno">  201 </span><span class="spaces">  </span><span class="istickedoff">= return ((VBool (fn i1 i2)) : stk)</span>
+<span class="lineno">  202 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Real_Real fn) _ (VReal r2:VReal r1:stk)</span>
+<span class="lineno">  203 </span><span class="spaces">  </span><span class="istickedoff">= return ((VReal (fn r1 r2)) : stk)</span>
+<span class="lineno">  204 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Real_Bool fn) _ (VReal r2:VReal r1:stk)</span>
+<span class="lineno">  205 </span><span class="spaces">  </span><span class="istickedoff">= return ((VBool (fn r1 r2)) : stk)</span>
+<span class="lineno">  206 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Arr_Int_Value fn) _ (VInt i:VArray arr:stk)</span>
+<span class="lineno">  207 </span><span class="spaces">  </span><span class="istickedoff">= return ((fn arr i) : stk)</span>
+<span class="lineno">  208 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  209 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  210 </span><span class="spaces">    </span><span class="istickedoff">-- Many arguments, typically image mangling</span>
+<span class="lineno">  211 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  212 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Obj_Obj_Obj fn) _ (VObject o2:VObject o1:stk)</span>
+<span class="lineno">  213 </span><span class="spaces">  </span><span class="istickedoff">= return ((VObject (fn o1 o2)) : <span class="nottickedoff">stk</span>)</span>
+<span class="lineno">  214 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Point_Color_Light fn) _ (VPoint r g b:VPoint x y z : stk)</span>
+<span class="lineno">  215 </span><span class="spaces">  </span><span class="istickedoff">= return (VLight (fn (x,y,z) (color r g b)) : <span class="nottickedoff">stk</span>)</span>
+<span class="lineno">  216 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Point_Point_Color_Real_Real_Light fn) _ </span>
+<span class="lineno">  217 </span><span class="spaces">         </span><span class="istickedoff">(VReal r2:VReal r1:VPoint r g b:VPoint x2 y2 z2:VPoint x1 y1 z1 : stk)</span>
+<span class="lineno">  218 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">return (VLight (fn (x1,y1,z1) (x2,y2,z2) (color r g b) r1 r2) : stk)</span></span>
+<span class="lineno">  219 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Real_Real_Real_Point fn) _ (VReal r3:VReal r2:VReal r1:stk)</span>
+<span class="lineno">  220 </span><span class="spaces">  </span><span class="istickedoff">= return ((fn r1 r2 r3) : stk)</span>
+<span class="lineno">  221 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Obj_Real_Obj fn) _ (VReal r:VObject o:stk)</span>
+<span class="lineno">  222 </span><span class="spaces">  </span><span class="istickedoff">= return (VObject (fn o r) : <span class="nottickedoff">stk</span>)</span>
+<span class="lineno">  223 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Obj_Real_Real_Real_Obj fn) _ (VReal r3:VReal r2:VReal r1:VObject o:stk)</span>
+<span class="lineno">  224 </span><span class="spaces">  </span><span class="istickedoff">= return (VObject (fn o r1 r2 r3) : stk)</span>
+<span class="lineno">  225 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  226 </span><span class="spaces"></span><span class="istickedoff">-- This one is our testing harness</span>
+<span class="lineno">  227 </span><span class="spaces"></span><span class="istickedoff">doPrimOp (Value_String_Value fn) _ (VString s:o:stk)</span>
+<span class="lineno">  228 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">res `seq` return (res : stk)</span></span>
+<span class="lineno">  229 </span><span class="spaces">  </span><span class="istickedoff">where</span>
+<span class="lineno">  230 </span><span class="spaces">     </span><span class="istickedoff"><span class="nottickedoff">res = fn o s</span></span>
+<span class="lineno">  231 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  232 </span><span class="spaces"></span><span class="istickedoff">doPrimOp primOp op args </span>
+<span class="lineno">  233 </span><span class="spaces">  </span><span class="istickedoff">= <span class="nottickedoff">err (&quot;\n\ntype error when attempting to execute builtin primitive \&quot;&quot; ++</span></span>
+<span class="lineno">  234 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">show op ++ &quot;\&quot;\n\n| &quot; ++</span></span>
+<span class="lineno">  235 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">show op ++ &quot; takes &quot; ++ show (length types) ++ &quot; argument&quot; ++ s</span></span>
+<span class="lineno">  236 </span><span class="spaces">                   </span><span class="istickedoff"><span class="nottickedoff">++ &quot; with&quot; ++ the ++ &quot; type&quot; ++ s ++ &quot;\n|\n|&quot; ++</span></span>
+<span class="lineno">  237 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">&quot;      &quot; ++ unwords [ show ty | ty &lt;- types ]  ++ &quot;\n|\n|&quot; ++ </span></span>
+<span class="lineno">  238 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">&quot; currently, the relevent argument&quot; ++ s ++ &quot; on the stack &quot; ++ </span></span>
+<span class="lineno">  239 </span><span class="spaces">                  </span><span class="istickedoff"><span class="nottickedoff">are ++ &quot;\n|\n| &quot; ++ </span></span>
+<span class="lineno">  240 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">unwords [ &quot;(&quot; ++ show arg ++ &quot;)&quot; </span></span>
+<span class="lineno">  241 </span><span class="spaces">                  </span><span class="istickedoff"><span class="nottickedoff">| arg &lt;-  reverse (take (length types) args) ]  ++ &quot;\n|\n| &quot;</span></span>
+<span class="lineno">  242 </span><span class="spaces">          </span><span class="istickedoff"><span class="nottickedoff">++ &quot;    (top of stack is on the right hand side)\n\n&quot;)</span></span>
+<span class="lineno">  243 </span><span class="spaces">  </span><span class="istickedoff">where</span>
+<span class="lineno">  244 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">len   = length types</span></span>
+<span class="lineno">  245 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">s =  (if len /= 1 then &quot;s&quot; else &quot;&quot;)</span></span>
+<span class="lineno">  246 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">are =  (if len /= 1 then &quot;are&quot; else &quot;is&quot;)</span></span>
+<span class="lineno">  247 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">the =  (if len /= 1 then &quot;&quot; else &quot; the&quot;)</span></span>
+<span class="lineno">  248 </span><span class="spaces">      </span><span class="istickedoff"><span class="nottickedoff">types = getPrimOpType primOp</span></span></span>
+<span class="lineno">  249 </span>
+<span class="lineno">  250 </span>
+<span class="lineno">  251 </span>-- Render is somewhat funny, becauase it can only get called at top level.
+<span class="lineno">  252 </span>-- All other operations are purely functional.
+<span class="lineno">  253 </span>
+<span class="lineno">  254 </span>doAllOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; IO Stack
+<span class="lineno">  255 </span><span class="decl"><span class="istickedoff">doAllOp (Render render) Op_render</span>
+<span class="lineno">  256 </span><span class="spaces">                           </span><span class="istickedoff">(VString str:VInt ht:VInt wid:VReal fov</span>
+<span class="lineno">  257 </span><span class="spaces">                           </span><span class="istickedoff">:VInt dep:VObject obj:VArray arr</span>
+<span class="lineno">  258 </span><span class="spaces">                           </span><span class="istickedoff">:VPoint r g b : stk)</span>
+<span class="lineno">  259 </span><span class="spaces">  </span><span class="istickedoff">= do { render (color r g b) lights obj dep (fov * (pi / 180.0)) wid ht <span class="nottickedoff">str</span></span>
+<span class="lineno">  260 </span><span class="spaces">       </span><span class="istickedoff">; return <span class="nottickedoff">stk</span></span>
+<span class="lineno">  261 </span><span class="spaces">       </span><span class="istickedoff">}</span>
+<span class="lineno">  262 </span><span class="spaces">  </span><span class="istickedoff">where</span>
+<span class="lineno">  263 </span><span class="spaces">      </span><span class="istickedoff">lights = [ light | (VLight light) &lt;- elems arr ]</span>
+<span class="lineno">  264 </span><span class="spaces"></span><span class="istickedoff"></span>
+<span class="lineno">  265 </span><span class="spaces"></span><span class="istickedoff">doAllOp primOp op stk = doPrimOp primOp <span class="nottickedoff">op</span> stk</span></span> -- call the purely functional operators
+<span class="lineno">  266 </span>
+<span class="lineno">  267 </span>------------------------------------------------------------------------------
+<span class="lineno">  268 </span>{-
+<span class="lineno">  269 </span> - Abstract evaluation.
+<span class="lineno">  270 </span> -
+<span class="lineno">  271 </span> - The idea is you check for constant code that 
+<span class="lineno">  272 </span> - (1) does not look at its arguments
+<span class="lineno">  273 </span> - (2) gives a fixed result
+<span class="lineno">  274 </span> -
+<span class="lineno">  275 </span> - We run for 100 steps.
+<span class="lineno">  276 </span> -
+<span class="lineno">  277 </span> -}
+<span class="lineno">  278 </span>
+<span class="lineno">  279 </span>absapply :: Env -&gt; Code -&gt; Stack -&gt; Maybe Stack
+<span class="lineno">  280 </span><span class="decl"><span class="istickedoff">absapply env code stk = </span>
+<span class="lineno">  281 </span><span class="spaces">     </span><span class="istickedoff">case runAbs (eval (State env stk code)) 100 of</span>
+<span class="lineno">  282 </span><span class="spaces">       </span><span class="istickedoff">AbsState stk _ -&gt; <span class="nottickedoff">Just stk</span></span>
+<span class="lineno">  283 </span><span class="spaces">       </span><span class="istickedoff">AbsFail m      -&gt; Nothing</span></span>
+<span class="lineno">  284 </span>
+<span class="lineno">  285 </span>newtype Abs a   = Abs { runAbs :: Int -&gt; AbsState a }
+<span class="lineno">  286 </span>data AbsState a = AbsState a !Int
+<span class="lineno">  287 </span>                | AbsFail String
+<span class="lineno">  288 </span>
+<span class="lineno">  289 </span>instance Monad Abs where
+<span class="lineno">  290 </span>    <span class="decl"><span class="istickedoff">(Abs fn) &gt;&gt;= k = Abs (\ s -&gt; case fn s of</span>
+<span class="lineno">  291 </span><span class="spaces">                                   </span><span class="istickedoff">AbsState r s' -&gt; runAbs (k r) s'</span>
+<span class="lineno">  292 </span><span class="spaces">                                   </span><span class="istickedoff">AbsFail m     -&gt; AbsFail <span class="nottickedoff">m</span>)</span></span>
+<span class="lineno">  293 </span>    <span class="decl"><span class="istickedoff">return x     = Abs (\ n -&gt; AbsState x n)</span></span>
+<span class="lineno">  294 </span>    <span class="decl"><span class="istickedoff">fail s       = Abs (\ n -&gt; AbsFail <span class="nottickedoff">s</span>)</span></span>
+<span class="lineno">  295 </span>
+<span class="lineno">  296 </span>instance MonadEval Abs where
+<span class="lineno">  297 </span>  <span class="decl"><span class="istickedoff">doOp = doAbsOp</span></span>
+<span class="lineno">  298 </span>  <span class="decl"><span class="istickedoff">err  = fail</span></span>
+<span class="lineno">  299 </span>  <span class="decl"><span class="istickedoff">tick = Abs (\ n -&gt; if <span class="tickonlyfalse">n &lt;= 0</span></span>
+<span class="lineno">  300 </span><span class="spaces">                     </span><span class="istickedoff">then <span class="nottickedoff">AbsFail &quot;run out of time&quot;</span></span>
+<span class="lineno">  301 </span><span class="spaces">                     </span><span class="istickedoff">else AbsState <span class="nottickedoff">()</span> (n-1))</span></span>
+<span class="lineno">  302 </span>
+<span class="lineno">  303 </span>doAbsOp :: PrimOp -&gt; GMLOp -&gt; Stack -&gt; Abs Stack
+<span class="lineno">  304 </span><span class="decl"><span class="istickedoff">doAbsOp _ Op_point (VReal r3:VReal r2:VReal r1:stk) </span>
+<span class="lineno">  305 </span><span class="spaces">               </span><span class="istickedoff">= <span class="nottickedoff">return ((VPoint r1 r2 r3) : stk)</span></span>
+<span class="lineno">  306 </span><span class="spaces"> </span><span class="istickedoff">-- here, you could have an (AbsPoint :: AbsObj) which you put on the</span>
+<span class="lineno">  307 </span><span class="spaces"> </span><span class="istickedoff">-- stack, with any object in the three fields.</span>
+<span class="lineno">  308 </span><span class="spaces"></span><span class="istickedoff">doAbsOp _ op _ = err <span class="nottickedoff">(&quot;operator not understood (&quot; ++ show op ++ &quot;)&quot;)</span></span></span>
+<span class="lineno">  309 </span>
+<span class="lineno">  310 </span>------------------------------------------------------------------------------
+<span class="lineno">  311 </span>-- Driver
+<span class="lineno">  312 </span>
+<span class="lineno">  313 </span>mainEval :: Code -&gt; IO ()
+<span class="lineno">  314 </span><span class="decl"><span class="istickedoff">mainEval prog = do { stk &lt;- eval (State <span class="nottickedoff">emptyEnv</span> [] prog) </span>
+<span class="lineno">  315 </span><span class="spaces">                   </span><span class="istickedoff">; return <span class="nottickedoff">()</span></span>
+<span class="lineno">  316 </span><span class="spaces">                   </span><span class="istickedoff">}</span></span>
+<span class="lineno">  317 </span>{- 
+<span class="lineno">  318 </span>  * Oops, one of the example actually has something
+<span class="lineno">  319 </span>  * on the stack at the end. 
+<span class="lineno">  320 </span>  * Oh well...
+<span class="lineno">  321 </span>                  ; if null stk
+<span class="lineno">  322 </span>                     then return ()
+<span class="lineno">  323 </span>                    else do { putStrLn done
+<span class="lineno">  324 </span>                             ; print stk
+<span class="lineno">  325 </span>                             }
+<span class="lineno">  326 </span>-}
+<span class="lineno">  327 </span>
+<span class="lineno">  328 </span><span class="decl"><span class="nottickedoff">done = &quot;Items still on stack at (successfull) termination of program&quot;</span></span>
+<span class="lineno">  329 </span>
+<span class="lineno">  330 </span>------------------------------------------------------------------------------
+<span class="lineno">  331 </span>-- testing
+<span class="lineno">  332 </span>
+<span class="lineno">  333 </span>test :: String -&gt; Pure Stack
+<span class="lineno">  334 </span><span class="decl"><span class="nottickedoff">test is = eval (State emptyEnv [] (rayParse is))</span></span>
+<span class="lineno">  335 </span>
+<span class="lineno">  336 </span>testF :: String -&gt; IO Stack
+<span class="lineno">  337 </span><span class="decl"><span class="nottickedoff">testF is = do prog &lt;- rayParseF is</span>
+<span class="lineno">  338 </span><span class="spaces">              </span><span class="nottickedoff">eval (State emptyEnv [] prog)</span></span>
+<span class="lineno">  339 </span>
+<span class="lineno">  340 </span>testA :: String -&gt; Either String (Stack,Int)
+<span class="lineno">  341 </span><span class="decl"><span class="nottickedoff">testA is = case runAbs (eval (State emptyEnv </span>
+<span class="lineno">  342 </span><span class="spaces">                                    </span><span class="nottickedoff">[VAbsObj AbsFACE,VAbsObj AbsU,VAbsObj AbsV]</span>
+<span class="lineno">  343 </span><span class="spaces">                                    </span><span class="nottickedoff">(rayParse is))) 100 of</span>
+<span class="lineno">  344 </span><span class="spaces">             </span><span class="nottickedoff">AbsState a n -&gt; Right (a,n)</span>
+<span class="lineno">  345 </span><span class="spaces">             </span><span class="nottickedoff">AbsFail m -&gt; Left m</span></span>
+<span class="lineno">  346 </span>
+<span class="lineno">  347 </span><span class="decl"><span class="nottickedoff">abstest1 = &quot;1.0 0.0 0.0 point /red { /v /u /face red 1.0 0.0 1.0 } apply&quot;</span></span> 
+<span class="lineno">  348 </span>
+<span class="lineno">  349 </span>-- should be [3:: Int]
+<span class="lineno">  350 </span><span class="decl"><span class="nottickedoff">et1 = test &quot;1 /x { x } /f 2 /x f apply x addi&quot;</span></span>
+<span class="lineno">  351 </span>
+<span class="lineno">  352 </span>
+<span class="lineno">  353 </span>
+<span class="lineno">  354 </span>
+<span class="lineno">  355 </span>
 
 </pre>
 </html>
@@ -2760,16 +2760,16 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">41%</td><td>17/41</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">41%</td><td>5/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">60%</td><td>381/635</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="60%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Data.hs.html">Data</a></tt></td>
-<td align="right">22%</td><td>10/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>2/51</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>254/647</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">22%</td><td>10/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>2/51</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>254/646</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Eval.hs.html">Eval</a></tt></td>
-<td align="right">62%</td><td>22/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="62%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">59%</td><td>40/67</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="59%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>361/629</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">62%</td><td>22/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="62%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">59%</td><td>40/67</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="59%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>361/628</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Geometry.hs.html">Geometry</a></tt></td>
 <td align="right">58%</td><td>42/72</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="58%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">40%</td><td>4/10</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="40%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">70%</td><td>300/427</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="70%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Illumination.hs.html">Illumination</a></tt></td>
-<td align="right">45%</td><td>11/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>16/42</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">44%</td><td>299/679</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="44%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">45%</td><td>11/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>16/42</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">44%</td><td>299/678</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="44%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Intersections.hs.html">Intersections</a></tt></td>
 <td align="right">63%</td><td>14/22</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">42%</td><td>35/83</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>382/1001</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@@ -2793,7 +2793,7 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">36%</td><td>4/11</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="36%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">35%</td><td>7/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">18%</td><td>43/231</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="18%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr></tr><tr style="background: #e0e0e0">
 <th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
-<td align="right">49%</td><td>146/295</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="49%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>124/322</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>2292/4718</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">49%</td><td>146/295</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="49%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>124/322</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>2292/4715</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 </table></html>
 Writing: hpc_index_fun.html
 <html><style type="text/css">table.bar { background-color: #f25913; }
@@ -2815,7 +2815,7 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">63%</td><td>14/22</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">42%</td><td>35/83</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>382/1001</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Eval.hs.html">Eval</a></tt></td>
-<td align="right">62%</td><td>22/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="62%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">59%</td><td>40/67</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="59%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>361/629</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">62%</td><td>22/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="62%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">59%</td><td>40/67</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="59%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>361/628</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Geometry.hs.html">Geometry</a></tt></td>
 <td align="right">58%</td><td>42/72</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="58%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">40%</td><td>4/10</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="40%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">70%</td><td>300/427</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="70%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@@ -2824,7 +2824,7 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">47%</td><td>8/17</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="47%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>9/23</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">41%</td><td>69/165</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Illumination.hs.html">Illumination</a></tt></td>
-<td align="right">45%</td><td>11/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>16/42</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">44%</td><td>299/679</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="44%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">45%</td><td>11/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>16/42</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">44%</td><td>299/678</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="44%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Construct.hs.html">Construct</a></tt></td>
 <td align="right">41%</td><td>17/41</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">41%</td><td>5/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">60%</td><td>381/635</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="60%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@@ -2833,7 +2833,7 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">36%</td><td>4/11</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="36%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">35%</td><td>7/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">18%</td><td>43/231</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="18%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Data.hs.html">Data</a></tt></td>
-<td align="right">22%</td><td>10/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>2/51</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>254/647</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">22%</td><td>10/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>2/51</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>254/646</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Primitives.hs.html">Primitives</a></tt></td>
 <td align="right">16%</td><td>1/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">20%</td><td>5/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@@ -2845,7 +2845,7 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td></tr>
 <tr></tr><tr style="background: #e0e0e0">
 <th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
-<td align="right">49%</td><td>146/295</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="49%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>124/322</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>2292/4718</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">49%</td><td>146/295</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="49%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>124/322</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>2292/4715</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 </table></html>
 Writing: hpc_index_alt.html
 <html><style type="text/css">table.bar { background-color: #f25913; }
@@ -2858,14 +2858,14 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <table class="dashboard" width="100%" border=1>
 <tr><th rowspan=2><a href="hpc_index.html">module</a></th><th colspan=3><a href="hpc_index_fun.html">Top Level Definitions</a></th><th colspan=3><a href="hpc_index_alt.html">Alternatives</a></th><th colspan=3><a href="hpc_index_exp.html">Expressions</a></th></tr><tr><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th></tr><tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Eval.hs.html">Eval</a></tt></td>
-<td align="right">62%</td><td>22/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="62%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">59%</td><td>40/67</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="59%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>361/629</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
-<tr>
-<td>&nbsp;&nbsp;<tt>module <a href="Intersections.hs.html">Intersections</a></tt></td>
-<td align="right">63%</td><td>14/22</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">42%</td><td>35/83</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>382/1001</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">62%</td><td>22/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="62%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">59%</td><td>40/67</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="59%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>361/628</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Parse.hs.html">Parse</a></tt></td>
 <td align="right">80%</td><td>16/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="80%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">42%</td><td>6/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">72%</td><td>192/264</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="72%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
+<td>&nbsp;&nbsp;<tt>module <a href="Intersections.hs.html">Intersections</a></tt></td>
+<td align="right">63%</td><td>14/22</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">42%</td><td>35/83</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>382/1001</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Construct.hs.html">Construct</a></tt></td>
 <td align="right">41%</td><td>17/41</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">41%</td><td>5/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">60%</td><td>381/635</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="60%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
@@ -2876,28 +2876,28 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">47%</td><td>8/17</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="47%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>9/23</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">41%</td><td>69/165</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Illumination.hs.html">Illumination</a></tt></td>
-<td align="right">45%</td><td>11/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>16/42</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">44%</td><td>299/679</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="44%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">45%</td><td>11/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>16/42</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">44%</td><td>299/678</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="44%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Surface.hs.html">Surface</a></tt></td>
 <td align="right">36%</td><td>4/11</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="36%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">35%</td><td>7/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">18%</td><td>43/231</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="18%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Data.hs.html">Data</a></tt></td>
-<td align="right">22%</td><td>10/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>2/51</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>254/647</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">22%</td><td>10/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>2/51</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>254/646</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Main.hs.html">Main</a></tt></td>
 <td align="right">100%</td><td>1/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
-<td>&nbsp;&nbsp;<tt>module <a href="Primitives.hs.html">Primitives</a></tt></td>
-<td align="right">16%</td><td>1/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">20%</td><td>5/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td>&nbsp;&nbsp;<tt>module <a href="CSG.hs.html">CSG</a></tt></td>
+<td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Misc.hs.html">Misc</a></tt></td>
 <td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">0%</td><td>0/10</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
 <tr>
-<td>&nbsp;&nbsp;<tt>module <a href="CSG.hs.html">CSG</a></tt></td>
-<td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td></tr>
+<td>&nbsp;&nbsp;<tt>module <a href="Primitives.hs.html">Primitives</a></tt></td>
+<td align="right">16%</td><td>1/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">20%</td><td>5/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr></tr><tr style="background: #e0e0e0">
 <th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
-<td align="right">49%</td><td>146/295</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="49%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>124/322</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>2292/4718</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">49%</td><td>146/295</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="49%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>124/322</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>2292/4715</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 </table></html>
 Writing: hpc_index_exp.html
 <html><style type="text/css">table.bar { background-color: #f25913; }
@@ -2922,16 +2922,16 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">41%</td><td>17/41</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">41%</td><td>5/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">60%</td><td>381/635</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="60%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Eval.hs.html">Eval</a></tt></td>
-<td align="right">62%</td><td>22/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="62%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">59%</td><td>40/67</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="59%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>361/629</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">62%</td><td>22/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="62%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">59%</td><td>40/67</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="59%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>361/628</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Illumination.hs.html">Illumination</a></tt></td>
-<td align="right">45%</td><td>11/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>16/42</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">44%</td><td>299/679</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="44%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">45%</td><td>11/24</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>16/42</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">44%</td><td>299/678</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="44%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Interval.hs.html">Interval</a></tt></td>
 <td align="right">47%</td><td>8/17</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="47%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>9/23</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">41%</td><td>69/165</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="41%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Data.hs.html">Data</a></tt></td>
-<td align="right">22%</td><td>10/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>2/51</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>254/647</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">22%</td><td>10/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>2/51</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">39%</td><td>254/646</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="39%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 <tr>
 <td>&nbsp;&nbsp;<tt>module <a href="Intersections.hs.html">Intersections</a></tt></td>
 <td align="right">63%</td><td>14/22</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">42%</td><td>35/83</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>382/1001</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@@ -2949,7 +2949,7 @@ table.dashboard { border-collapse: collapse  ; border: solid 1px black }
 <td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td></tr>
 <tr></tr><tr style="background: #e0e0e0">
 <th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
-<td align="right">49%</td><td>146/295</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="49%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>124/322</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>2292/4718</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
+<td align="right">49%</td><td>146/295</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="49%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">38%</td><td>124/322</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="38%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>2292/4715</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
 </table></html>