diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# 3.3.0.0
+
+  * Allow decimal specifiers in format strings
+  * Add `--header` (and `:set header;`) which includes match in record.
+
 # 3.2.0.1
 
   * Include file in errors
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -3,12 +3,16 @@
 module Main (main) where
 
 import           A
-import           Control.DeepSeq    (NFData (..))
+import           Control.DeepSeq (NFData (..))
 import           Criterion.Main
-import qualified Data.Text.IO       as TIO
+import qualified Data.Text.IO    as TIO
 import           File
-import           System.IO.Silently (silence)
+import           System.IO       (IOMode (WriteMode), withFile)
 
+hrun ifp e m fp = withFile "/dev/null" WriteMode $ \h -> runOnFile [] "(bench)" e [] m fp h
+runs e m fp = nfIO $ hrun "(bench)" e m fp
+fruns ifp m fp = nfIO $ do { contents <- TIO.readFile ifp; hrun ifp contents m fp }
+
 main :: IO ()
 main =
     defaultMain [ bgroup "eval"
@@ -16,20 +20,23 @@
                       , bench "exprEval" $ nf exprEval "reintercalate ' ' (split '01-23-1987' /-/)"
                       ]
                 , bgroup "csv"
-                      [ bench "dedup" $ nfIO (silence $ runOnFile [] "" "~.{ix>1}{`8}" [] CSV "bench/data/food-prices.csv")
-                      , bench "succdiff" $ nfIO (silence $ runOnFile [] "" "(%)\\. {%/Apple/}{`3:}" [] CSV "bench/data/food-prices.csv")
+                      [ bench "dedup" $ runs "~.{ix>1}{`8}" CSV "bench/data/food-prices.csv"
+                      , bench "succdiff" $ runs "(%)\\. {%/Apple/}{`3:}" CSV "bench/data/food-prices.csv"
                       ]
+                , bgroup "report"
+                      [ bench "ghc-filt" $ fruns "test/examples/ghc-filt.jac" awk "test/data/ghc" ]
                 , bgroup "stream"
-                      [ bench "path" $ nfIO (silence $ runOnFile [] "" "{|[x+'\\n'+y]|>`$}" [] (AWK (Just ":") Nothing) "bench/data/PATH")
-                      , bench "RS" $ nfIO (silence $ runOnFile [] "" "$0" [] (AWK Nothing (Just ":")) "bench/data/PATH")
-                      , bench "runOnFile" $ nfIO (silence $ runOnFile [] "" "(+)|0 {%/Bloom/}{1}" [] (AWK Nothing Nothing) "bench/data/ulysses.txt")
-                      , bench "runOnFile/wc.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/wc.jac" ; runOnFile [] "examples/wc.jac" contents [] (AWK Nothing Nothing) "bench/data/ulysses.txt" })
-                      , bench "runOnFile/span2.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/span2.jac" ; runOnFile [] "examples/span2.jac" contents [] (AWK Nothing Nothing) "bench/data/span.txt" })
-                      , bench "sedstream.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/sedstream.jac" ; runOnFile [] "examples/sedstream.jac" contents [] (AWK Nothing Nothing) "bench/data/lines.txt" })
-                      , bench "gnused.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/gnused.jac" ; runOnFile [] "exampes/gnused.jac" contents [] (AWK Nothing Nothing) "bench/data/lines.txt" })
-                      -- , bench "fungnused.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/fungnused.jac" ; runOnFile [] contents (AWK Nothing Nothing) "bench/data/lines.txt" })
-                      , bench "hsLibversionMac.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/hsLibversionMac.jac"; runOnFile [] "examples/hsLibVersionMac.jac" contents [] (AWK Nothing Nothing) "bench/data/pandoc-mac" })
-                      , bench "sedsmtp.jac" $ nfIO (silence $ do { contents <- TIO.readFile "examples/sedsmtp.jac" ; runOnFile [] "examples/sedsmtp.jac" contents [] (AWK Nothing Nothing) "test/examples/data/2.txt" })
+                      [ bench "sprintf" $ runs "{%/infix(r|l)?\\s+\\d+/}{sprintf '- fixity: %s' `0}" awk "src/A.hs"
+                      , bench "path" $ runs "{|[x+'\\n'+y]|>`$}" (AWK (Just ":") Nothing False) "bench/data/PATH"
+                      , bench "RS" $ runs "$0" (AWK Nothing (Just ":") False) "bench/data/PATH"
+                      , bench "runOnFile" $ runs "(+)|0 {%/Bloom/}{1}" awk "bench/data/ulysses.txt"
+                      , bench "runOnFile/wc.jac" $ fruns "examples/wc.jac" awk "bench/data/ulysses.txt"
+                      , bench "runOnFile/span2.jac" $ fruns "examples/span2.jac" awk "bench/data/span.txt"
+                      , bench "sedstream.jac" $ fruns "examples/sedstream.jac" awk "bench/data/lines.txt"
+                      , bench "gnused.jac" $ fruns "examples/gnused.jac" awk "bench/data/lines.txt"
+                      -- , bench "fungnused.jac" $ fruns "examples/fungnused.jac" awk "bench/data/lines.txt" }
+                      , bench "hsLibversionMac.jac" $ fruns "examples/hsLibversionMac.jac" awk "bench/data/pandoc-mac"
+                      , bench "sedsmtp.jac" $ fruns "examples/sedsmtp.jac" awk "test/examples/data/2.txt"
                       ]
                 ]
 
diff --git a/doc/guide.pdf b/doc/guide.pdf
Binary files a/doc/guide.pdf and b/doc/guide.pdf differ
diff --git a/examples/evenOdd.jac b/examples/evenOdd.jac
new file mode 100644
--- /dev/null
+++ b/examples/evenOdd.jac
@@ -0,0 +1,14 @@
+fn count(x) ≔
+  fold (+) 0 (([:1)"x);
+
+fn isEven() :=
+  (~ /(0|2|4|6|8)$/);
+
+fn isOdd() :=
+  (~ /(1|3|5|7|9)$/);
+
+let
+  val even := count (isEven #. $0)
+  val odd := count (isOdd #. $0)
+  val total := odd + even
+in (total . even . odd) end
diff --git a/examples/latestCabal.jac b/examples/latestCabal.jac
new file mode 100644
--- /dev/null
+++ b/examples/latestCabal.jac
@@ -0,0 +1,5 @@
+:set header;
+:set rs:=/\n[^:\n]*:/;
+:set fs:=/\s*,\s*/;
+
+[x ~* 1 /(\d+(\.\d+)*)/]:?{%/Versions available:/}{[y]|>`$}
diff --git a/examples/otool/dllibs.jac b/examples/otool/dllibs.jac
new file mode 100644
--- /dev/null
+++ b/examples/otool/dllibs.jac
@@ -0,0 +1,5 @@
+{. otool -l $(locate libapple.dylib) | ja run dllibs.jac
+:set rs:=/Load command/;
+:set fs:=/ *\n */;
+
+.?{`2 ~ /^cmd LC_LOAD_DYLIB$/}{`0 ~* 1 /\n *name ([^\s]+)/}
diff --git a/examples/otool/rpath.jac b/examples/otool/rpath.jac
new file mode 100644
--- /dev/null
+++ b/examples/otool/rpath.jac
@@ -0,0 +1,5 @@
+{. otool -l $(locate libapple.dylib) | ja run rpath.jac
+:set rs:=/Load command/;
+:set fs:=/ *\n */;
+
+.?{`2 ~ /^cmd LC_RPATH$/}{`0 ~* 1 /\n *path ([^\s]+)/}
diff --git a/examples/tagsex.jac b/examples/tagsex.jac
new file mode 100644
--- /dev/null
+++ b/examples/tagsex.jac
@@ -0,0 +1,12 @@
+fn mkEx(s) :=
+  '/^' + s + '$/;';
+
+{. TODO: insert \zs at precise identifier! https://stackoverflow.com/a/31089753/11296354
+
+fn processStr(s) :=
+  let
+    val line := split s /[ \(:]+/
+    val outLine := sprintf '%s\t%s\t%s' (line.3 . fp . mkEx s)
+  in outLine end;
+
+processStr¨{%/fn +[[:lower:]][[:latin:]]*.*:=/}{`0}
diff --git a/jacinda.cabal b/jacinda.cabal
--- a/jacinda.cabal
+++ b/jacinda.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               jacinda
-version:            3.2.0.1
+version:            3.3.0.0
 license:            AGPL-3.0-only
 license-file:       COPYING
 maintainer:         vamchale@gmail.com
@@ -27,6 +27,27 @@
     doc/guide.pdf
     test/examples/*.jac
     examples/*.jac
+    examples/otool/*.jac
+    test/golden/*.out
+    test/data/a.csv
+    test/data/cabal-info
+    test/data/cabal-plan
+    test/data/cdeps
+    test/data/download.html
+    test/data/env
+    test/data/food-prices.csv
+    test/data/fut-ctags
+    test/data/ghc
+    test/data/ghc-pkg
+    test/data/git-tags
+    test/data/ls
+    test/data/otool
+    test/data/py-ver
+    test/data/python-site
+    test/data/r-version
+    test/data/readelf
+    test/data/trailingWhitespace
+    test/data/url
 
 source-repository head
     type:     git
@@ -50,10 +71,8 @@
     exposed-modules:
         File
         A
-        Parser
-        Parser.Rw
         Ty
-        Ty.Const
+        Parser
         Jacinda.Regex
 
     hs-source-dirs:   src
@@ -64,6 +83,8 @@
         Nm
         U
         R
+        Parser.Rw
+        Ty.Const
         Jacinda.Check.Field
         Jacinda.Backend.Const
         Jacinda.Backend.T
@@ -97,9 +118,11 @@
         deepseq,
         lazy-csv
 
-    other-extensions:
+    default-extensions:
         DeriveFunctor
         OverloadedStrings
+
+    other-extensions:
         DeriveAnyClass
         DeriveGeneric
         DeriveFoldable
@@ -135,10 +158,12 @@
     build-depends:
         base,
         jacinda-lib,
-        tasty,
         bytestring,
-        text,
-        tasty-hunit
+        tasty,
+        tasty-golden,
+        tasty-hunit,
+        temporary,
+        text
 
 benchmark jacinda-bench
     import:           warnings
@@ -152,5 +177,4 @@
         criterion,
         jacinda-lib,
         deepseq,
-        text,
-        silently
+        text
diff --git a/lib/prefixSizes.jac b/lib/prefixSizes.jac
--- a/lib/prefixSizes.jac
+++ b/lib/prefixSizes.jac
@@ -1,11 +1,11 @@
 fn prettyMem(x) :=
   ?x>=1073741824.0
-  ;sprintf'%f GB' (x%1073741824.0)
+  ;sprintf'%f.2 GB' (x%1073741824.0)
   ;?x>=1048576.0
-   ;sprintf'%f MB' (x%1048576.0)
+   ;sprintf'%f.2 MB' (x%1048576.0)
    ;?x>=1024.0
-    ;sprintf'%f kB' (x%1024.0)
-    ;sprintf'%f b' x;
+    ;sprintf'%f.2 kB' (x%1024.0)
+    ;sprintf'%f.0 b' x;
 
 {. du reports memory in bytes by default
 fn duMem(x) := prettyMem(x*1024.0);
diff --git a/man/ja.1 b/man/ja.1
--- a/man/ja.1
+++ b/man/ja.1
@@ -39,6 +39,9 @@
 \f[B]\-\-csv\f[R]
 Process as CSV
 .TP
+\f[B]\-b\f[R] \f[B]\-\-header\f[R]
+Include match when splitting records
+.TP
 \f[B]\-Dfile=main.c\f[R]
 Define variable
 .SH LANGUAGE
@@ -174,6 +177,10 @@
 \f[B]drop#, take#\f[R]
 Int \-> List a \-> List a
 .SS SYNTAX
+\f[B]\[aq]str\[aq]\f[R] string literal
+.PP
+\f[B]/pat/\f[R] regex literal
+.PP
 \f[B]\[ga]n\f[R] nth field
 .PP
 \f[B]\[ga]0\f[R] current line
@@ -233,6 +240,8 @@
 .PP
 \f[B]:set rs=/REGEX/;\f[R] Set record separator
 .PP
+\f[B]:set header;\f[R] Include match when splitting records
+.PP
 \f[B]:set csv;\f[R] Process as CSV
 .PP
 \f[B]:flush;\f[R] Flush stdout for every line
@@ -251,7 +260,7 @@
 Select only the third line
 .TP
 :set csv; {ix=1}{[x+\[aq]\[rs]n\[aq]+y]|>\[ga]$}
-Present column names of a .csv file, one per line
+Present column names of a .csv file
 .TP
 (+)|0 $1:i
 Sum first column
@@ -277,11 +286,11 @@
 [y]|> {|\[ga]0\[ti]/\[ha]$/}
 Is the last line blank?
 .TP
-{|option ⍬ [x] (\[ga]0 \[ti]* 1 /\[ha]((\[rs]s+\[rs]S|\[rs]S)*)$/)}
+{|option ⍬ [x] (\[ga]0 \[ti]* 1 /\[ha]((\[rs]s+\[rs]S|\[rs]S)*)\[rs]s*$/)}
 Trim trailing whitespace
 .TP
 ja \-R\[aq]\[rs]n\[rs]s*\[aq] \[dq][x+\[aq] \[aq]+y]|>\[rs]$0\[dq]
-Concatenate into one line, discarding extra leading whitespace between
+Concatenate into one line, discarding leading whitespace between
 .SH BUGS
 Please report any bugs you may come across to
 https://github.com/vmchale/jacinda/issues
diff --git a/src/A.hs b/src/A.hs
--- a/src/A.hs
+++ b/src/A.hs
@@ -1,13 +1,11 @@
-{-# LANGUAGE DeriveAnyClass    #-}
-{-# LANGUAGE DeriveFunctor     #-}
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric  #-}
 
 module A ( E (..), T (..), (~>), TB (..), C (..)
          , L (..), N (..), BBin (..), BTer (..)
          , BUn (..), DfnVar (..)
          , D (..), Program (..)
-         , Mode (..)
+         , Mode (..), awk
          , mapExpr
          , getS, flushD
          ) where
@@ -373,7 +371,7 @@
 -- decl
 data D a = SetFS T.Text | SetRS T.Text
          | FunDecl (Nm a) [Nm a] (E a)
-         | FlushDecl
+         | FlushDecl | SetH
          | SetAsv | SetUsv | SetCsv
          | SetOFS T.Text | SetORS T.Text
          deriving (Functor)
@@ -383,6 +381,7 @@
     pretty (SetRS rs)       = ":set rs :=" <+> "/" <> pretty rs <> "/;"
     pretty (FunDecl n ns e) = "fn" <+> pretty n <> tupled (pretty <$> ns) <+> ":=" <#> indent 2 (pretty e <> ";")
     pretty FlushDecl        = ":flush;"
+    pretty SetH             = ":set header;"
     pretty SetAsv           = ":set asv;"
     pretty SetUsv           = ":set usv;"
     pretty SetCsv           = ":set csv;"
@@ -399,16 +398,19 @@
 flushD :: Program a -> Bool
 flushD (Program ds _) = any p ds where p FlushDecl = True; p _ = False
 
-data Mode = CSV | AWK (Maybe T.Text) (Maybe T.Text) -- field, record
+awk = AWK Nothing Nothing False
 
+data Mode = CSV | AWK (Maybe T.Text) (Maybe T.Text) Bool -- field, record, include header in record split
+
 getS :: Program a -> Mode
-getS (Program ds _) = foldl' go (AWK Nothing Nothing) ds where
-    go (AWK _ rs) (SetFS bs) = AWK (Just bs) rs
-    go _ SetAsv              = AWK (Just "\\x1f") (Just "\\x1e")
-    go _ SetUsv              = AWK (Just "␞") (Just "␟")
-    go _ SetCsv              = CSV
-    go (AWK fs _) (SetRS bs) = AWK fs (Just bs)
-    go next _                = next
+getS (Program ds _) = foldl' go awk ds where
+    go (AWK _ rs b) (SetFS bs) = AWK (Just bs) rs b
+    go _ SetAsv                = AWK (Just "\\x1f") (Just "\\x1e") False
+    go _ SetUsv                = AWK (Just "␞") (Just "␟") False
+    go _ SetCsv                = CSV
+    go (AWK fs _ b) (SetRS bs) = AWK fs (Just bs) b
+    go (AWK fs rs _) SetH      = AWK fs rs True
+    go next _                  = next
 
 mapExpr :: (E a -> E a) -> Program a -> Program a
 mapExpr f (Program ds e) = Program ds (f e)
diff --git a/src/A/E.hs b/src/A/E.hs
--- a/src/A/E.hs
+++ b/src/A/E.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module A.E ( M, nN, eta ) where
 
 import           A
diff --git a/src/A/I.hs b/src/A/I.hs
--- a/src/A/I.hs
+++ b/src/A/I.hs
@@ -35,7 +35,7 @@
 iD :: D T -> RM T ()
 iD (FunDecl n [] e) = do {eI <- iE e; bind n eI}
 iD SetFS{} = pure (); iD SetRS{} = pure (); iD SetAsv = pure (); iD SetUsv = pure (); iD SetCsv = pure ()
-iD SetORS{} = pure (); iD SetOFS{} = pure (); iD FlushDecl{} = pure ()
+iD SetORS{} = pure (); iD SetOFS{} = pure (); iD FlushDecl{} = pure (); iD SetH{} = pure ()
 iD FunDecl{} = desugar
 
 desugar = error "Internal error. Should have been de-sugared in an earlier stage!"
diff --git a/src/File.hs b/src/File.hs
--- a/src/File.hs
+++ b/src/File.hs
@@ -1,6 +1,4 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module File ( tcIO, tySrc
+module File ( tcIO
             , runStdin, runOnFile
             , exprEval
             ) where
@@ -34,7 +32,7 @@
 import           Prettyprinter                    (Pretty (pretty))
 import           R
 import           Regex.Rure                       (RurePtr)
-import           System.IO                        (stdin)
+import           System.IO                        (Handle, stdin, stdout)
 import           Text.CSV.Lazy.ByteString         (CSVField (..), parseCSV)
 import           Ty
 
@@ -148,21 +146,23 @@
            -> [(T.Text, Value)]
            -> Mode
            -> BSL.ByteString
+           -> Handle -- ^ Out handle
            -> IO ()
-runOnBytes incls fp fn src vars mode contents = do
+runOnBytes incls fp fn src vars mode contents h = do
     incls' <- defaultIncludes <*> pure incls
     (ast, m) <- parsePWithMax incls' fn src vars
     (typed, i) <- yIO fn $ runTyM m (tyP ast)
     let (eI, j) = ib i typed
     m'Throw $ cF eI
     let (e', k) = runState (eta eI) j
-        cont=run (flushD typed) k (compileR (encodeUtf8 $ T.pack fp) e')
+        cont=run h (flushD typed) k (compileR (encodeUtf8 $ T.pack fp) e')
     case (mode, getS ast) of
-        (AWK cliFS cliRS, AWK afs ars) ->
+        (AWK cliFS cliRS cliH, AWK afs ars ah) ->
             let r=compileFS (cliFS <|> afs)
-                bs=case cliRS <|> ars of
-                    Nothing -> fmap BSL.toStrict (ASCIIL.lines contents)
-                    Just rs -> lazySplit (tcompile rs) contents
+                bs=case (cliRS <|> ars, cliH||ah) of
+                    (Nothing, _)     -> fmap BSL.toStrict (ASCIIL.lines contents)
+                    (Just rs, False) -> lazySplit (tcompile rs) contents
+                    (Just rs, True)  -> lazySplitH (tcompile rs) contents
                 ctxs=zipWith (\ ~(x,y) z -> (x,y,z)) [(b, splitBy r b) | b <- bs] [1..]
             in cont ctxs
         (CSV, _) -> let ctxs = csvCtx contents in cont ctxs
@@ -174,7 +174,7 @@
          -> [(T.Text, Value)]
          -> Mode
          -> IO ()
-runStdin is src fn vars m = runOnBytes is "(stdin)" src fn vars m =<< BSL.hGetContents stdin
+runStdin is src fn vars m = do {b <- BSL.hGetContents stdin; runOnBytes is "(stdin)" src fn vars m b stdout}
 
 runOnFile :: [FilePath]
           -> FilePath
@@ -182,8 +182,9 @@
           -> [(T.Text, Value)]
           -> Mode
           -> FilePath
+          -> Handle -- ^ May need to be closed (lazy bytestring I/O)
           -> IO ()
-runOnFile is fn e vs m fp = runOnBytes is fp fn e vs m =<< BSL.readFile fp
+runOnFile is fn e vs m fp h = do {b <- BSL.readFile fp; runOnBytes is fp fn e vs m b h}
 
 tcIO :: [FilePath] -> FilePath -> T.Text -> IO ()
 tcIO incls fn src = do
@@ -192,12 +193,6 @@
     (pT, i) <- yIO fn $ runTyM m (tyP ast)
     let (eI, _) = ib i pT
     m'Throw $ cF eI
-
-tySrc :: T.Text -> T
-tySrc src =
-    case parseWithMax' src of
-        Right (ast, m) -> yeet $ fst <$> runTyM m (tyOf (expr ast))
-        Left err       -> throw err
 
 m'Throw :: Exception e => Maybe e -> IO ()
 m'Throw = traverse_ throwIO
diff --git a/src/Include.hs b/src/Include.hs
--- a/src/Include.hs
+++ b/src/Include.hs
@@ -7,7 +7,7 @@
 import           Data.List.Split    (splitWhen)
 import           Data.Maybe         (listToMaybe)
 import           Paths_jacinda      (getDataDir)
-import           System.Directory   (doesFileExist, getCurrentDirectory,doesDirectoryExist)
+import           System.Directory   (doesDirectoryExist, doesFileExist, getCurrentDirectory)
 import           System.Environment (lookupEnv)
 import           System.FilePath    ((</>))
 
diff --git a/src/Jacinda/Backend/Printf.hs b/src/Jacinda/Backend/Printf.hs
--- a/src/Jacinda/Backend/Printf.hs
+++ b/src/Jacinda/Backend/Printf.hs
@@ -1,13 +1,11 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module Jacinda.Backend.Printf ( sprintf
-                              ) where
+module Jacinda.Backend.Printf ( sprintf ) where
 
 import           A
 import qualified Data.ByteString                   as BS
 import           Data.ByteString.Builder           (toLazyByteString)
 import           Data.ByteString.Builder.RealFloat (doubleDec)
 import qualified Data.ByteString.Lazy              as BSL
+import           Data.Char                         (isDigit)
 import qualified Data.Text                         as T
 import           Data.Text.Encoding                (decodeUtf8, encodeUtf8)
 
@@ -19,25 +17,44 @@
 pf :: Double -> T.Text
 pf = decodeUtf8 . BSL.toStrict . toLazyByteString . doubleDec
 
--- TODO: interpret precision, like %0.6f %.6
+pd n x = let (l,r) = T.break (=='.') (pf x) in l <> T.take (n+1) r
 
--- FIXME: if next is, say %i and encounter an int in the tuple, that should be an error
+data PF = D !(Maybe Int) | I | B | S
+
+{-# SCC next #-}
+next :: T.Text -> (T.Text, Maybe (PF, T.Text))
+next inp = case T.break (=='%') inp of
+    (p, mfmt) | "%i" `T.isPrefixOf` mfmt -> (p, Just (I, T.drop 2 mfmt))
+              | "%s" `T.isPrefixOf` mfmt -> (p, Just (S, T.drop 2 mfmt))
+              | "%b" `T.isPrefixOf` mfmt -> (p, Just (B, T.drop 2 mfmt))
+              | "%f." `T.isPrefixOf` mfmt -> let s=T.drop 3 mfmt in
+                    case precision s of
+                        Nothing    -> error "Missing digit in format specifier."
+                        Just (n,f) -> (p, Just (D (Just n), f))
+              | "%f" `T.isPrefixOf` mfmt -> (p, Just (D Nothing, T.drop 2 mfmt))
+              | otherwise -> (p, Nothing)
+
+precision :: T.Text -> Maybe (Int, T.Text)
+precision t =
+    let (n,f) = T.span isDigit t  in
+    if T.null n then Nothing else Just (read (T.unpack n), f)
+
+{-# SCC sp #-}
+sp :: T.Text -> [E a] -> T.Text
+sp t [] = t
+sp t (e:es) =
+    case (next t, e) of
+        ((_, Nothing), _)                             -> error "Argument to sprintf has more values than expected by format string."
+        ((p, Just (D Nothing, fmt)), Lit _ (FLit f))  -> p <> pf f <> sp fmt es
+        ((p, Just (D (Just n), fmt)), Lit _ (FLit f)) -> p <> pd n f <> sp fmt es
+        ((p, Just (B, fmt)), Lit _ (BLit b))          -> p <> showBool b <> sp fmt es
+        ((p, Just (I, fmt)), Lit _ (ILit i))          -> p <> T.pack (show i) <> sp fmt es
+        ((p, Just (S, fmt)), Lit _ (StrLit bs))       -> p <> decodeUtf8 bs <> sp fmt es
+        ((_, Just{}), _)                              -> error "Argument type does not match sprintf format string."
+
+  where
+    showBool True = "#t"; showBool False = "#f"
+
 sprintf' :: T.Text -> E a -> T.Text
-sprintf' fmt (Lit _ (FLit f)) =
-    let (prefix, fmt') = T.breakOn "%f" fmt
-        in prefix <> pf f <> T.drop 2 fmt'
-sprintf' fmt (Lit _ (ILit i)) =
-    let (prefix, fmt') = T.breakOn "%i" fmt
-        in prefix <> T.pack (show i) <> T.drop 2 fmt'
-sprintf' fmt (Lit _ (StrLit bs)) =
-    let (prefix, fmt') = T.breakOn "%s" fmt
-        in prefix <> decodeUtf8 bs <> T.drop 2 fmt'
-sprintf' fmt (Tup _ [e]) = sprintf' fmt e
-sprintf' fmt (Tup l (e:es)) =
-    let nextFmt = sprintf' fmt e
-        in sprintf' nextFmt (Tup l es)
-sprintf' fmt (Lit _ (BLit b)) =
-    let (prefix, fmt') = T.breakOn "%b" fmt
-        in prefix <> showBool b <> T.drop 2 fmt'
-    where showBool True  = "true"
-          showBool False = "false"
+sprintf' fmt e@Lit{}    = sp fmt [e]
+sprintf' fmt (Tup _ es) = sp fmt es
diff --git a/src/Jacinda/Backend/T.hs b/src/Jacinda/Backend/T.hs
--- a/src/Jacinda/Backend/T.hs
+++ b/src/Jacinda/Backend/T.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Jacinda.Backend.T ( LineCtx, run, eB ) where
 
 import           A
@@ -7,7 +5,7 @@
 import           C
 import           Control.Exception                 (Exception, throw)
 import           Control.Monad                     (zipWithM, (<=<))
-import           Control.Monad.Trans.State.Strict  (State, evalState, runState, state)
+import           Control.Monad.Trans.State.Strict  (evalState, runState, state)
 import           Data.Bifunctor                    (first, second)
 import qualified Data.ByteString                   as BS
 import           Data.ByteString.Builder           (hPutBuilder)
@@ -30,9 +28,9 @@
 import           Nm
 import           NumParse
 import           Prettyprinter                     (hardline, pretty)
-import           Prettyprinter.Render.Text         (putDoc)
+import           Prettyprinter.Render.Text         (hPutDoc)
 import           Regex.Rure                        (RureMatch (RureMatch), RurePtr)
-import           System.IO                         (hFlush, stdout)
+import           System.IO                         (Handle, hFlush)
 import           Ty.Const
 import           U
 
@@ -47,6 +45,7 @@
              | InternalNm (Nm T)
              | InternalArityOrEta Int (E T)
              | InternalUnexpectedStream (E T)
+             | StreamFunc (E T)
              deriving (Show)
 
 instance Exception EvalErr where
@@ -81,63 +80,62 @@
 
 foldSeq x = foldr seq () x `seq` x
 
-type MM = State Int
-
-nI :: MM Int
+nI :: UM Int
 nI = state (\i -> (i, i+1))
 
-nN :: T -> MM (Nm T)
+nN :: T -> UM (Nm T)
 nN t = do {u <- nI; pure (Nm "fold_hole" (U u) t)}
 
-pSF :: Bool -> (Maybe Tmp, [Tmp]) -> [Env] -> IO ()
-pSF flush (Just t, tt) [e] = do
-    traverse_ (traverse_ (pS flush).(e !)) tt
-    traverse_ (pS flush) (e!t)
-pSF flush c@(_, tt) (e:es) = do
-    traverse_ (traverse_ (pS flush)) [e!t|t <- tt]
-    pSF flush c es
-pSF _ _ [] = pure ()
+pSF :: Handle -> Bool -> (Maybe Tmp, [Tmp]) -> [Env] -> IO ()
+pSF h flush (Just t, tt) [e] = do
+    traverse_ (traverse_ (pS h flush).(e !)) tt
+    traverse_ (pS h flush) (e!t)
+pSF h flush c@(_, tt) (e:es) = do
+    traverse_ (traverse_ (pS h flush)) [e!t|t <- tt]
+    pSF h flush c es
+pSF _ _ _ [] = pure ()
 
-run :: Bool -> Int -> E T -> [LineCtx] -> IO ()
-run _ _ e _ | ty@TyArr{} <- eLoc e = error ("Found function type: " ++ show ty)
-run flush j e ctxs | TyB TyUnit <- eLoc e =  (\(s, f, env) -> pSF flush (s,f) env) $ flip evalState j $ do
+uStream = flip evalState
+
+run :: Handle -> Bool -> Int -> E T -> [LineCtx] -> IO ()
+run _ _ _ e _ | ty@TyArr{} <- eLoc e = error ("Found function type: " ++ show ty)
+run h flush j e ctxs | TyB TyUnit <- eLoc e =  (\(s, f, env) -> pSF h flush (s,f) env) $ uStream j $ do
     (res, tt, iEnv, μ) <- unit e
     u <- nI
     let outs=μ<$>ctxs; es'=scanl' (&) (Σ u iEnv IM.empty IM.empty IM.empty IS.empty) outs
     pure (res, tt, gE<$>es')
-run flush j e ctxs | TyB TyStream:$_ <- eLoc e = traverse_ (traverse_ (pS flush)).flip evalState j $ do
+run h flush j e ctxs | TyB TyStream:$_ <- eLoc e = traverse_ (traverse_ (pS h flush)).uStream j $ do
     t <- nI
     (iEnv, μ) <- ctx e t
     u <- nI
     let outs=μ<$>ctxs; es={-# SCC "scanMain" #-} scanl' (&) (Σ u iEnv IM.empty IM.empty IM.empty IS.empty) outs
     pure ((! t).gE<$>es)
-run _ j e ctxs = pDocLn $ flip evalState j $ do
+run h _ j e ctxs = pDocLn h $ uStream j $ do
     (iEnv, g, e0) <- collect e
     u <- nI
     let updates=g<$>ctxs
         finEnv=foldl' (&) (Σ u iEnv IM.empty IM.empty IM.empty IS.empty) updates
     e0@>(fromMaybe (throw EmptyFold)<$>gE finEnv)
 
-unit :: E T -> MM (Maybe Tmp, [Tmp], Env, LineCtx -> Σ -> Σ)
+unit :: E T -> UM (Maybe Tmp, [Tmp], Env, LineCtx -> Σ -> Σ)
 unit (Anchor _ es) = do
     tt <- traverse (\_ -> nI) es
     (iEnvs, μs) <- unzip <$> zipWithM ctx es tt
     pure (Nothing, tt, fold iEnvs, ts μs)
 unit (EApp _ (EApp _ (BB _ Report) es) e) = do
-    r <- nI
-    t <- nI
+    t <- nI; r <- nI
     (iEnv, μ) <- ctx es t
     (rEnv, g) <- φ e r
     pure (Just r, [t], iEnv<>rEnv, μ@.g)
 unit e = error ("Internal error. '" ++ show e ++ "' assigned unit type?")
 
-pS p = if p then (*>fflush).pDocLn else pDocLn where fflush = hFlush stdout
+pS h p e = if p then pDocLn h e *> hFlush h else pDocLn h e
 
-pDocLn :: E T -> IO ()
-pDocLn (Lit _ (FLit f)) = hPutBuilder stdout (doubleDec f <> "\n")
-pDocLn e                = putDoc (pretty e <> hardline)
+pDocLn :: Handle -> E T -> IO ()
+pDocLn h (Lit _ (FLit f)) = hPutBuilder h (doubleDec f <> "\n")
+pDocLn h e                = hPutDoc h (pretty e <> hardline)
 
-collect :: E T -> MM (Env, LineCtx -> Σ -> Σ, E T)
+collect :: E T -> UM (Env, LineCtx -> Σ -> Σ, E T)
 collect e@(EApp ty (EApp _ (EApp _ (TB _ Fold) _) _) _) = do
     v <- nN ty
     (iEnv, g) <- φ e (unU$unique v)
@@ -199,7 +197,7 @@
 ts :: [LineCtx -> Σ -> Σ] -> LineCtx -> Σ -> Σ
 ts = foldl' (@.) (\_ -> id)
 
-φ :: E T -> Tmp -> MM (Env, LineCtx -> Σ -> Σ)
+φ :: E T -> Tmp -> UM (Env, LineCtx -> Σ -> Σ)
 φ (EApp _ (EApp _ (EApp _ (TB _ Fold) op) seed) xs) tgt = do
     t <- nI
     seed' <- seed @> mempty
@@ -222,7 +220,7 @@
 κ FieldList{} ~(_, bs, _) = vS bs
 κ (EApp ty e0 e1) line    = EApp ty (e0 `κ` line) (e1 `κ` line)
 κ (NB _ Ix) ~(_, _, fp)   = mkI fp
-κ (NB _ Nf) ~(_, bs, _)   = mkI$fromIntegral (length bs)
+κ (NB _ Nf) ~(_, bs, _)   = mkI$!fromIntegral (length bs)
 κ e@BB{} _                = e
 κ e@UB{} _                = e
 κ e@TB{} _                = e
@@ -257,26 +255,26 @@
 ni t=IM.singleton t Nothing
 na=IM.alter go where go Nothing = Just Nothing; go x@Just{} = x
 
-ctx :: E T -> Tmp -> MM (Env, LineCtx -> Σ -> Σ)
-ctx AllColumn{} res                                      = pure (ni res, \ ~(b, _, _) -> mE$IM.insert res (Just$!mkStr b))
-ctx (ParseAllCol (_:$TyB TyI)) res                       = pure (ni res, \ ~(b, _, _) -> mE$IM.insert res (Just$!parseAsEInt b))
-ctx (ParseAllCol (_:$TyB TyFloat)) res                   = pure (ni res, \ ~(b, _, _) -> mE$IM.insert res (Just$!parseAsF b))
-ctx FParseAllCol{} res                                   = pure (ni res, \ ~(b, _, _) -> mE$IM.insert res (Just$!parseAsF b))
-ctx IParseAllCol{} res                                   = pure (ni res, \ ~(b, _, _) -> mE$IM.insert res (Just$!parseAsEInt b))
-ctx (Column _ i) res                                     = pure (ni res, \ ~(b, bs, _) -> mE$IM.insert res (Just$mkStr (fieldOf bs b i)))
-ctx (FParseCol _ i) res                                  = pure (ni res, \ ~(b, bs, _) -> mE$IM.insert res (Just$!parseAsF (fieldOf bs b i)))
-ctx (IParseCol _ i) res                                  = pure (ni res, \ ~(b, bs, _) -> mE$IM.insert res (Just$!parseAsEInt (fieldOf bs b i)))
-ctx (ParseCol (_:$TyB TyFloat) i) res                    = pure (ni res, \ ~(b, bs, _) -> mE$IM.insert res (Just$!parseAsF (fieldOf bs b i)))
-ctx (ParseCol (_:$TyB TyI) i) res                        = pure (ni res, \ ~(b, bs, _) -> mE$IM.insert res (Just$!parseAsEInt (fieldOf bs b i)))
+ctx :: E T -> Tmp -> UM (Env, LineCtx -> Σ -> Σ)
+ctx AllColumn{} res                                      = pure (ni res, \ ~(b, _, _) -> mE$res~!mkStr b)
+ctx (ParseAllCol (_:$TyB TyI)) res                       = pure (ni res, \ ~(b, _, _) -> mE$res~!parseAsEInt b)
+ctx (ParseAllCol (_:$TyB TyFloat)) res                   = pure (ni res, \ ~(b, _, _) -> mE$res~!parseAsF b)
+ctx FParseAllCol{} res                                   = pure (ni res, \ ~(b, _, _) -> mE$res~!parseAsF b)
+ctx IParseAllCol{} res                                   = pure (ni res, \ ~(b, _, _) -> mE$res~!parseAsEInt b)
+ctx (Column _ i) res                                     = pure (ni res, \ ~(b, bs, _) -> mE$res~!mkStr (fieldOf bs b i))
+ctx (FParseCol _ i) res                                  = pure (ni res, \ ~(b, bs, _) -> mE$res~!parseAsF (fieldOf bs b i))
+ctx (IParseCol _ i) res                                  = pure (ni res, \ ~(b, bs, _) -> mE$res~!parseAsEInt (fieldOf bs b i))
+ctx (ParseCol (_:$TyB TyFloat) i) res                    = pure (ni res, \ ~(b, bs, _) -> mE$res~!parseAsF (fieldOf bs b i))
+ctx (ParseCol (_:$TyB TyI) i) res                        = pure (ni res, \ ~(b, bs, _) -> mE$res~!parseAsEInt (fieldOf bs b i))
 ctx (EApp _ (EApp _ (BB _ Map) f) xs) o                  = do {t <- nI; (env, sb) <- ctx xs t; pure (na o env, \l->wM f t o.sb l)}
 ctx (EApp _ (EApp _ (BB _ MapMaybe) f) xs) o             = do {t <- nI; (env, sb) <- ctx xs t; pure (na o env, \l->wMM f t o.sb l)}
 ctx (EApp _ (UB _ CatMaybes) xs) o                       = do {t <- nI; (env, sb) <- ctx xs t; pure (na o env, \l->wCM t o.sb l)}
 ctx (EApp _ (EApp _ (BB _ Filter) p) xs) o               = do {t <- nI; (env, sb) <- ctx xs t; pure (na o env, \l->wP p t o.sb l)}
 ctx (Guarded _ p e) o                                    = pure (ni o, wG (p, e) o)
 ctx (Implicit _ e) o                                     = pure (ni o, wI e o)
-ctx (EApp _ (EApp _ (EApp _ (TB _ Scan) op) seed) xs) o  = do {t <- nI; (env, sb) <- ctx xs t; seed' <- seed@>mempty; pure (IM.insert o (Just$!seed') env, \l->wF op t o.sb l)}
+ctx (EApp _ (EApp _ (EApp _ (TB _ Scan) op) seed) xs) o  = do {t <- nI; (env, sb) <- ctx xs t; seed' <- seed@>mempty; pure (env&o~!seed', \l->wF op t o.sb l)}
 ctx (EApp _ (EApp _ (EApp _ (TB _ ZipW) op) xs) ys) o    = do {t0 <- nI; t1 <- nI; (env0, sb0) <- ctx xs t0; (env1, sb1) <- ctx ys t1; pure (na o (env0<>env1), \l->wZ op t0 t1 o.sb0 l.sb1 l)}
-ctx (EApp _ (EApp _ (BB _ Prior) op) xs) o               = do {t <- nI; (env, sb) <- ctx xs t; pt <- nI; pure (na o (IM.insert pt Nothing env), \l -> wΠ op pt t o.sb l)}
+ctx (EApp _ (EApp _ (BB _ Prior) op) xs) o               = do {t <- nI; (env, sb) <- ctx xs t; pt <- nI; pure (na o (pt\~env), \l -> wΠ op pt t o.sb l)}
 ctx (EApp (_:$TyB ty) (UB _ Dedup) xs) o                 = do {k <- nI; t <- nI; (env, sb) <- ctx xs t; pure (na o env, \l->wD ty k t o.sb l)}
 ctx (EApp _ (EApp _ (BB _ DedupOn) f) xs) o              = do {k <- nI; t <- nI; (env, sb) <- ctx xs t; pure (na o env, \l->wDOp f k t o.sb l)}
 ctx (EApp _ (EApp _ (EApp _ (TB _ Bookend) e0) e1) xs) o = do {k <- nI; t <- nI; (env, sb) <- ctx xs t; r0 <- e0@>mempty; r1<- e1@>mempty; pure (na o env, \l->wB (r0,r1) k t o.sb l)}
@@ -536,6 +534,7 @@
 e@TB{} @> _ = pure e
 e@UB{} @> _ = pure e
 (Lam t n e) @> b = Lam t n <$> (e@>b)
+e @> _ | TyArr{} <- eLoc e = throw $ StreamFunc e
 -- basically an option can evaluate to a function... so ((option ...) x)
 -- needs to be reduced! but nothing will detect that...
 -- (when can a builtin etc. return a FUNCTION? if...then...else could!)
@@ -554,78 +553,69 @@
 
 wCM :: Tmp -> Tmp -> Σ -> Σ
 wCM src tgt (Σ u env d di df b) =
-    let xϵ=env!src
-    in Σ u (case xϵ of
-        Just y  -> case asM y of {Nothing -> IM.insert tgt Nothing env; Just yϵ -> IM.insert tgt (Just$!yϵ) env}
-        Nothing -> IM.insert tgt Nothing env) d di df b
+    Σ u (case env!src of
+        Just y  -> case asM y of {Nothing -> tgt\~env; Just yϵ -> env&tgt~!yϵ}
+        Nothing -> tgt\~env) d di df b
 
 {-# SCC wMM #-}
 wMM :: E T -> Tmp -> Tmp -> Σ -> Σ
 wMM (Lam _ n e) src tgt (Σ j env d di df b) =
-    let xϵ=env!src
-    in case xϵ of
+    case env!src of
         Just x ->
             let be=ms n x; (y,k)=e@!(j,be)
             in Σ k (case asM y of
-                Just yϵ -> IM.insert tgt (Just$!yϵ) env
-                Nothing -> IM.insert tgt Nothing env) d di df b
-        Nothing -> Σ j (IM.insert tgt Nothing env) d di df b
+                Just yϵ -> env&tgt~!yϵ
+                Nothing -> tgt\~env) d di df b
+        Nothing -> Σ j (tgt\~env) d di df b
 wMM e _ _ _ = throw$InternalArityOrEta 1 e
 
 wZ :: E T -> Tmp -> Tmp -> Tmp -> Σ -> Σ
 wZ (Lam _ n0 (Lam _ n1 e)) src0 src1 tgt (Σ j env d di df b) =
-    let x0ϵ=env!src0; x1ϵ=env!src1
-    in (case (x0ϵ, x1ϵ) of
+    (case (env!src0, env!src1) of
         (Just x, Just y) ->
             let be=me [(n0, x), (n1, y)]; (z,k)=e@!(j,be)
-            in Σ k (IM.insert tgt (Just$!z) env)
-        (Nothing, Nothing) -> Σ j (IM.insert tgt Nothing env)) d di df b
+            in Σ k (env&tgt~!z)
+        (Nothing, Nothing) -> Σ j (tgt\~env)) d di df b
 wZ e _ _ _ _ = throw$InternalArityOrEta 2 e
 
 wM :: E T -> Tmp -> Tmp -> Σ -> Σ
 wM (Lam _ n e) src tgt (Σ j env d di df b) =
-    let xϵ=env!src
-    in case xϵ of
+    case env!src of
         Just x ->
             let be=ms n x; (y,k)=e@!(j,be)
-            in Σ k (IM.insert tgt (Just$!y) env) d di df b
-        Nothing -> Σ j (IM.insert tgt Nothing env) d di df b
+            in Σ k (env&tgt~!y) d di df b
+        Nothing -> Σ j (tgt\~env) d di df b
 wM e _ _ _ = throw$InternalArityOrEta 1 e
 
 wI :: E T -> Tmp -> LineCtx -> Σ -> Σ
 wI e tgt line (Σ j env d di df b) =
-    let e'=e `κ` line; (e'',k)=e'$@j in Σ k (IM.insert tgt (Just$!e'') env) d di df b
+    let e'=e `κ` line; (e'',k)=e'$@j in Σ k (env&tgt~!e'') d di df b
 
 wG :: (E T, E T) -> Tmp -> LineCtx -> Σ -> Σ
 wG (p, e) tgt line (Σ j env d di df b) =
     let p'=p `κ` line; (p'',k)=p'$@j
     in (if asB p''
-        then let e'=e `κ` line; (e'',u) =e'$@k in Σ u (IM.insert tgt (Just$!e'') env)
-        else Σ k (IM.insert tgt Nothing env)) d di df b
+        then let e'=e `κ` line; (e'',u) =e'$@k in Σ u (env&tgt~!e'')
+        else Σ k (tgt\~env)) d di df b
 
 wDOp :: E T -> Int -> Tmp -> Tmp -> Σ -> Σ
 wDOp (Lam (TyArr _ (TyB TyStr)) n e) key src tgt (Σ i env d di df b) =
-    let x=env!src
-    in case x of
-        Nothing -> Σ i (IM.insert tgt Nothing env) d di df b
+    case env!src of
+        Nothing -> Σ i (tgt\~env) d di df b
         Just xϵ ->
             case IM.lookup key d of
-                Nothing -> Σ k (IM.insert tgt (Just$!y) env) (IM.insert key (S.singleton e') d) di df b
-                Just ss -> (if e' `S.member` ss then Σ k (IM.insert tgt Nothing env) d else Σ k (IM.insert tgt (Just$!y) env) (IM.alter go key d)) di df b
+                Nothing -> Σ k (env&tgt~!y) (IM.insert key (S.singleton e') d) di df b
+                Just ss -> (if e' `S.member` ss then Σ k (tgt\~env) d else Σ k (env&tgt~!y) (key!:e'$d)) di df b
               where
                 (y,k)=e@!(i,be); be=ms n xϵ
                 e'=asS y
-
-                go Nothing  = Just$!S.singleton e'
-                go (Just s) = Just$!S.insert e' s
 wDOp (Lam (TyArr _ (TyB TyI)) n e) key src tgt (Σ i env d di df b) =
-    let x=env!src
-    in case x of
-        Nothing -> Σ i (IM.insert tgt Nothing env) d di df b
+    case env!src of
+        Nothing -> Σ i (tgt\~env) d di df b
         Just xϵ ->
             case IM.lookup key di of
-                Nothing -> Σ k (IM.insert tgt (Just$!y) env) d (IM.insert key (IS.singleton e') di) df b
-                Just ds -> (if e' `IS.member` ds then Σ k (IM.insert tgt Nothing env) d di else Σ k (IM.insert tgt (Just$!y) env) d (IM.alter go key di)) df b
+                Nothing -> Σ k (env&tgt~!y) d (IM.insert key (IS.singleton e') di) df b
+                Just ds -> (if e' `IS.member` ds then Σ k (tgt\~env) d di else Σ k (env&tgt~!y) d (IM.alter go key di)) df b
 
               where
                 (y,k)=e@!(i,be); be=ms n xϵ
@@ -634,110 +624,98 @@
                 go Nothing  = Just$!IS.singleton e'
                 go (Just s) = Just$!IS.insert e' s
 wDOp (Lam (TyArr _ (TyB TyFloat)) n e) key src tgt (Σ i env d di df b) =
-    let x=env!src
-    in case x of
-        Nothing -> Σ i (IM.insert tgt Nothing env) d di df b
+    case env!src of
+        Nothing -> Σ i (tgt\~env) d di df b
         Just xϵ ->
             case IM.lookup key df of
-                Nothing -> Σ k (IM.insert tgt (Just$!y) env) d di (IM.insert key (S.singleton e') df) b
-                Just ds -> if e' `S.member` ds then Σ k (IM.insert tgt Nothing env) d di df b else Σ k (IM.insert tgt (Just$!y) env) d di (IM.alter go key df) b
+                Nothing -> Σ k (env&tgt~!y) d di (IM.insert key (S.singleton e') df) b
+                Just ds -> if e' `S.member` ds then Σ k (tgt\~env) d di df b else Σ k (env&tgt~!y) d di (key!:e'$df) b
               where
                 (y,k)=e@!(i,be); be=ms n xϵ
                 e'=asF y
-
-                go Nothing  = Just$!S.singleton e'
-                go (Just s) = Just$!S.insert e' s
 wDOp e _ _ _ _ = throw $ InternalArityOrEta 1 e
 
+(\~) k = IM.insert k Nothing
+(~!) k x = IM.insert k (Just$!x)
+
+(!:) k e = IM.alter (\x -> Just$!case x of Nothing -> S.singleton e; Just s -> S.insert e s) k
+
 wB :: (E T, E T) -> Int -> Tmp -> Tmp -> Σ -> Σ
 wB (e0, e1) key src tgt (Σ i env d di df b) =
-    let x=env!src
-    in case x of
-        Nothing -> Σ i (IM.insert tgt Nothing env) d di df b
+    case env!src of
+        Nothing -> Σ i (tgt\~env) d di df b
         Just xϵ -> let xS=asS xϵ in if key `IS.member` b
-            then if isMatch' r1 xS then Σ i (IM.insert tgt (Just$!xϵ) env) d di df (IS.delete key b) else Σ i (IM.insert tgt (Just$!xϵ) env) d di df b
-            else if isMatch' r0 xS then Σ i (IM.insert tgt (Just$!xϵ) env) d di df (IS.insert key b) else Σ i (IM.insert tgt Nothing env) d di df b
+            then if isMatch' r1 xS then Σ i (env&tgt~!xϵ) d di df (IS.delete key b) else Σ i (env&tgt~!xϵ) d di df b
+            else if isMatch' r0 xS then Σ i (env&tgt~!xϵ) d di df (IS.insert key b) else Σ i (tgt\~env) d di df b
   where
     r0=asR e0; r1=asR e1
 
 {-# SCC wD #-}
 wD :: TB -> Int -> Tmp -> Tmp -> Σ -> Σ
 wD TyStr key src tgt (Σ i env d di df b) =
-    let x=env!src
-    in case x of
-        Nothing -> Σ i (IM.insert tgt Nothing env) d di df b
+    case env!src of
+        Nothing -> Σ i (tgt\~env) d di df b
         Just e ->
             case IM.lookup key d of
-                Nothing -> Σ i (IM.insert tgt (Just$!e) env) (IM.insert key (S.singleton e') d) di df b
-                Just ds -> (if e' `S.member` ds then Σ i (IM.insert tgt Nothing env) d else Σ i (IM.insert tgt (Just$!e) env) (IM.alter go key d)) di df b
+                Nothing -> Σ i (env&tgt~!e) (IM.insert key (S.singleton e') d) di df b
+                Just ds -> (if e' `S.member` ds then Σ i (tgt\~env) d else Σ i (env&tgt~!e) (key!:e'$d)) di df b
               where
-                go Nothing  = Just$!S.singleton e'
-                go (Just s) = Just$!S.insert e' s
-
                 e'=asS e
 wD TyI key src tgt (Σ i env d di df b) =
-    let x=env!src
-    in case x of
-        Nothing -> Σ i (IM.insert tgt Nothing env) d di df b
+    case env!src of
+        Nothing -> Σ i (tgt\~env) d di df b
         Just e ->
             case IM.lookup key di of
-                Nothing -> Σ i (IM.insert tgt (Just$!e) env) d (IM.insert key (IS.singleton e') di) df b
-                Just ds -> (if e' `IS.member` ds then Σ i (IM.insert tgt Nothing env) d di else Σ i (IM.insert tgt (Just$!e) env) d (IM.alter go key di)) df b
+                Nothing -> Σ i (env&tgt~!e) d (IM.insert key (IS.singleton e') di) df b
+                Just ds -> (if e' `IS.member` ds then Σ i (tgt\~env) d di else Σ i (env&tgt~!e) d (IM.alter go key di)) df b
               where
                 e'=fromIntegral$asI e
 
                 go Nothing  = Just$!IS.singleton e'
                 go (Just s) = Just$!IS.insert e' s
 wD TyFloat key src tgt (Σ i env d di df b) =
-    let x=env!src
-    in case x of
-        Nothing -> Σ i (IM.insert tgt Nothing env) d di df b
+    case env!src of
+        Nothing -> Σ i (tgt\~env) d di df b
         Just e ->
             case IM.lookup key df of
-                Nothing -> Σ i (IM.insert tgt (Just$!e) env) d di (IM.insert key (S.singleton e') df) b
-                Just ds -> (if e' `S.member` ds then Σ i (IM.insert tgt Nothing env) d di df else Σ i (IM.insert tgt (Just$!e) env) d di (IM.alter go key df)) b
+                Nothing -> Σ i (env&tgt~!e) d di (IM.insert key (S.singleton e') df) b
+                Just ds -> (if e' `S.member` ds then Σ i (tgt\~env) d di df else Σ i (env&tgt~!e) d di (key!:e'$df)) b
               where
                 e'=asF e
 
-                go Nothing  = Just$!S.singleton e'
-                go (Just s) = Just$!S.insert e' s
 
-
 wP :: E T -> Tmp -> Tmp -> Σ -> Σ
 wP (Lam _ n e) src tgt (Σ j env d di df b) =
-    let xϵ=env!src
-    in case xϵ of
+    case env!src of
         Just x ->
             let be=ms n x; (p,k)=e@!(j,be)
             in Σ k (IM.insert tgt (if asB p then Just$!x else Nothing) env) d di df b
-        Nothing -> Σ j (IM.insert tgt Nothing env) d di df b
+        Nothing -> Σ j (tgt\~env) d di df b
 wP e _ _ _ = throw $ InternalArityOrEta 1 e
 
 wΠ :: E T -> Tmp -> Tmp -> Tmp -> Σ -> Σ
 wΠ (Lam _ nn (Lam _ nprev e)) pt src tgt (Σ j env d di df b) =
-    let prevϵ=env!pt; xϵ=env!src
-    in (case (prevϵ, xϵ) of
+    (case (env!pt, env!src) of
         (Just prev, Just x) ->
             let be=me [(nprev, prev), (nn, x)]
                 (res,u)=e@!(j,be)
             in Σ u (IM.insert pt (Just$!x) (IM.insert tgt (Just$!res) env))
-        (Nothing, Nothing) -> Σ j (IM.insert tgt Nothing env)
-        (Nothing, Just x) -> Σ j (IM.insert pt (Just$!x) (IM.insert tgt Nothing env))
-        (Just{}, Nothing) -> Σ j (IM.insert tgt Nothing env)) d di df b
+        (Nothing, Nothing) -> Σ j (tgt\~env)
+        (Nothing, Just x) -> Σ j (pt~!x$tgt\~env)
+        (Just{}, Nothing) -> Σ j (tgt\~env)) d di df b
 wΠ e _ _ _ _ = throw $ InternalArityOrEta 2 e
 
 {-# SCC wF #-}
 wF :: E T -> Tmp -> Tmp -> Σ -> Σ
 wF (Lam _ nacc (Lam _ nn e)) src tgt (Σ j env d di df b) =
-    let accϵ = env!tgt; xϵ = env!src
-    in (case (accϵ, xϵ) of
+    (case (env!tgt, env!src) of
         (Just acc, Just x) ->
             let be=me [(nacc, acc), (nn, x)]
                 (res, u)=e@!(j, be)
-            in Σ u (IM.insert tgt (Just$!res) env)
-        (Just acc, Nothing) -> Σ j (IM.insert tgt (Just$!acc) env)
-        (Nothing, Nothing) -> Σ j (IM.insert tgt Nothing env)
-        (Nothing, Just x) -> Σ j (IM.insert tgt (Just$!x) env)) d di df b
+            in Σ u (env&tgt~!res)
+        (Just acc, Nothing) -> Σ j (env&tgt~!acc)
+        (Nothing, Nothing) -> Σ j (tgt\~env)
+        (Nothing, Just x) -> Σ j (env&tgt~!x)) d di df b
 wF e _ _ _ = throw $ InternalArityOrEta 2 e
 
 badctx e = error ("Internal error: κ called on" ++ show e)
diff --git a/src/Jacinda/Check/Field.hs b/src/Jacinda/Check/Field.hs
--- a/src/Jacinda/Check/Field.hs
+++ b/src/Jacinda/Check/Field.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Jacinda.Check.Field ( cF, LErr (..) ) where
 
 import           A
diff --git a/src/Jacinda/Regex.hs b/src/Jacinda/Regex.hs
--- a/src/Jacinda/Regex.hs
+++ b/src/Jacinda/Regex.hs
@@ -1,8 +1,9 @@
-{-# LANGUAGE OverloadedLists   #-}
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedLists #-}
 
 module Jacinda.Regex ( lazySplit
+                     , lazySplitH
                      , splitBy
+                     , splitH
                      , defaultRurePtr
                      , isMatch'
                      , find'
@@ -76,18 +77,31 @@
 find' :: RurePtr -> BS.ByteString -> Maybe RureMatch
 find' re str = unsafeDupablePerformIO $ find re str 0
 
+lazySplitH :: RurePtr -> BSL.ByteString -> [BS.ByteString]
+lazySplitH rp = go Nothing . BSL.toChunks where
+    go Nothing [] = []
+    go Nothing (c:cs) =
+        case unsnoc (splitH rp c) of
+            Just (iss,lss) -> iss++go (Just lss) cs
+            Nothing        -> go Nothing cs
+    go (Just c) [] = splitByA rp c
+    go (Just e) (c:cs) =
+        case unsnoc (splitByA rp (e<>c)) of
+            Just (iss,lss) -> iss++go (Just lss) cs
+            Nothing        -> go Nothing cs
+
 lazySplit :: RurePtr -> BSL.ByteString -> [BS.ByteString]
-lazySplit rp bs = let c=BSL.toChunks bs in go Nothing c
-        where go Nothing []      = []
-              go Nothing (c:cs)  = let ss=splitByA rp c
-                    in case unsnoc ss of
-                        Just (iss,lss) -> iss++go (Just lss) cs
-                        Nothing        -> go Nothing cs
-              go (Just c) []     = let ss=splitByA rp c in ss
-              go (Just e) (c:cs) = let ss=splitByA rp (e<>c)
-                    in case unsnoc ss of
-                        Just (iss,lss) -> iss++go (Just lss) cs
-                        Nothing        -> go Nothing cs
+lazySplit rp = go Nothing . BSL.toChunks where
+    go Nothing []      = []
+    go Nothing (c:cs)  =
+        case unsnoc (splitByA rp c) of
+            Just (iss,lss) -> iss++go (Just lss) cs
+            Nothing        -> go Nothing cs
+    go (Just c) []     = splitByA rp c
+    go (Just e) (c:cs) =
+        case unsnoc (splitByA rp (e<>c)) of
+            Just (iss,lss) -> iss++go (Just lss) cs
+            Nothing        -> go Nothing cs
 
 unsnoc :: [a] -> Maybe ([a], a)
 unsnoc = foldr (\x acc -> Just $ case acc of {Nothing -> ([], x); Just ~(a, b) -> (x:a, b)}) Nothing
@@ -95,19 +109,28 @@
 splitBy :: RurePtr -> BS.ByteString -> V.Vector BS.ByteString
 splitBy = (V.fromList .) . splitByA
 
-{-# NOINLINE splitBy #-}
+{-# NOINLINE splitByA #-}
 splitByA :: RurePtr
          -> BS.ByteString
          -> [BS.ByteString]
-splitByA _ "" = mempty
+splitByA _ "" = []
 splitByA re haystack@(BS.BS fp l) =
-    [BS.BS (fp `plusForeignPtr` s) (e-s) | (s, e) <- slicePairs]
+    [BS.BS (fp `plusForeignPtr` s) (e-s) | (s,e) <- slicePairs]
     where ixes = unsafeDupablePerformIO $ matches' re haystack
           slicePairs = case ixes of
                 (RureMatch 0 i:rms) -> mkMiddle (fromIntegral i) rms
                 rms                 -> mkMiddle 0 rms
           mkMiddle begin' []        = [(begin', l)]
           mkMiddle begin' (rm0:rms) = (begin', fromIntegral (start rm0)) : mkMiddle (fromIntegral $ end rm0) rms
+
+{-# NOINLINE splitH #-}
+splitH :: RurePtr -> BS.ByteString -> [BS.ByteString]
+splitH _ "" = []
+splitH re haystack@(BS.BS fp l) =
+    [BS.BS (fp `plusForeignPtr` s) (e-s) | (s,e) <- chopAt 0 ixes]
+    where ixes = unsafeDupablePerformIO $ matches' re haystack
+          chopAt begin []                  = [(begin, l)]
+          chopAt begin (RureMatch b _:rms) = (begin, fromIntegral b) : chopAt (fromIntegral b) rms
 
 isMatch' :: RurePtr
          -> BS.ByteString
diff --git a/src/L.x b/src/L.x
--- a/src/L.x
+++ b/src/L.x
@@ -1,6 +1,4 @@
 {
-    {-# LANGUAGE DeriveFunctor     #-}
-    {-# LANGUAGE OverloadedStrings #-}
     module L ( alexMonadScan
              , alexInitUserState
              , runAlexSt
@@ -153,6 +151,7 @@
         asv                      { mkKw KwAsv }
         usv                      { mkKw KwUsv }
         csv                      { mkKw KwCsv }
+        header                   { mkKw KwHeader }
 
         fs                       { res VarFs }
         rs                       { res VarRs }
@@ -377,7 +376,7 @@
              | KwVal
              | KwEnd
              | KwSet
-             | KwFlush
+             | KwFlush | KwHeader
              | KwFn
              | KwInclude
              | KwIf | KwThen | KwElse
@@ -412,6 +411,7 @@
     pretty KwUsv     = "usv"
     pretty KwAsv     = "asv"
     pretty KwCsv     = "csv"
+    pretty KwHeader = "header"
 
 data Builtin = BIParse | BFParse
              | BSubstr
diff --git a/src/Nm.hs b/src/Nm.hs
--- a/src/Nm.hs
+++ b/src/Nm.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE DeriveFunctor #-}
-
 module Nm ( Nm (..), TyName
           , eqName
           ) where
diff --git a/src/Nm/Map.hs b/src/Nm/Map.hs
--- a/src/Nm/Map.hs
+++ b/src/Nm/Map.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE DeriveFoldable    #-}
-{-# LANGUAGE DeriveFunctor     #-}
 {-# LANGUAGE DeriveTraversable #-}
 
 module Nm.Map ( NmMap (..)
diff --git a/src/Parser.y b/src/Parser.y
--- a/src/Parser.y
+++ b/src/Parser.y
@@ -1,8 +1,5 @@
 {
-    {-# LANGUAGE DeriveFunctor     #-}
-    {-# LANGUAGE OverloadedStrings #-}
-    module Parser ( parse
-                  , parseWithMax
+    module Parser ( parseWithMax
                   , parseWithCtx
                   , parseLibWithCtx
                   , ParseError (..)
@@ -129,6 +126,7 @@
     if { TokKeyword $$ KwIf }
     then { TokKeyword $$ KwThen }
     else { TokKeyword $$ KwElse }
+    header { TokKeyword $$ KwHeader }
     usv { TokKeyword $$ KwUsv }
     asv { TokKeyword $$ KwAsv }
     csv { TokKeyword $$ KwCsv }
@@ -252,6 +250,7 @@
   | set usv semicolon { SetUsv }
   | set csv semicolon { SetCsv }
   | flush semicolon { FlushDecl }
+  | set header semicolon { SetH }
   | fn name Args defEq E semicolon { FunDecl $2 $3 $5 }
   | fn name defEq E semicolon { FunDecl $2 [] $4 }
 
@@ -415,9 +414,6 @@
 
 df :: T.Text -> Value -> Alex (E AlexPosn -> E AlexPosn)
 df t x = do {nm <- newVarAlex t; let l=Nm.loc nm in pure (Let l (nm, guess l x))}
-
-parse :: T.Text -> Either (ParseError AlexPosn) File
-parse = fmap snd . runParse parseF
 
 parseWithMax :: T.Text -> Either (ParseError AlexPosn) (Int, File)
 parseWithMax = fmap (first fst3) . runParse parseF
diff --git a/src/R.hs b/src/R.hs
--- a/src/R.hs
+++ b/src/R.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module R ( rE, rP
          , Renames (..)
          , HasRenames (..)
diff --git a/src/Ty.hs b/src/Ty.hs
--- a/src/Ty.hs
+++ b/src/Ty.hs
@@ -1,10 +1,6 @@
-{-# LANGUAGE DeriveFunctor     #-}
-{-# LANGUAGE OverloadedStrings #-}
-
 module Ty ( Subst
           , runTyM, tyP
           , match, aT
-          , tyOf
           ) where
 
 import           A
@@ -281,9 +277,6 @@
         Just ty -> pure ty -- liftCloneTy ty
         Nothing -> throwError $ IllScoped l n
 
-tyOf :: Ord a => E a -> TyM a T
-tyOf = fmap eLoc.tyE
-
 tyDS :: Ord a => Subst -> D a -> TyM a (D T, Subst)
 tyDS s (SetFS bs)  = pure (SetFS bs, s)
 tyDS s (SetRS bs)  = pure (SetRS bs, s)
@@ -292,6 +285,7 @@
 tyDS s SetCsv      = pure (SetCsv, s)
 tyDS s SetAsv      = pure (SetAsv, s)
 tyDS s SetUsv      = pure (SetUsv, s)
+tyDS s SetH        = pure (SetH, s)
 tyDS s FlushDecl   = pure (FlushDecl, s)
 tyDS s (FunDecl n@(Nm _ (U i) _) [] e) = do
     (e', s') <- tyES s e
@@ -376,13 +370,6 @@
 
 desugar :: a
 desugar = error "Internal error: should have been de-sugared in an earlier stage!"
-
-tyE :: Ord a => E a -> TyM a (E T)
-tyE e = do
-    (e', s) <- tyES mempty e
-    cvs <- gets (IM.toList . classVars)
-    traverse_ (uncurry (checkClass s)) cvs
-    pure (fmap (aT s) e')
 
 tyES :: Ord a => Subst -> E a -> TyM a (E T, Subst)
 tyES _ F{}                = error "impossible."
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -3,124 +3,103 @@
 module Main (main) where
 
 import           A
-import qualified Data.ByteString  as BS
-import           Data.Foldable    (toList)
-import           Data.Functor     (void)
-import qualified Data.Text        as T
-import qualified Data.Text.IO     as TIO
+import qualified Data.ByteString      as BS
+import qualified Data.ByteString.Lazy as BSL
+import           Data.Foldable        (toList)
+import qualified Data.Text            as T
+import qualified Data.Text.IO         as TIO
 import           File
 import           Jacinda.Regex
-import           Parser
-import           Parser.Rw
+import           System.IO            (hClose)
+import           System.IO.Temp       (withSystemTempFile)
 import           Test.Tasty
+import           Test.Tasty.Golden    (goldenVsString)
 import           Test.Tasty.HUnit
-import           Ty.Const
 
+eio :: FilePath -- ^ Source filename
+    -> T.Text
+    -> Mode
+    -> FilePath -- ^ Input
+    -> IO BSL.ByteString
+eio src e m fp =
+    withSystemTempFile "JAC_TEST" $ \oϵ h -> do
+        runOnFile [] src e [] m fp h *> hClose h
+        BSL.readFile oϵ
+
+ep :: T.Text
+   -> Mode
+   -> FilePath -- ^ Input
+   -> BSL.ByteString -- ^ Expected output
+   -> TestTree
+ep e m fp expected = testCase (T.unpack e) $ do
+    actual <- eio undefined e m fp
+    actual @?= expected <> "\n"
+
+harnessF e m fp o = goldenVsString (T.unpack e) o $ eio undefined e m fp
+
+harness :: FilePath -- ^ Source file
+        -> Mode
+        -> FilePath -- ^ Input file
+        -> FilePath -- ^ Expected output
+        -> TestTree
+harness src m fp o =
+    goldenVsString src o $ do {t <- TIO.readFile src; eio src t m fp}
+
 main :: IO ()
 main = defaultMain $
-    testGroup "Jacinda interpreter"
-        [ testCase "parse as" (parseTo sumBytes sumBytesAST)
-        , testCase "parse as" (parseTo "#`0>72" pAst)
-        , parseFile "test/examples/ab.jac"
-        , splitWhitespaceT "1 1.3\tj" ["1", "1.3", "j"]
-        , splitWhitespaceT
-            "drwxr-xr-x  12 vanessa  staff   384 Dec 26 19:43 _darcs"
-            ["drwxr-xr-x","12","vanessa","staff","384","Dec","26","19:43","_darcs"]
-        , splitWhitespaceT "      55 ./src/Jacinda/File.hs" ["55", "./src/Jacinda/File.hs"]
-        , testCase "subs" $
-            let actual = subs (compileDefault "zi") "vectorzm0zi13zi1zi0zmc80ea02f780be2984f831df2de071f6e6040c0f670b3dd2428e80f5d111d7f72_DataziVectorziGeneric_partition_closure" "."
-            in actual @?= "vectorzm0.13.1.0zmc80ea02f780be2984f831df2de071f6e6040c0f670b3dd2428e80f5d111d7f72_Data.Vector.Generic_partition_closure"
-        , splitWhitespaceT "" []
-        , splitWhitespaceT "5" ["5"]
-        , testCase "type of" (tyOfT sumBytes (TyB TyI))
-        , testCase "type of" (tyOfT krakRegex (TyB TyStream :$ TyB TyStr)) -- stream of str
-        , testCase "type of" (tyOfT krakCol (TyB TyStream :$ TyB TyStr)) -- stream of str
-        , testCase "type of (zip)" (tyOfT ",(-) $3:i $6:i" (tyStream tyI))
-        , testCase "type of (filter)" (tyOfT "(>110) #. #\"$0" (tyStream tyI))
-        , testCase "typechecks dfn" (tyOfT "[(+)|0 x] $1:i" tyI)
-        , testCase "count bytes" (tyOfT "(+)|0 #¨$0" tyI)
-        , testCase "running count (lines)" (tyOfT "(+)^0 [:1¨$0" (tyStream tyI))
-        , testCase "type of (tally)" (tyOfT "#'hello world'" tyI)
-        , testCase "typechecks dfn" (tyFile "test/examples/ab.jac")
-        , testCase "parses parens" (tyFile "examples/lib.jac")
-        , testCase "typechecks/parses correctly" (tyFile "test/examples/line.jac")
-        , testCase "split eval" (evalTo "[x+' '+y]|> split '01-23-1987' /-/" "01 23 1987")
-        , testCase "length eval" (evalTo "#*split '01-23-1987' /-/" "3")
-        , testCase "captureE" (evalTo "'01-23-1987' ~* 3 /(\\d{2})-(\\d{2})-(\\d{4})/" "Some 1987")
-        , testCase "if...then...else" (evalTo "if #t then 0 else 1" "0")
-        , testGroup "Examples should be well-typed"
-            [ testCase (T.unpack s) (tyRight s) |
-                s <- [ "(||)|#f {#`0>110}{#t}"
-                     , "(&)|#t (>)\\. {|`1:f}"
-                     , "[y]|> {|`0~/^$/}"
-                     , "(max|_1 #¨$0) > 110"
-                     , "(||)|#f {#`0>110}{#t}"
-                     , "(+)|0 {`5 ~ /^\\d+$/}{`5:}"
-                     ]
-            ]
-        ]
+    testGroup "ja" [
+        testGroup "stream"
+          [ harness "examples/otool/rpath.jac" awk "test/data/otool" "test/golden/rpath.out"
+          , harness "examples/otool/dllibs.jac" awk "test/data/otool" "test/golden/ldlib.out"
+          , harness "test/examples/ghc-filt.jac" awk "test/data/ghc" "test/golden/ghc.out"
+          , ep "[x ~* 1 /(\\d+(\\.\\d+)*)/]:?{%/Versions available:/}{[y]|>`$}"
+                (AWK (Just "\\s*,\\s*") (Just "\\n[^:\\n]*:") True)
+                "test/data/cabal-info"
+                "0.1.0.5"
+          , ep ".?{|`1 ~* 1 /([^\\?]*)/}" awk "test/data/url" "https://soundcloud.com/shitzulover07/ayesha-erotica-vacation-bible-school"
+          , ep "[x+' '+y]|>(sprintf'-L%s')¨.?{|`1 ~* 1 /([^']*site-packages)/}"
+                awk
+                "test/data/python-site"
+                "-L/Users/vanessa/Library/Python/3.13/lib/python/site-packages -L/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages"
+          , harnessF "{%/hs-source-dirs/}{`2}" (AWK (Just "\\s*:\\s*") Nothing False) "jacinda.cabal" "test/golden/src-dirs.out"
+          , harnessF ".?{|`0 ~* 1 /^\\s*hs-source-dirs:\\s*(.*)/}" awk "jacinda.cabal" "test/golden/src-dirs.out"
+          -- , harnessF "[x+' '+y]|>$0" (AWK Nothing (Just "\\n\\s*") False) "vscode/syntaxes/jacinda.tmLanguage.json" "test/golden/minify.out"
+          , ep "@include'lib/prefixSizes.jac' prettyMem((+)|0.0 {ix>1}{`5:})" awk "test/data/ls" "73.82 kB"
+          , ep "[y]|>{%/tags/}{`*}" (AWK (Just "/") Nothing False) "test/data/git-tags" "v1.7.4"
+          , harnessF ".?{%/clang|mold|gold|GCC|GHC|rustc/}{`0 ~* 1 /^\\s*\\[[\\sa-f0-9]*\\]\\s*(.*$)/}" awk "test/data/readelf" "test/golden/compiler-version.out"
+          , ep "~.{%/LANGUAGE\\s*.*\\s*#-/}{`3}" awk "src/Jacinda/Regex.hs" "OverloadedLists"
+          , ep ".?{|`2 ~* 1 /(\\d+\\.\\d+)\\.\\d+/}" awk "test/data/py-ver" "3.13"
+          , ep "{ix=1}{`2}" awk "test/data/ghc-pkg" "/Users/vanessa/.ghcup/ghc/9.10.1/lib/ghc-9.10.1/lib/../lib/aarch64-osx-ghc-9.10.1"
+          , ep ".?{ix=1}{`0 ~* 1 /(\\d+\\.\\d+)/}" awk "test/data/r-version" "4.4"
+          , harnessF "{ix=1}{[x+'\\n'+y]|>`$}" CSV "test/data/a.csv" "test/golden/csv-col.out"
+          , harnessF "[x+' '+y]|> ~.{|subs /[^\\/]+\\/\\.\\.\\// '' `0}" awk "test/data/cdeps" "test/golden/mk-depends.out"
+          , harnessF "(sub1 /\\s+$/ ⍬)¨$0" awk "test/data/trailingWhitespace" "test/golden/trailing-whitespace.out"
+          , harnessF "{|option ⍬ [x] (`0 ~* 1 /^((\\s+\\S|\\S)*)\\s*$/)}" awk "test/data/trailingWhitespace" "test/golden/trailing-whitespace.out"
+          , ep "[:|>.?{|`0 ~* 1 /less-(\\d+)\\.tar\\.gz/}" awk "test/data/download.html" "668"
+          , ep "[:|>[x ~* 1 /less-(\\d+)\\.tar\\.gz/]:?$0" awk "test/data/download.html" "668"
+          , ep "{%/libapple.dylib/}{`2}" awk "test/data/cabal-plan" "/Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/f/apple/build/apple/libapple.dylib"
+          , harnessF "{|sprintf '%s\\t%s\\tcall cursor(%s,%s)' (`2.`3.`4.(splitc `5 '-').1)}" (AWK (Just "[\\s+:]") Nothing False) "test/data/fut-ctags" "test/golden/ctags.out"
+          , harnessF "{ix=1}{sprintf'CREATE TABLE c (%s);'([x+', '+y]|>[sprintf '%s TEXT' x]¨`$)}" CSV "test/data/food-prices.csv" "test/golden/sql.out"
+          , harnessF "{%/infix(r|l)? \\d+/}{sprintf '- fixity: %s' `0}" awk "src/A.hs" "test/golden/hlint-fix.out"
+          , harnessF "{%/^PATH/}{`2}" (AWK (Just "=") Nothing False) "test/data/env" "test/golden/env.out"
+          ]
+      , testGroup "eval"
+          [ splitWhitespaceT "" []
+          , splitWhitespaceT "5" ["5"]
+          , testCase "split eval" (evalTo "[x+' '+y]|> split '01-23-1987' /-/" "01 23 1987")
+          , testCase "length eval" (evalTo "#*split '01-23-1987' /-/" "3")
+          , testCase "captureE" (evalTo "'01-23-1987' ~* 3 /(\\d{2})-(\\d{2})-(\\d{4})/" "Some 1987")
+          , testCase "subs" (evalTo "subs /zi/ '.' 'vectorzm0zi13zi1zi0zmc80ea02f780be2984f831df2de071f6e6040c0f670b3dd2428e80f5d111d7f72_DataziVectorziGeneric_partition_closure'" "vectorzm0.13.1.0zmc80ea02f780be2984f831df2de071f6e6040c0f670b3dd2428e80f5d111d7f72_Data.Vector.Generic_partition_closure")
+          , testCase "basename" (evalTo "'test/data/py.py' ~* 2 /([^\\/]*\\/)*(.*)/" "Some py.py")
+          ]
+    ]
 
 evalTo :: T.Text -> String -> Assertion
 evalTo bsl expected =
     let actual = show (exprEval bsl)
         in actual @?= expected
 
-pAst :: E ()
-pAst =
-    EApp ()
-        (EApp ()
-            (BB () Gt)
-            (EApp ()
-                (UB () Tally)
-                (AllField ())))
-        (Lit () (ILit 72))
-
 splitWhitespaceT :: BS.ByteString -> [BS.ByteString] -> TestTree
 splitWhitespaceT haystack expected =
     testCase "split col" $
         toList (splitBy defaultRurePtr haystack) @?= expected
-
--- example: ls -l | ja '(+)|0 $5:i'
-sumBytes :: T.Text
-sumBytes = "(+)|0 $5:i"
-
-krakRegex :: T.Text
-krakRegex = "{% /Krakatoa/}{`0}"
-
-krakCol :: T.Text
-krakCol = "{`3:i > 4}{`0}"
-
-sumBytesAST :: E ()
-sumBytesAST =
-    EApp ()
-        (EApp ()
-            (EApp ()
-                (TB () Fold)
-                (BB () Plus))
-            (Lit () (ILit 0)))
-            (IParseCol () 5)
-
-tyFile :: FilePath -> Assertion
-tyFile fp = tcIO [] fp =<< TIO.readFile fp
-
-tyRight :: T.Text -> Assertion
-tyRight src = assertBool (T.unpack src) (tySrc src `seq` True)
-
-tyOfT :: T.Text -> T -> Assertion
-tyOfT src expected =
-    tySrc src @?= expected
-
-parseTo :: T.Text -> E () -> Assertion
-parseTo src e =
-    case rwP . snd <$> parse src of
-        Left err     -> assertFailure (show err)
-        Right actual -> void (expr actual) @?= e
-
-parseFile :: FilePath -> TestTree
-parseFile fp = testCase ("Parses " ++ fp) $ parseNoErr =<< TIO.readFile fp
-
-parseNoErr :: T.Text -> Assertion
-parseNoErr src =
-    case parse src of
-        Left err -> assertFailure (show err)
-        Right{}  -> assertBool "success" True
diff --git a/test/data/a.csv b/test/data/a.csv
new file mode 100644
--- /dev/null
+++ b/test/data/a.csv
@@ -0,0 +1,3 @@
+5.0,"Escaped?","Contains double char ""","newline lol
+","another"
+5.0,"a","a","b","b"
diff --git a/test/data/cabal-info b/test/data/cabal-info
new file mode 100644
--- /dev/null
+++ b/test/data/cabal-info
@@ -0,0 +1,61 @@
+* splitmix         (library)
+    Synopsis:      Fast Splittable PRNG
+    Versions available: 0, 0.0.3, 0.0.4, 0.0.5, 0.1, 0.1.0.2, 0.1.0.3, 0.1.0.4,
+                        0.1.0.5 (and 3 others)
+    Versions installed: [ Not installed ]
+    Homepage:      [ Not specified ]
+    Bug reports:   https://github.com/haskellari/splitmix/issues
+    Description:   Pure Haskell implementation of SplitMix described in
+                   
+                   Guy L. Steele, Jr., Doug Lea, and Christine H. Flood. 2014.
+                   Fast splittable pseudorandom number generators. In
+                   Proceedings of the 2014 ACM International Conference on
+                   Object Oriented Programming Systems Languages & Applications
+                   (OOPSLA '14). ACM, New York, NY, USA, 453-472. DOI:
+                   <https://doi.org/10.1145/2660193.2660195>
+                   
+                   The paper describes a new algorithm /SplitMix/ for
+                   /splittable/ pseudorandom number generator that is quite
+                   fast: 9 64 bit arithmetic/logical operations per 64 bits
+                   generated.
+                   
+                   /SplitMix/ is tested with two standard statistical test
+                   suites (DieHarder and TestU01, this implementation only using
+                   the former) and it appears to be adequate for "everyday" use,
+                   such as Monte Carlo algorithms and randomized data structures
+                   where speed is important.
+                   
+                   In particular, it __should not be used for cryptographic or
+                   security applications__, because generated sequences of
+                   pseudorandom values are too predictable (the mixing functions
+                   are easily inverted, and two successive outputs suffice to
+                   reconstruct the internal state).
+    Category:      System, Random
+    License:       BSD3
+    Maintainer:    Oleg Grenrus <oleg.grenrus@iki.fi>
+    Source repo:   https://github.com/haskellari/splitmix.git
+    Flags:         optimised-mixer
+    Dependencies:  base >=4.3 && <4.21, deepseq >=1.3.0.0 && <1.6,
+                   time >=1.2.0.3 && <1.13, base,
+                   HUnit ==1.3.1.2 || >=1.6.0.0 && <1.7, splitmix, base,
+                   base-compat-batteries >=0.10.5 && <0.14, splitmix,
+                   async >=2.2.1 && <2.3, base,
+                   base-compat-batteries >=0.10.5 && <0.14,
+                   bytestring >=0.9.1.8 && <0.13, deepseq,
+                   process >=1.0.1.5 && <1.7, random, splitmix,
+                   tf-random >=0.5 && <0.6, vector >=0.11.0.0 && <0.14, base,
+                   splitmix, base, splitmix, base,
+                   base-compat >=0.11.1 && <0.14, containers >=0.4.0.0 && <0.8,
+                   HUnit ==1.3.1.2 || >=1.6.0.0 && <1.7,
+                   math-functions ==0.1.7.0 || >=0.3.3.0 && <0.4, splitmix,
+                   test-framework >=0.8.2.0 && <0.9,
+                   test-framework-hunit >=0.3.0.2 && <0.4, base,
+                   HUnit ==1.3.1.2 || >=1.6.0.0 && <1.7, splitmix, base, random,
+                   splitmix, clock >=0.8 && <0.9, base, random, splitmix, base,
+                   containers >=0.4.2.1 && <0.8, criterion >=1.1.0.0 && <1.7,
+                   random, splitmix, tf-random >=0.5 && <0.6
+    Cached:        Yes
+    Modules:
+        System.Random.SplitMix
+        System.Random.SplitMix32
+
diff --git a/test/data/cabal-plan b/test/data/cabal-plan
new file mode 100644
--- /dev/null
+++ b/test/data/cabal-plan
@@ -0,0 +1,12 @@
+apple:flib:apple  /Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/f/apple/build/apple/libapple.dylib
+apple:bench:apple-bench  /Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/b/apple-bench/build/apple-bench/apple-bench
+apple:test:apple-o  /Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/t/apple-o/build/apple-o/apple-o
+apple:test:apple-test  /Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/t/apple-test/build/apple-test/apple-test
+apple:exe:arepl  /Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/x/arepl/build/arepl/arepl
+apple:exe:atc  /Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/x/atc/build/atc/atc
+apple:exe:writeo  /Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/x/writeo/build/writeo/writeo
+c2hs:exe:c2hs  /Users/vanessa/.local/state/cabal/store/ghc-9.10.1-64dd/c2hs-0.28.8-3e2168d2/bin/c2hs
+criterion:exe:criterion-report  /Users/vanessa/.local/state/cabal/store/ghc-9.10.1-64dd/crtrn-1.6.4.0-d85ffb3c/bin/criterion-report
+happy:exe:happy  /Users/vanessa/.local/state/cabal/store/ghc-9.10.1-64dd/hppy-2.1.3-52f20e2f/bin/happy
+hsc2hs:exe:hsc2hs  /Users/vanessa/.local/state/cabal/store/ghc-9.10.1-64dd/hsc2hs-0.68.10-86ce5d7f/bin/hsc2hs
+alex:exe:alex  /Users/vanessa/.local/state/cabal/store/ghc-9.10.1-64dd/lx-3.5.1.0-20231e5c/bin/alex
diff --git a/test/data/cdeps b/test/data/cdeps
new file mode 100644
--- /dev/null
+++ b/test/data/cdeps
@@ -0,0 +1,5 @@
+pyc/../c/../include/apple.h
+pyc/../c/../include/m.h
+pyc/../c/ffi.c
+pyc/../include/apple_abi.h
+pyc/../include/m.h
diff --git a/test/data/download.html b/test/data/download.html
new file mode 100644
--- /dev/null
+++ b/test/data/download.html
@@ -0,0 +1,217 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title> Downloading less </title>
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+
+<table cellpadding=6 cellspacing=4 align="center">
+<tr>
+<h1><center> Downloading less </center></h1> 
+</tr>
+<tr>
+<td> <a href="index.html"> Home </a> </td>
+<td> <a href="faq.html"> FAQ </a> </td>
+<td> <a href="download.html"> Download </a> </td>
+<td> <a href="https://github.com/gwsw/less/issues"> Bugs and Enhancement Requests </a> </td>
+<td> <a href="less-announce.html"> Mailing List </a> </td>
+</tr>
+</table>
+
+<hr>
+
+
+<P>
+You can download a copy of less here.
+First you must choose whether you want 
+<a href=#source><strong>source</strong></a> or <a href=#binaries><strong>binaries</strong></a>.
+It is simpler to get binaries, but binaries are available for
+only a few systems (see below).
+If you download source, you must then <STRONG>build</STRONG> the binaries.
+To do this, you must have a C compiler.
+</P>
+<P>
+You must also choose which version of less you want.
+Generally, you should choose the version marked as <strong>RECOMMENDED</strong>.
+</P>
+
+<HR>
+<a name="source"></a>
+<H2>Source</H2>
+<P>
+If you have a Unix, Linux or another Unix-like system, you should download
+the source and build it on your system.
+Less uses autoconf to make the build process relatively painless.
+Building less will work on most Linux and Unix-like systems.
+Less will also build from source on many non-Unix systems, including
+most versions of Windows, MS-DOS, OS/2, OS-9 and z/OS.
+</P>
+
+Each source release is packaged in both a gzip'd tar archive and in a zip archive.
+You may download either type of archive, whichever is more convenient for you.
+<UL>
+
+<LI>Download <strong>RECOMMENDED</strong> version 668 (source)
+<UL>
+<LI><A HREF="less-668.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-668.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-668.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 661 (source)
+<UL>
+<LI><A HREF="less-661.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-661.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-661.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 643 (source)
+<UL>
+<LI><A HREF="less-643.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-643.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-643.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 633 (source)
+<UL>
+<LI><A HREF="less-633.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-633.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-633.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 608 (source)
+<UL>
+<LI><A HREF="less-608.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-608.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-608.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 590 (source)
+<UL>
+<LI><A HREF="less-590.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-590.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-590.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 581.2 (source)
+<UL>
+<LI><A HREF="less-581.2.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-581.2.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-581.2.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 563 (source)
+<UL>
+<LI><A HREF="less-563.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-563.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-563.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 551 (source)
+<UL>
+<LI><A HREF="less-551.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-551.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-551.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 530 (source)
+<UL>
+<LI><A HREF="less-530.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-530.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-530.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 487 (source)
+<UL>
+<LI><A HREF="less-487.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-487.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-487.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 481 (source)
+<UL>
+<LI><A HREF="less-481.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-481.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-481.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 458 (source)
+<UL>
+<LI><A HREF="less-458.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-458.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-458.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 451 (source)
+<UL>
+<LI><A HREF="less-451.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-451.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-451.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 436 (source)
+<UL>
+<LI><A HREF="less-436.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-436.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-436.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 429 (source)
+<UL>
+<LI><A HREF="less-429.tar.gz">Gzip'd tar archive</A>.
+<FONT size="-1"><A HREF="less-429.sig">(Package signature)</A></FONT>
+<LI><A HREF="less-429.zip">Zip archive</A>.
+</UL>
+
+<LI>Download version 394 (source)
+<UL>
+<LI><A HREF="less-394.tar.gz">Gzip'd tar archive</A>.
+<LI><A HREF="less-394.zip">Zip archive</A>.
+</UL>
+
+<LI>Signature key
+<UL>
+<LI><A HREF="pubkey.asc">GPG public key for package signatures.</A>
+</UL>
+</UL>
+<HR>
+<a name="binaries"></a>
+<H2>Binaries</H2>
+<P>
+Less binaries are no longer distributed on this site, since I do not
+have the resources to generate and test binaries on a variety of systems.
+However binaries for certain systems are available from other sites below.
+</P>
+<P>
+I have not tested or verified the contents of these binary packages,
+so use them at your own risk.
+</P>
+
+<DL>
+
+<DT> <B>Windows</B>
+<DD> Windows binaries are available at:
+<UL>
+<LI> <A HREF="https://github.com/jftuga/less-Windows">https://github.com/jftuga/less-Windows</A>
+</UL>
+
+<DT> <B>Solaris</B>
+<DD> Solaris binaries are available at:
+<UL>
+<LI> <A HREF="http://unixpackages.com">http://unixpackages.com</A>.
+<LI> <A HREF="http://www.ibiblio.org/pub/packages/solaris/sparc">http://www.ibiblio.org/pub/packages/solaris/sparc</A>.
+<LI> <A HREF="http://www.opencsw.org/packages/less">http://www.opencsw.org/packages/less</A>.
+</UL>
+
+</DL>
+
+<FONT size="-1">
+If you maintain a site that hosts less binaries and wish your site to be listed here,
+send an email to <A HREF="mailto:markn@greenwoodsoftware.com">markn@greenwoodsoftware.com</A>.
+</FONT>
+<HR>
+
+</BODY>
+</HTML>
diff --git a/test/data/env b/test/data/env
new file mode 100644
--- /dev/null
+++ b/test/data/env
@@ -0,0 +1,39 @@
+TERM_SESSION_ID=w0t0p0:B2A638A3-C0C0-4FA1-BA7A-95DFF0A99BED
+SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.rii0JhficH/Listeners
+LC_TERMINAL_VERSION=3.5.9
+COLORFGBG=11;15
+ITERM_PROFILE=Default
+SQLITE_EXEMPT_PATH_FROM_VNODE_GUARDS=/Users/vanessa/Library/WebKit/Databases
+XPC_FLAGS=0x0
+LANG=en_US.UTF-8
+PWD=/Users/vanessa/dev/haskell/jacinda
+SHELL=/bin/zsh
+__CFBundleIdentifier=com.googlecode.iterm2
+TERM_FEATURES=T3LrMSc7UUw9Ts3BFGsSyHNoSxF
+TERM_PROGRAM_VERSION=3.5.9
+TERM_PROGRAM=iTerm.app
+PATH=/Users/vanessa/.opam/default/bin:/Users/vanessa/.cabal/bin:/Users/vanessa/.ghcup/bin:/Library/Frameworks/Python.framework/Versions/3.13/bin:/Library/Frameworks/Python.framework/Versions/3.12/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/Library/Frameworks/Python.framework/Versions/3.10/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/X11/bin:/Library/TeX/texbin:/usr/local/go/bin:/Users/vanessa/.cpm/bin:/Users/vanessa/pakcs/bin:/Users/vanessa/.local/bin:/Users/vanessa/.cargo/bin:/Applications/iTerm.app/Contents/Resources/utilities:/Users/vanessa/.fzf/bin
+DISPLAY=/private/tmp/com.apple.launchd.YmA3AqJ9zk/org.xquartz:0
+LC_TERMINAL=iTerm2
+COLORTERM=truecolor
+COMMAND_MODE=unix2003
+TERM=xterm-256color
+TERMINFO_DIRS=/Applications/iTerm.app/Contents/Resources/terminfo:/usr/share/terminfo
+HOME=/Users/vanessa
+TMPDIR=/var/folders/t5/6d5ws1yj0g78plhhzy_03ybm0000gn/T/
+USER=vanessa
+XPC_SERVICE_NAME=0
+LOGNAME=vanessa
+__CF_USER_TEXT_ENCODING=0x0:0:0
+ITERM_SESSION_ID=w0t0p0:B2A638A3-C0C0-4FA1-BA7A-95DFF0A99BED
+SHLVL=1
+OLDPWD=/Users/vanessa/dev/haskell/apple
+HISTSIZE=1000000000
+HISTFILESIZE=1000000000
+SAVEHIST=1000000000
+OPAMNOENVNOTICE=true
+OPAM_SWITCH_PREFIX=/Users/vanessa/.opam/default
+CAML_LD_LIBRARY_PATH=/Users/vanessa/.opam/default/lib/stublibs:/Users/vanessa/.opam/default/lib/ocaml/stublibs:/Users/vanessa/.opam/default/lib/ocaml
+OCAML_TOPLEVEL_PATH=/Users/vanessa/.opam/default/lib/toplevel
+OPAM_LAST_ENV=/Users/vanessa/.opam/.last-env/env-e11ea89f0858dbd243348d81ca05c0a8-0
+_=/usr/bin/printenv
diff --git a/test/data/food-prices.csv b/test/data/food-prices.csv
new file mode 100644
--- /dev/null
+++ b/test/data/food-prices.csv
@@ -0,0 +1,20 @@
+Series_reference,Period,Data_value,STATUS,UNITS,Subject,Group,Series_title_1
+CPIM.SAP0100,2006.06,3.11,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2006.07,2.78,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2006.08,2.43,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2006.09,2.42,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2006.1,3.04,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2006.11,3.24,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2006.12,3.27,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.01,3.18,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.02,3.74,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.03,4.21,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.04,4.16,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.05,4.29,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.06,3.6,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.07,3.14,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.08,2.62,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.09,2.47,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.1,2.5,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.11,2.93,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
+CPIM.SAP0100,2007.12,3.28,FINAL,Dollars,Consumers Price Index - CPI,Food Price Index Selected Monthly Weighted Average Prices for New Zealand,"Oranges, 1kg"
diff --git a/test/data/fut-ctags b/test/data/fut-ctags
new file mode 100644
--- /dev/null
+++ b/test/data/fut-ctags
@@ -0,0 +1,201 @@
+type real lib/github.com/diku-dk/complex/complex.fut:50:3-18
+type complex lib/github.com/diku-dk/complex/complex.fut:51:3-28
+value mk lib/github.com/diku-dk/complex/complex.fut:53:3-37
+value mk_re lib/github.com/diku-dk/complex/complex.fut:54:3-37
+value mk_im lib/github.com/diku-dk/complex/complex.fut:55:3-37
+value conj lib/github.com/diku-dk/complex/complex.fut:57:3-49
+value re lib/github.com/diku-dk/complex/complex.fut:58:3-31
+value im lib/github.com/diku-dk/complex/complex.fut:59:3-31
+value + lib/github.com/diku-dk/complex/complex.fut:61:3-63
+value - lib/github.com/diku-dk/complex/complex.fut:62:3-63
+value * lib/github.com/diku-dk/complex/complex.fut:63:3-64:64
+value / lib/github.com/diku-dk/complex/complex.fut:65:3-67:44
+value mag lib/github.com/diku-dk/complex/complex.fut:69:3-70:29
+value arg lib/github.com/diku-dk/complex/complex.fut:71:3-72:16
+value sqrt lib/github.com/diku-dk/complex/complex.fut:74:3-78:22
+value exp lib/github.com/diku-dk/complex/complex.fut:80:3-82:44
+value log lib/github.com/diku-dk/complex/complex.fut:84:3-85:31
+type real lib/github.com/diku-dk/fft/stockham-radix-2.fut:15:3-18
+type complex lib/github.com/diku-dk/fft/stockham-radix-2.fut:16:3-33
+value radix lib/github.com/diku-dk/fft/stockham-radix-2.fut:18:3-20
+value fft_iteration lib/github.com/diku-dk/fft/stockham-radix-2.fut:20:3-28:49
+value fft' lib/github.com/diku-dk/fft/stockham-radix-2.fut:30:3-44:11
+value log2 lib/github.com/diku-dk/fft/stockham-radix-2.fut:46:3-52:9
+value is_power_of_2 lib/github.com/diku-dk/fft/stockham-radix-2.fut:54:3-50
+value generic_fft lib/github.com/diku-dk/fft/stockham-radix-2.fut:56:3-60:40
+value fft lib/github.com/diku-dk/fft/stockham-radix-2.fut:62:3-63:26
+value ifft lib/github.com/diku-dk/fft/stockham-radix-2.fut:65:3-67:50
+value fft_re lib/github.com/diku-dk/fft/stockham-radix-2.fut:69:3-70:33
+value ifft_re lib/github.com/diku-dk/fft/stockham-radix-2.fut:72:3-73:34
+value generic_fft2 lib/github.com/diku-dk/fft/stockham-radix-2.fut:75:3-82:31
+value fft2 lib/github.com/diku-dk/fft/stockham-radix-2.fut:84:3-85:27
+value ifft2 lib/github.com/diku-dk/fft/stockham-radix-2.fut:87:3-89:65
+value fft2_re lib/github.com/diku-dk/fft/stockham-radix-2.fut:91:3-92:48
+value ifft2_re lib/github.com/diku-dk/fft/stockham-radix-2.fut:94:3-95:49
+type t lib/github.com/diku-dk/statistics/gammaln.fut:88:1-13
+value A1C lib/github.com/diku-dk/statistics/gammaln.fut:90:1-43
+value A1 lib/github.com/diku-dk/statistics/gammaln.fut:91:1-96:11
+value A2C lib/github.com/diku-dk/statistics/gammaln.fut:97:1-43
+value A2 lib/github.com/diku-dk/statistics/gammaln.fut:98:1-103:11
+value RC lib/github.com/diku-dk/statistics/gammaln.fut:105:1-19
+value R' lib/github.com/diku-dk/statistics/gammaln.fut:107:1-113:11
+value SC lib/github.com/diku-dk/statistics/gammaln.fut:115:1-49
+value S lib/github.com/diku-dk/statistics/gammaln.fut:117:1-123:10
+value T1C lib/github.com/diku-dk/statistics/gammaln.fut:124:1-43
+value T1 lib/github.com/diku-dk/statistics/gammaln.fut:125:1-129:11
+value T2C lib/github.com/diku-dk/statistics/gammaln.fut:130:1-50
+value T2 lib/github.com/diku-dk/statistics/gammaln.fut:131:1-135:11
+value T3C lib/github.com/diku-dk/statistics/gammaln.fut:136:1-43
+value T3 lib/github.com/diku-dk/statistics/gammaln.fut:137:1-141:11
+value UC lib/github.com/diku-dk/statistics/gammaln.fut:142:1-49
+value U lib/github.com/diku-dk/statistics/gammaln.fut:143:1-148:10
+value VC lib/github.com/diku-dk/statistics/gammaln.fut:149:1-19
+value V lib/github.com/diku-dk/statistics/gammaln.fut:150:1-155:10
+value WC lib/github.com/diku-dk/statistics/gammaln.fut:156:1-42
+value W lib/github.com/diku-dk/statistics/gammaln.fut:157:1-163:10
+value YMIN lib/github.com/diku-dk/statistics/gammaln.fut:164:1-38
+value TWO52 lib/github.com/diku-dk/statistics/gammaln.fut:165:1-35
+value TWO58 lib/github.com/diku-dk/statistics/gammaln.fut:166:1-37
+value TINY lib/github.com/diku-dk/statistics/gammaln.fut:167:1-39
+value TC lib/github.com/diku-dk/statistics/gammaln.fut:168:1-42
+value TF lib/github.com/diku-dk/statistics/gammaln.fut:169:1-49
+value TT lib/github.com/diku-dk/statistics/gammaln.fut:170:1-49
+value evalpoly lib/github.com/diku-dk/statistics/gammaln.fut:172:1-173:74
+value polyvalA1 lib/github.com/diku-dk/statistics/gammaln.fut:175:1-28
+value polyvalA2 lib/github.com/diku-dk/statistics/gammaln.fut:176:1-28
+value polyvalR lib/github.com/diku-dk/statistics/gammaln.fut:177:1-27
+value polyvalS lib/github.com/diku-dk/statistics/gammaln.fut:178:1-26
+value polyvalT1 lib/github.com/diku-dk/statistics/gammaln.fut:179:1-28
+value polyvalT2 lib/github.com/diku-dk/statistics/gammaln.fut:180:1-28
+value polyvalT3 lib/github.com/diku-dk/statistics/gammaln.fut:181:1-28
+value polyvalU lib/github.com/diku-dk/statistics/gammaln.fut:182:1-26
+value polyvalV lib/github.com/diku-dk/statistics/gammaln.fut:183:1-26
+value polyvalW lib/github.com/diku-dk/statistics/gammaln.fut:184:1-26
+value sinpi lib/github.com/diku-dk/statistics/gammaln.fut:186:1-31
+value case0 lib/github.com/diku-dk/statistics/gammaln.fut:188:1-193:33
+value case1 lib/github.com/diku-dk/statistics/gammaln.fut:195:1-202:20
+value case2 lib/github.com/diku-dk/statistics/gammaln.fut:204:1-207:42
+value gammaln lib/github.com/diku-dk/statistics/gammaln.fut:209:1-267:28
+value radix_sort_step lib/github.com/diku-dk/sorts/radix_sort.fut:14:7-32:29
+value radix_sort lib/github.com/diku-dk/sorts/radix_sort.fut:50:1-53:63
+value with_indices lib/github.com/diku-dk/sorts/radix_sort.fut:55:1-56:18
+value by_key_wrapper lib/github.com/diku-dk/sorts/radix_sort.fut:58:7-62:34
+value radix_sort_by_key lib/github.com/diku-dk/sorts/radix_sort.fut:65:1-68:52
+value radix_sort_int lib/github.com/diku-dk/sorts/radix_sort.fut:73:1-79:37
+value radix_sort_int_by_key lib/github.com/diku-dk/sorts/radix_sort.fut:82:1-85:56
+value radix_sort_float lib/github.com/diku-dk/sorts/radix_sort.fut:91:1-104:37
+value radix_sort_float_by_key lib/github.com/diku-dk/sorts/radix_sort.fut:107:1-110:58
+value segmented_scan lib/github.com/diku-dk/segmented/segmented.fut:7:1-13:29
+value segmented_reduce lib/github.com/diku-dk/segmented/segmented.fut:20:1-37:71
+value replicated_iota lib/github.com/diku-dk/segmented/segmented.fut:44:1-50:36
+value segmented_iota lib/github.com/diku-dk/segmented/segmented.fut:58:1-60:27
+value expand lib/github.com/diku-dk/segmented/segmented.fut:70:1-74:44
+value expand_reduce lib/github.com/diku-dk/segmented/segmented.fut:84:1-91:37
+value expand_outer_reduce lib/github.com/diku-dk/segmented/segmented.fut:97:1-103:46
+type t lib/github.com/diku-dk/statistics/statistics.fut:130:3-15
+value argmax lib/github.com/diku-dk/statistics/statistics.fut:135:3-138:55
+value mean lib/github.com/diku-dk/statistics/statistics.fut:140:3-141:23
+value gmean lib/github.com/diku-dk/statistics/statistics.fut:143:3-144:36
+value hmean lib/github.com/diku-dk/statistics/statistics.fut:146:3-147:38
+value qmean lib/github.com/diku-dk/statistics/statistics.fut:149:3-150:53
+value pow2 lib/github.com/diku-dk/statistics/statistics.fut:152:3-31
+value pow3 lib/github.com/diku-dk/statistics/statistics.fut:153:3-33
+value pow4 lib/github.com/diku-dk/statistics/statistics.fut:154:3-36
+value variance lib/github.com/diku-dk/statistics/statistics.fut:156:3-159:35
+value stddev lib/github.com/diku-dk/statistics/statistics.fut:161:3-162:26
+value covariance0 lib/github.com/diku-dk/statistics/statistics.fut:164:3-166:28
+value covariance lib/github.com/diku-dk/statistics/statistics.fut:168:3-169:42
+value correlation lib/github.com/diku-dk/statistics/statistics.fut:171:3-172:51
+value covariance_matrix lib/github.com/diku-dk/statistics/statistics.fut:174:3-180:24
+value variance_pop lib/github.com/diku-dk/statistics/statistics.fut:182:3-183:46
+value stddev_pop lib/github.com/diku-dk/statistics/statistics.fut:185:3-186:30
+value skewness lib/github.com/diku-dk/statistics/statistics.fut:188:3-192:26
+value skewness_adj lib/github.com/diku-dk/statistics/statistics.fut:194:3-195:70
+value kurtosis lib/github.com/diku-dk/statistics/statistics.fut:197:3-201:26
+value kurtosis_excess lib/github.com/diku-dk/statistics/statistics.fut:203:3-204:28
+value median_sorted lib/github.com/diku-dk/statistics/statistics.fut:206:3-210:18
+value median lib/github.com/diku-dk/statistics/statistics.fut:212:3-71
+value quantile_sorted lib/github.com/diku-dk/statistics/statistics.fut:214:3-220:57
+value quantile lib/github.com/diku-dk/statistics/statistics.fut:222:3-75
+value mode_sorted lib/github.com/diku-dk/statistics/statistics.fut:224:3-230:13
+value mode lib/github.com/diku-dk/statistics/statistics.fut:232:3-67
+type regression_result lib/github.com/diku-dk/statistics/statistics.fut:234:3-44
+value regress lib/github.com/diku-dk/statistics/statistics.fut:236:3-245:30
+value gamma_big lib/github.com/diku-dk/statistics/statistics.fut:248:3-263:65
+value gamma lib/github.com/diku-dk/statistics/statistics.fut:265:3-268:25
+value gammaln lib/github.com/diku-dk/statistics/statistics.fut:272:3-44
+type dist lib/github.com/diku-dk/statistics/statistics.fut:275:3-54
+value poison_pmf lib/github.com/diku-dk/statistics/statistics.fut:277:3-278:69
+value fac lib/github.com/diku-dk/statistics/statistics.fut:280:3-281:64
+value poison_cdf lib/github.com/diku-dk/statistics/statistics.fut:283:3-285:96
+value normal_pdf lib/github.com/diku-dk/statistics/statistics.fut:287:3-288:84
+value erf lib/github.com/diku-dk/statistics/statistics.fut:290:3-304:28
+value normal_cdf lib/github.com/diku-dk/statistics/statistics.fut:306:3-307:60
+value normal_cdf_inv lib/github.com/diku-dk/statistics/statistics.fut:309:3-352:8
+value poison_cdf_inv lib/github.com/diku-dk/statistics/statistics.fut:371:3-41
+value mk_poison lib/github.com/diku-dk/statistics/statistics.fut:373:3-374:78
+value mk_normal lib/github.com/diku-dk/statistics/statistics.fut:376:3-377:83
+value mk_uniform lib/github.com/diku-dk/statistics/statistics.fut:379:3-385:33
+value pmf lib/github.com/diku-dk/statistics/statistics.fut:387:3-52
+value pdf lib/github.com/diku-dk/statistics/statistics.fut:388:3-50
+value cdf lib/github.com/diku-dk/statistics/statistics.fut:389:3-39
+value sample lib/github.com/diku-dk/statistics/statistics.fut:391:3-43
+value cum_norm_dist_pos lib/github.com/diku-dk/statistics/statistics.fut:394:3-403:47
+value cum_norm_dist lib/github.com/diku-dk/statistics/statistics.fut:405:3-407:33
+type num lib/github.com/vmchale/img-fut/img.fut:79:3-17
+type border lib/github.com/vmchale/img-fut/img.fut:81:3-33
+value window lib/github.com/vmchale/img-fut/img.fut:83:9-85:81
+value with_window_reflect lib/github.com/vmchale/img-fut/img.fut:87:3-116:24
+value with_window_extended lib/github.com/vmchale/img-fut/img.fut:118:3-147:24
+value with_window lib/github.com/vmchale/img-fut/img.fut:149:3-152:54
+value maximum_2d lib/github.com/vmchale/img-fut/img.fut:154:3-155:32
+value minimum_2d lib/github.com/vmchale/img-fut/img.fut:157:3-158:32
+value maximum_filter lib/github.com/vmchale/img-fut/img.fut:161:3-162:37
+value minimum_filter lib/github.com/vmchale/img-fut/img.fut:164:3-165:37
+value matmul lib/github.com/vmchale/img-fut/img.fut:167:3-171:10
+value correlate lib/github.com/vmchale/img-fut/img.fut:173:3-183:72
+value convolve lib/github.com/vmchale/img-fut/img.fut:185:3-190:32
+value ez_resize lib/github.com/vmchale/img-fut/img.fut:192:3-198:62
+value crop lib/github.com/vmchale/img-fut/img.fut:200:3-201:34
+type num lib/github.com/vmchale/img-fut/img.fut:210:3-17
+type real lib/github.com/vmchale/img-fut/img.fut:211:3-18
+type border lib/github.com/vmchale/img-fut/img.fut:217:3-32
+value with_window lib/github.com/vmchale/img-fut/img.fut:219:3-41
+value maximum_filter lib/github.com/vmchale/img-fut/img.fut:220:3-47
+value minimum_filter lib/github.com/vmchale/img-fut/img.fut:221:3-47
+value maximum_2d lib/github.com/vmchale/img-fut/img.fut:222:3-39
+value minimum_2d lib/github.com/vmchale/img-fut/img.fut:223:3-39
+value convolve lib/github.com/vmchale/img-fut/img.fut:224:3-35
+value correlate lib/github.com/vmchale/img-fut/img.fut:225:3-37
+value ez_resize lib/github.com/vmchale/img-fut/img.fut:226:3-37
+value crop lib/github.com/vmchale/img-fut/img.fut:227:3-27
+value mean_filter lib/github.com/vmchale/img-fut/img.fut:229:3-236:24
+value conjugate_fft lib/github.com/vmchale/img-fut/img.fut:238:9-243:73
+value fft_mean_filter lib/github.com/vmchale/img-fut/img.fut:247:3-248:39
+value sobel lib/github.com/vmchale/img-fut/img.fut:255:3-270:68
+value laplacian lib/github.com/vmchale/img-fut/img.fut:272:3-277:28
+value prewitt lib/github.com/vmchale/img-fut/img.fut:279:3-294:68
+value scale_2d lib/github.com/vmchale/img-fut/img.fut:296:9-298:47
+value laplacian_of_gaussian lib/github.com/vmchale/img-fut/img.fut:300:3-328:32
+value gaussian lib/github.com/vmchale/img-fut/img.fut:330:3-356:30
+type num lib/github.com/vmchale/img-fut/img.fut:370:3-17
+type real lib/github.com/vmchale/img-fut/img.fut:371:3-18
+type float lib/github.com/vmchale/img-fut/img.fut:372:3-19
+type border lib/github.com/vmchale/img-fut/img.fut:374:3-35
+value correlate lib/github.com/vmchale/img-fut/img.fut:377:3-40
+value convolve lib/github.com/vmchale/img-fut/img.fut:378:3-38
+value sobel lib/github.com/vmchale/img-fut/img.fut:379:3-30
+value prewitt lib/github.com/vmchale/img-fut/img.fut:380:3-34
+value mean_filter lib/github.com/vmchale/img-fut/img.fut:381:3-42
+value maximum_filter lib/github.com/vmchale/img-fut/img.fut:382:3-50
+value minimum_filter lib/github.com/vmchale/img-fut/img.fut:383:3-50
+value with_window lib/github.com/vmchale/img-fut/img.fut:384:3-44
+value maximum_2d lib/github.com/vmchale/img-fut/img.fut:385:3-42
+value minimum_2d lib/github.com/vmchale/img-fut/img.fut:386:3-42
+value ez_resize lib/github.com/vmchale/img-fut/img.fut:387:3-40
+value crop lib/github.com/vmchale/img-fut/img.fut:388:3-30
+value gaussian lib/github.com/vmchale/img-fut/img.fut:389:3-36
+value laplacian lib/github.com/vmchale/img-fut/img.fut:390:3-38
+value laplacian_of_gaussian lib/github.com/vmchale/img-fut/img.fut:391:3-62
+value fft_mean_filter lib/github.com/vmchale/img-fut/img.fut:392:3-50
+value median_filter lib/github.com/vmchale/img-fut/img.fut:395:3-396:67
diff --git a/test/data/ghc b/test/data/ghc
new file mode 100644
--- /dev/null
+++ b/test/data/ghc
@@ -0,0 +1,1420 @@
+GHCi, version 9.10.1: https://www.haskell.org/ghc/  :? for help
+Command is not supported (yet) in multi-mode
+/Users/vanessa/dev/haskell/apple/src/IR.hs:139:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘abs’ and ‘signum’
+    • In the instance declaration for ‘Num Exp’
+    |
+139 | instance Num Exp where
+    |          ^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/IR.hs:142:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘abs’ and ‘signum’
+    • In the instance declaration for ‘Num (FExp ftemp Double e)’
+    |
+142 | instance Num (FExp ftemp Double e) where
+    |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Hs/A.hs:33:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘alignment’
+    • In the instance declaration for ‘Storable AB’
+   |
+33 | instance Storable AB where
+   |          ^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Hs/A.hs:35:15: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a \case alternative:
+        Patterns of type ‘Word8’ not matched:
+            p where p is not one of {1, 0}
+   |
+35 |     peek p = (\case 1 -> T; 0 -> F) <$> peek (castPtr p :: Ptr Word8)
+   |               ^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Hs/A.hs:39:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘alignment’ and (either ‘poke’ or ‘pokeElemOff’ or ‘pokeByteOff’)
+    • In the instance declaration for ‘Storable (P2 a b)’
+   |
+39 | instance (Storable a, Storable b) => Storable (P2 a b) where
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Hs/A.hs:43:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘alignment’ and (either ‘poke’ or ‘pokeElemOff’ or ‘pokeByteOff’)
+    • In the instance declaration for ‘Storable (P3 a b c)’
+   |
+43 | instance (Storable a, Storable b, Storable c) => Storable (P3 a b c) where
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Hs/A.hs:47:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘alignment’ and (either ‘poke’ or ‘pokeElemOff’ or ‘pokeByteOff’)
+    • In the instance declaration for ‘Storable (P4 a b c d)’
+   |
+47 | instance (Storable a, Storable b, Storable c, Storable d) => Storable (P4 a b c d) where
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Hs/A.hs:69:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘alignment’
+    • In the instance declaration for ‘Storable (Apple a)’
+   |
+69 | instance Storable a => Storable (Apple a) where
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/IR/Hoist.hs:62:21: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘FTemp’ not matched:
+            F0
+            F1
+            F2
+            F3
+            ...
+   |
+62 | view f (F2Temp i) = case f (FTemp i) of (FTemp j) -> F2Temp j
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/IR/Hoist.hs:124:32: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Stmt, ControlAnn)’ not matched:
+            ((MJ _ _), _)
+            ((J _), _)
+            ((MT _ _), _)
+            ((MX _ _), _)
+            ...
+    |
+124 |     ss = getCf<$>IS.toList ns; (L lh,_) = getCf n
+    |                                ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/IR/Hoist.hs:128:14: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of S ‘su’
+    |
+128 |            , su :: !(M.Map FTemp FTemp)
+    |              ^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Frame.hs:29:11: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘handleRax’:
+        Patterns of type ‘CFunc’ not matched:
+            JR
+            Exp
+            Log
+            Pow
+   |
+29 |           handleRax Malloc = filter (/=Rax)
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Frame.hs:34:11: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘mx’:
+        Patterns of type ‘CFunc’ not matched:
+            JR
+            Exp
+            Log
+            Pow
+   |
+34 |           mx Free   = const []
+   |           ^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64.hs:104:5: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘pw’:
+        Patterns of type ‘AbsReg’ not matched:
+            LR
+            FP
+            ASP
+    |
+104 |     pw (IReg i) = "W" <> pretty i
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64.hs:116:27: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘pq’:
+        Patterns of type ‘V2Reg FAbsReg’ not matched:
+            V2Reg FArg0
+            V2Reg FArg1
+            V2Reg FArg2
+            V2Reg FArg3
+            ...
+    |
+116 | instance SIMD F2Abs where pq (V2Reg (FReg i)) = "~Q" <> pretty i; pv (V2Reg (FReg i)) = "~V" <> pretty i
+    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64.hs:116:67: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘pv’:
+        Patterns of type ‘V2Reg FAbsReg’ not matched:
+            V2Reg FArg0
+            V2Reg FArg1
+            V2Reg FArg2
+            V2Reg FArg3
+            ...
+    |
+116 | instance SIMD F2Abs where pq (V2Reg (FReg i)) = "~Q" <> pretty i; pv (V2Reg (FReg i)) = "~V" <> pretty i
+    |                                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64.hs:215:8: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘String’ not matched:
+            []
+            (p:_) where p is not one of {'l', 'd'}
+            ['l']
+            ('l':p:_) where p is not one of {'i'}
+            ...
+    |
+215 | pSym = case os of {"linux" -> id; "darwin" -> ("_"<>)}.pretty
+    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/CF.hs:78:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘usesF’:
+        Patterns of type ‘X86 reg freg ann’ not matched:
+            Vfmadd213sd _ _ _ _
+            Vfmsub231sd _ _ _ _
+            Vfmsub213sd _ _ _ _
+            Vfmsub132sd _ _ _ _
+            ...
+   |
+78 | usesF (Movapd _ _ r)            = singleton r
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/CF.hs:165:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘uses’:
+        Patterns of type ‘X86 reg freg ann’ not matched:
+            Vfmadd213sd _ _ _ _
+            Vfmsub231sd _ _ _ _
+            Vfmsub213sd _ _ _ _
+            Vfmsub132sd _ _ _ _
+            ...
+    |
+165 | uses (MovRR _ _ r)          = singleton r
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/CF.hs:254:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘defsF’:
+        Patterns of type ‘X86 reg freg ann’ not matched:
+            Vfmadd213sd _ _ _ _
+            Vfmsub231sd _ _ _ _
+            Vfmsub213sd _ _ _ _
+            Vfmsub132sd _ _ _ _
+            ...
+    |
+254 | defsF (Movapd _ r _)         = singleton r
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/CF.hs:342:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘defs’:
+        Patterns of type ‘X86 reg freg ann’ not matched:
+            Vfmadd213sd _ _ _ _
+            Vfmsub231sd _ _ _ _
+            Vfmsub213sd _ _ _ _
+            Vfmsub132sd _ _ _ _
+            ...
+    |
+342 | defs (MovRR _ r _)     = singleton r
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Sp.hs:54:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘ao’: Patterns of type ‘Int’ not matched: _
+   |
+54 | ao o | Just i8 <- mi8 o = RC BP i8
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/Fr.hs:65:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘fi’:
+        Patterns of type ‘a’ not matched:
+            p where p is not one of {(-46), (-45), (-44), ...}
+   |
+65 | fi 10 = D0; fi 11 = D1; fi 12 = D2; fi 13 = D3
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/Sp.hs:55:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘ao’: Patterns of type ‘Int’ not matched: _
+   |
+55 | ao o | Just w16 <- m16 o = RP FP w16
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/G.hs:261:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘freeze’:
+        Patterns of type ‘K’, ‘St’ not matched: _ _
+    |
+261 | freeze ᴋ s | Just (u, _) <- IS.minView (fr$wkls s) =
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/G.hs:286:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘coalesce’:
+        Patterns of type ‘K’, ‘St’ not matched: _ _
+    |
+286 | coalesce ᴋ s | Just (m@(x,y), nWl) <- S.minView (wl$mvS s) =
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/G.hs:299:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘sspill’:
+        Patterns of type ‘K’, ‘St’ not matched: _ _
+    |
+299 | sspill ᴋ s | Just (m, nSp) <- IS.minView (sp$wkls s) = freezeMoves ᴋ m $ mapWk (iSimp m . \wk -> wk { sp = nSp }) s
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/P.hs:38:29: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘(Either
+                             Data.IntSet.Internal.IntSet (IM.IntMap X86Reg),
+                           Either
+                             Data.IntSet.Internal.IntSet (IM.IntMap FX86Reg))’ not matched:
+            ((Right _), (Left _))
+            ((Left _), (Left _))
+   |
+38 |               where rmaps = case (regsM, fregsM) of
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/P.hs:40:40: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘fregs’
+   |
+40 |                         (Left s, Right fregs) ->
+   |                                        ^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/P.hs:37:29: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘(Either
+                             Data.IntSet.Internal.IntSet (IM.IntMap AReg),
+                           Either Data.IntSet.Internal.IntSet (IM.IntMap FAReg))’ not matched:
+            ((Right _), (Left _))
+            ((Left _), (Left _))
+   |
+37 |               where rmaps = case (regsM, fregsM) of
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/P.hs:42:40: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘fregs’
+   |
+42 |                         (Left s, Right fregs) ->
+   |                                        ^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:116:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘bitC’:
+        Patterns of type ‘Word8’ not matched:
+            p where p is not one of {0, 1}
+    |
+116 | bitC 0x0 = 0x1
+    | ^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:147:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘mkVexA’:
+        Patterns of type ‘Word8’, ‘PP’, ‘VEXM’, ‘FX86Reg’, ‘FX86Reg’,
+                         ‘Addr X86Reg’ not matched:
+            _ _ _ _ _ (R _)
+            _ _ _ _ _ (RC32 _ _)
+            _ _ _ _ _ (RS _ _ _)
+            _ _ _ _ _ (RC Rcx _)
+            ...
+    |
+147 | mkVexA opc pp mm xr0 xr1 (RSD b s i d)=
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:346:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+346 |         (0, b1) = modRM r1
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:362:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+362 |         (0, b1) = modRM r1
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:392:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+392 |     let (0, b1) = modRM r1
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:430:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+            (p, _) where p is not one of {0}
+    |
+430 |         (0, b1) = modRM r1
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:445:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+445 |     let (0, b0) = modRM r0
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:451:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+451 |     let (0, bb) = modRM rb
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:755:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+755 |     let (0, b) = modRM Rsp
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:781:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+781 |         (0, bi) = modRM Rsp
+    |         ^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:789:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+789 |         (0, bi) = modRM Rsp
+    |         ^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:839:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+839 |     let (0, bi) = modRM ar
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/X86/Byte.hs:846:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Word8, Word8)’ not matched:
+            (p, _) where p is not one of {0}
+    |
+846 |     let (0, bi) = modRM ar
+    |         ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/Byte.hs:287:104: warning: [GHC-97441] [-Woverflowed-literals]
+    Literal 18446462598732840960 is out of the Int range -9223372036854775808..9223372036854775807
+    |
+287 |         w0=p .&. 0xffff; w1=(p .&. 0xffff0000) `lsr` 16; w2=(p .&. 0xFFFF00000000) `lsr` 32; w3=(p .&. 0xFFFF000000000000) `lsr` 48
+    |                                                                                                        ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/Byte.hs:295:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘rpf’:
+        Patterns of type ‘Pfop’ not matched:
+            Pfop PLI _ _
+            Pfop PLD L2 _
+            Pfop PLD L3 _
+            Pfop PST L2 _
+            ...
+    |
+295 | rpf (Pfop PLD L1 Keep) = 0b0
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/Byte.hs:300:109: warning: [GHC-97441] [-Woverflowed-literals]
+    Literal 18446462598732840960 is out of the Int range -9223372036854775808..9223372036854775807
+    |
+300 | m4 r a = let w0=a .&. 0xffff; w1=(a .&. 0xffff0000) `lsr` 16; w2=(a .&. 0xFFFF00000000) `lsr` 32; w3=(a .&. 0xFFFF000000000000) `lsr` 48
+    |                                                                                                             ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C.hs:113:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘abs’ and ‘signum’
+    • In the instance declaration for ‘Num CE’
+    |
+113 | instance Num CE where
+    |          ^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C.hs:120:10: warning: [GHC-06201] [-Wmissing-methods]
+    • No explicit implementation for
+        ‘abs’ and ‘signum’
+    • In the instance declaration for ‘Num (CFE t Double e)’
+    |
+120 | instance Num (CFE t Double e) where
+    |          ^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C.hs:272:11: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘ds’
+    |
+272 | prettyCS (ds,ss) = pCS (const"") ss
+    |           ^^
+
+/Users/vanessa/dev/haskell/apple/src/IR/C.hs:45:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘cToIRM’:
+        Patterns of type ‘CS a’ not matched: PlProd _ _ []
+   |
+45 | cToIRM (G _ l retL)          = pure [IR.C l, IR.L retL]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/IR/C.hs:167:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘irAt’:
+        Patterns of type ‘ArrAcc’ not matched: At _ _ _ _ _
+    |
+167 | irAt (ARnk t l)                                                = AP (ctemp t) Nothing l
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/CF.hs:308:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘uses’:
+        Patterns of type ‘CS a’ not matched:
+            For _ _ _ _ _ _
+            Rof _ _ _ _
+            Rof1 _ _ _ _
+            R2of _ _ _ _ _
+            ...
+    |
+308 | uses (Ma _ _ _ _ r n _)    = uE r<>uE n
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Alloc.hs:28:35: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of Ss ‘mLive’
+   |
+28 | data Slots = Ss { keep :: !Alias, mLive :: [(AL, Sh ())] }
+   |                                   ^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/A.hs:201:5: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘pt’:
+        Patterns of type ‘E (T a)’ not matched:
+            Dfn _ _
+            ResVar _ _
+            Parens _ _
+            Ann _ _ _
+            ...
+    |
+201 |     pt (Var t n)                                             = parens (pretty n <+> ":" <+> pretty t)
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Ty/Clone.hs:63:5: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘cT’: Patterns of type ‘T a’ not matched: Ρ _ _
+   |
+63 |     cT F            = pure F
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:40:24: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of Subst ‘tySubst’
+   |
+40 | data Subst a = Subst { tySubst :: IM.IntMap (T a)
+   |                        ^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:42:24: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of Subst ‘sSubst’
+   |
+42 |                      , sSubst  :: IM.IntMap (Sh a) -- ^ Shape variables
+   |                        ^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:114:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘mI’:
+        Patterns of type ‘Focus’, ‘I a’, ‘I a’ not matched:
+            RF (IEVar _ _) (Ix _ _)
+            RF (IEVar _ _) (StaPlus _ _ _)
+            RF (IEVar _ _) (StaMul _ _ _)
+            LF (IEVar _ _) (StaPlus _ _ _)
+            ...
+    |
+114 | mI f i0@(Ix _ i) i1@(Ix _ j) | i == j = Right mempty
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:364:6: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘f’
+    |
+364 | mgSh f l inp (Π t0) (Π t1) = undefined
+    |      ^
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:364:8: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘l’
+    |
+364 | mgSh f l inp (Π t0) (Π t1) = undefined
+    |        ^
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:364:10: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘inp’
+    |
+364 | mgSh f l inp (Π t0) (Π t1) = undefined
+    |          ^^^
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:364:17: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘t0’
+    |
+364 | mgSh f l inp (Π t0) (Π t1) = undefined
+    |                 ^^
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:364:24: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘t1’
+    |
+364 | mgSh f l inp (Π t0) (Π t1) = undefined
+    |                        ^^
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:503:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘tydrop’:
+        Patterns of type ‘Int’, ‘Sh a’ not matched:
+            p Nil where p is not one of {0}
+            p (SVar _) where p is not one of {0}
+            p (Rev _) where p is not one of {0}
+            p (Cat _ _) where p is not one of {0}
+            ...
+    |
+503 | tydrop 0 sh            = sh
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:810:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘checkTy’:
+        Patterns of type ‘T a’, ‘(C, a)’ not matched:
+            (P _) (IsOrd, _)
+            (P _) (IsEq, _)
+            (Ρ _ _) (IsOrd, _)
+            (Ρ _ _) (IsEq, _)
+            ...
+    |
+810 | checkTy (TVar n) (c, _)       = pure $ Just(n, c)
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Ty.hs:847:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘tyE’:
+        Patterns of type ‘Subst a’, ‘E a’ not matched: _ (Id _ _)
+    |
+847 | tyE s (EApp _ (Builtin _ Re) (ILit _ n)) = do
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/R/Dfn.hs:9:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘dedfn’:
+        Patterns of type ‘E a’ not matched: Id _ _
+  |
+9 | dedfn e@ILit{} = e
+  | ^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/R/Dfn.hs:37:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘replaceXY’:
+        Patterns of type ‘a -> Nm a’, ‘a -> Nm a’, ‘E a’ not matched:
+            _ _ (Dfn _ _)
+            _ _ (Parens _ _)
+            _ _ (Id _ _)
+   |
+37 | replaceXY _ y (ResVar l Y) = (Var l (y l), True)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/R.hs:70:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘rE’:
+        Patterns of type ‘E a’ not matched:
+            Dfn _ _
+            ResVar _ _
+            Parens _ _
+            Id _ (FoldSOfZip _ _ _)
+            ...
+   |
+70 | rE (Lam l n e) = doLocal $ do
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/run/QC.hs:36:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘gg’:
+        Patterns of type ‘Sh a’ not matched:
+            Rev _
+            Cat _ _
+            Π _
+            Cons (IEVar _ _) _
+            ...
+   |
+36 | gg Nil = pure (0, [])
+   | ^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/run/QC.hs:74:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘ga’:
+        Patterns of type ‘T a’ not matched:
+            Li _
+            TVar _
+            Arrow _ _
+            P _
+            ...
+   |
+74 | ga (Arr sh A.F) = do
+   | ^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Parser/Rw.hs:43:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘fi’:
+        Patterns of type ‘Builtin’ not matched:
+            Log
+            IDiv
+            Neg
+            Sqrt
+            ...
+   |
+43 | fi C = 9
+   | ^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Parser/Rw.hs:59:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘lassoc’:
+        Patterns of type ‘Builtin’ not matched:
+            Log
+            IDiv
+            Neg
+            Sqrt
+            ...
+   |
+59 | lassoc IntExp = False
+   | ^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/CGen.hs:18:5: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘pretty’:
+        Patterns of type ‘CType’ not matched:
+            ΠC []
+            ΠC ((AC _):_)
+            ΠC ((ΠC _):_)
+            ΠC ((SC CI):_)
+            ...
+   |
+18 |     pretty (AC CR)="Af"; pretty (AC CI)="Ai"; pretty (AC CB)="Ab"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/CGen.hs:56:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘cTy’:
+        Patterns of type ‘T a’ not matched:
+            Li _
+            TVar _
+            Ρ _ _
+            Arrow (Arr _ _) _
+            ...
+   |
+56 | cTy F                 = pure (SC CR)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/CGen.hs:69:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘irTy’: Patterns of type ‘T a’ not matched: Li _
+   |
+69 | irTy F                 = pure ([], F)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/A/Opt.hs:25:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘optA’:
+        Patterns of type ‘E (T ())’ not matched:
+            Def _ _ _
+            Dfn _ _
+            ResVar _ _
+            Parens _ _
+            ...
+   |
+25 | optA (ILit F x)            = pure (FLit F (realToFrac x))
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/A/Opt.hs:25:1: warning: [GHC-61505]
+    Pattern match checker ran into -fmax-pmcheck-models=30 limit, so
+      • Redundant clauses might not be reported at all
+      • Redundant clauses might be reported as inaccessible
+      • Patterns reported as unmatched might actually be matched
+    Suggested fix:
+      Increase the limit or resolve the warnings to suppress this message.
+   |
+25 | optA (ILit F x)            = pure (FLit F (realToFrac x))
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/A/Eta.hs:20:114: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘T ()’ not matched:
+            Arr _ _
+            F
+            I
+            B
+            ...
+   |
+20 |     lApps <- traverse (\t -> do { n <- nextN t ; pure (\e' -> let t' = eAnn e' in Lam (t ~> t') n e', \e' -> let Arrow _ cod = eAnn e' in EApp cod e' (Var t n)) }) ts
+   |                                                                                                                  ^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/A/Eta.hs:69:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘ηM’:
+        Patterns of type ‘E (T ())’ not matched:
+            Let _ _ _
+            Def _ _ _
+            Dfn _ _
+            ResVar _ _
+            ...
+   |
+69 | ηM e@FLit{}                = pure e
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/I.hs:62:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘iM’:
+        Patterns of type ‘E (T ())’ not matched: Id _ _
+   |
+62 | iM e@Builtin{} = pure e
+   | ^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/I.hs:91:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘bM’:
+        Patterns of type ‘E (T ())’ not matched:
+            Let _ _ _
+            Def _ _ _
+   |
+91 | bM e@Builtin{} = pure e
+   | ^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:15:58: warning: [GHC-38856] [-Wunused-imports]
+    The import of ‘foldl1'’ from module ‘Data.List’ is redundant
+   |
+15 | import           Data.List                        (find, foldl1', scanl')
+   |                                                          ^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:26:18: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of CSt ‘tempU’
+   |
+26 | data CSt = CSt { tempU       :: !Int
+   |                  ^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:27:18: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of CSt ‘arrU’
+   |
+27 |                , arrU        :: !AL
+   |                  ^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:28:18: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of CSt ‘assemblerSt’
+   |
+28 |                , assemblerSt :: !Int
+   |                  ^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:29:18: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of CSt ‘label’
+   |
+29 |                , label       :: !Label
+   |                  ^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:33:18: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of CSt ‘d2vars’
+   |
+33 |                , d2vars      :: IM.IntMap F2Temp
+   |                  ^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:37:18: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of CSt ‘mts’
+   |
+37 |                , mts         :: IM.IntMap Temp
+   |                  ^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:96:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘bT’:
+        Patterns of type ‘T a’ not matched:
+            Li _
+            TVar _
+            Arrow _ _
+            Ρ _ _
+   |
+96 | bT (P ts)=sum (bT<$>ts); bT F=8; bT I=8; bT B=1; bT Arr{}=8
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:226:5: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘go’:
+        Patterns of type ‘E (T ())’, ‘[FTemp]’, ‘[Temp]’ not matched:
+            (ALit _ _) _ _
+            (Var _ _) _ _
+            (Builtin _ _) _ _
+            (EApp _ _ _) _ _
+            ...
+    |
+226 |     go (Lam _ x@(Nm _ _ F) e) (fr:frs) rs = addD x fr *> go e frs rs
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:227:79: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘bt’:
+        Patterns of type ‘Temp’ not matched:
+            ATemp _
+            C0
+            C1
+            C2
+            ...
+    |
+227 |     go (Lam _ x@(Nm _ _ B) e) frs (r:rs) = addB x (bt r) *> go e frs rs where bt (ITemp i)=BTemp i
+    |                                                                               ^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:240:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘rtemp’:
+        Patterns of type ‘T a’ not matched:
+            Arr _ _
+            Li _
+            TVar _
+            Arrow _ _
+            ...
+    |
+240 | rtemp F=FT<$>nF; rtemp I=IT<$>nI; rtemp B=PT<$>nBT
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:252:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘hasS’:
+        Patterns of type ‘E a’ not matched:
+            ALit _ _
+            ILit _ _
+            BLit _ _
+            Let _ _ _
+            ...
+    |
+252 | hasS (Builtin _ b)     = bS b
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:261:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘write2’:
+        Patterns of type ‘E (T ())’, ‘[F2Temp]’, ‘F2Temp’ not matched:
+            (ALit _ _) (_:_) _
+            (Var _ _) (_:_) _
+            (Builtin _ _) (_:_) _
+            (EApp _ _ _) (_:_) _
+            ...
+    |
+261 | write2 (Lam _ x e) (v:vs) vret = addD2 x v *> write2 e vs vret
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:268:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘writeF’:
+        Patterns of type ‘E (T ())’, ‘[Arg]’, ‘RT’ not matched:
+            (ALit _ _) (_:_) _
+            (Var _ _) (_:_) _
+            (Builtin _ _) (_:_) _
+            (EApp _ _ _) (_:_) _
+            ...
+    |
+268 | writeF (Lam _ x e) (AA r l:rs) ret = addAVar x (l,r) *> writeF e rs ret
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:307:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘arg’:
+        Patterns of type ‘T ()’, ‘Ix'd’ not matched: _ _
+    |
+307 | arg ty at | isR ty = do
+    | ^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:315:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘rW’:
+        Patterns of type ‘T ()’, ‘Ix'd’ not matched: _ _
+    |
+315 | rW ty at | isR ty = do
+    | ^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:337:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘art’:
+        Patterns of type ‘Arg’ not matched: AA _ _
+    |
+337 | art (IPA r)=IT r;art (FA r)=FT r; art (BA r)=PT r
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:406:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘codT’:
+        Patterns of type ‘T ()’ not matched:
+            Arr _ _
+            F
+            I
+            B
+            ...
+    |
+406 | codT (Arrow _ t@Arrow{}) = codT t; codT (Arrow _ t) = t
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:418:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘llet’:
+        Patterns of type ‘(Nm (T ()), E (T ()))’ not matched:
+            (_, _)
+            (_, _)
+    |
+418 | llet (n,e') | isArr (eAnn e') = do
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:432:16: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of AD ‘eigen’
+    |
+432 | data AD = AD { eigen :: !Temp, alabel :: !(Maybe AL), eit :: Maybe (T ())
+    |                ^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:432:32: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of AD ‘alabel’
+    |
+432 | data AD = AD { eigen :: !Temp, alabel :: !(Maybe AL), eit :: Maybe (T ())
+    |                                ^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:432:55: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of AD ‘eit’
+    |
+432 | data AD = AD { eigen :: !Temp, alabel :: !(Maybe AL), eit :: Maybe (T ())
+    |                                                       ^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:433:16: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of AD ‘elemSz’
+    |
+433 |              , elemSz :: Maybe Int64
+    |                ^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:434:16: warning: [GHC-40910] [-Wunused-top-binds]
+    Defined but not used: record field of AD ‘arrn’
+    |
+434 |              , arrn :: Maybe CE
+    |                ^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:440:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘fill’:
+        Patterns of type ‘E (T ())’, ‘AD’, ‘[RA]’ not matched:
+            (ALit _ _) _ _
+            (Var _ _) _ _
+            (Lam _ _ _) _ _
+            (ILit _ _) _ _
+            ...
+    |
+440 | fill (Builtin (Arr sh F) Eye) (AD t lA _ _ _) [] | Just [i,_] <- staIx sh = do
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:440:1: warning: [GHC-61505]
+    Pattern match checker ran into -fmax-pmcheck-models=30 limit, so
+      • Redundant clauses might not be reported at all
+      • Redundant clauses might be reported as inaccessible
+      • Patterns reported as unmatched might actually be matched
+    Suggested fix:
+      Increase the limit or resolve the warnings to suppress this message.
+    |
+440 | fill (Builtin (Arr sh F) Eye) (AD t lA _ _ _) [] | Just [i,_] <- staIx sh = do
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:502:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘afort’:
+        Patterns of type ‘T a’, ‘CE’, ‘IRel’, ‘CE’,
+                         ‘Temp -> [CS ()]’ not matched:
+            F _ _ _ _
+            I _ _ _ _
+            B _ _ _ _
+            (Li _) _ _ _ _
+            ...
+    |
+502 | afort (Arr sh _) el c eu ss = do {i <- nI; pure (for sh i el c eu (ss i))}
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:622:5: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘w’:
+        Patterns of type ‘T a’, ‘ArrAcc’, ‘RT’ not matched:
+            _ _ (FT _)
+            _ _ (PT _)
+            _ _ (FT _)
+            _ _ (PT _)
+            ...
+    |
+622 |     w ty at tt      | isR ty = wt at tt
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:750:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘[Temp]’ not matched:
+            []
+            []
+            []
+    |
+750 |     let _:sstrides = sts; sss=init sssϵ
+    |         ^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:788:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘[Temp]’ not matched:
+            []
+            []
+            []
+    |
+788 |     let _:sstrides = sts; sss=init sssϵ
+    |         ^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:827:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘[Temp]’ not matched:
+            []
+            []
+            []
+    |
+827 |     let _:sstrides = sts; sss=init sssϵ
+    |         ^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:857:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘[Temp]’ not matched:
+            []
+            []
+            []
+    |
+857 |     let _:sstrides = sts; sss=init sssϵ
+    |         ^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:968:21: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In an irrefutable pattern:
+        Patterns of type ‘Maybe FTemp’ not matched:
+            Nothing
+            Nothing
+            Nothing
+    |
+968 |     (prologue, et, ~(Just zs)) <- if re xSh then pure (id, FTmp z0, Nothing) else do {zs <- nF; pure ((MX () zs 0:), FTmp zs+FTmp z0, Just zs)}
+    |                     ^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1041:21: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In an irrefutable pattern:
+        Patterns of type ‘Maybe FTemp’ not matched:
+            Nothing
+            Nothing
+            Nothing
+     |
+1041 |     (prologue, et, ~(Just zs)) <- if ce bSh then pure (id, FTmp z0, Nothing) else do {zs <- nF; pure ((MX () zs 0:), FTmp zs+FTmp z0, Just zs)}
+     |                     ^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1303:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘[Temp]’ not matched:
+            []
+            []
+            []
+            []
+     |
+1303 |     let _:sstrides = sts; (_:dstrides) = std
+     |         ^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1303:27: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘[Temp]’ not matched:
+            []
+            []
+            []
+            []
+     |
+1303 |     let _:sstrides = sts; (_:dstrides) = std
+     |                           ^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1396:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘[Temp]’ not matched:
+            []
+            []
+            []
+     |
+1396 |     let _:strides = sts; sss=init plS
+     |         ^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1482:17: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘T ()’ not matched:
+            Arr _ _
+            Li _
+            TVar _
+            Arrow _ _
+            ...
+     |
+1482 |         eCond = case ty of
+     |                 ^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1659:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘cond’:
+        Patterns of type ‘E (T ())’, ‘E (T ())’, ‘E (T ())’,
+                         ‘RT’ not matched:
+            (ALit _ _) _ _ _
+            (Var _ _) _ _ _
+            (Builtin _ _) _ _ _
+            (Lam _ _ _) _ _ _
+            ...
+     |
+1659 | cond (EApp _ (EApp _ (Builtin (Arrow F _) op) c0) c1) e e1 (FT t) | Just cmp <- frel op, Just cfe <- mFEval e1 = do
+     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1810:17: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘FBin’ not matched:
+            FMinus
+            FDiv
+            FExp
+     |
+1810 |     let seed2 = case c0 of {FPlus -> MX2 () acc2 (ConstF (0,0)); FTimes -> MX2 () acc2 (ConstF (1,1)); FMax -> DS () acc2 acc; FMin -> DS () acc2 acc}
+     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1831:17: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘FBin’ not matched:
+            FMinus
+            FDiv
+            FExp
+     |
+1831 |     let seedO = case c of {FPlus -> MX2 () acc2 (ConstF (0,0)); FTimes -> MX2 () acc2 (ConstF (1,1)); FMax -> DS () acc2 acc; FMin -> DS () acc2 acc}
+     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1898:9: warning: [GHC-62161] [-Wincomplete-uni-patterns]
+    Pattern match(es) are non-exhaustive
+    In a pattern binding:
+        Patterns of type ‘(Label, [Arg], RT)’ not matched:
+            (_, [], _)
+            (_, (_:_:_), _)
+            (_, [_], (IT _))
+            (_, [_], (PT _))
+     |
+1898 |     let (l, [a], FT r) = getT st f
+     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/C/Trans.hs:1934:13: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘T ()’ not matched:
+            Li _
+            TVar _
+            Arrow _ _
+            P _
+            ...
+     |
+1934 |             case eAnn e of
+     |             ^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/as/As.hs:26:15: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘(String, String)’ not matched:
+            ([], _)
+            ((p:_), _) where p is not one of {'a'}
+            (['a'], _)
+            (('a':p:_), _) where p is not one of {'a'}
+            ...
+   |
+26 |           exe=case (arch, os) of {("aarch64",_) -> "as"; (_,"linux") -> "aarch64-linux-gnu-as"}
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/as/As.hs:26:15: warning: [GHC-61505]
+    Pattern match checker ran into -fmax-pmcheck-models=30 limit, so
+      • Redundant clauses might not be reported at all
+      • Redundant clauses might be reported as inaccessible
+      • Patterns reported as unmatched might actually be matched
+    Suggested fix:
+      Increase the limit or resolve the warnings to suppress this message.
+   |
+26 |           exe=case (arch, os) of {("aarch64",_) -> "as"; (_,"linux") -> "aarch64-linux-gnu-as"}
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/src/Dbg.hs:82:11: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘zipS’:
+        Patterns of type ‘[X86.X86 reg freg a]’,
+                         ‘[BS.ByteString]’ not matched:
+            [] (_:_)
+            ((X86.IAddRR _ _ _):_) []
+            ((X86.IAddRI _ _ _):_) []
+            ((X86.ISubRR _ _ _):_) []
+            ...
+   |
+82 |     where zipS [] []                 = []
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/src/Dbg.hs:93:11: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘zipS’:
+        Patterns of type ‘[Aarch64.AArch64 reg freg a]’,
+                         ‘[BS.ByteString]’ not matched:
+            [] (_:_)
+            ((Aarch64.B _ _):_) []
+            ((Aarch64.Blr _ _):_) []
+            ((Aarch64.Bl _ _):_) []
+            ...
+   |
+93 |     where zipS [] []                                    = []
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/run/Main.hs:334:18: warning: [GHC-40910] [-Wunused-matches]
+    Defined but not used: ‘mp’
+    |
+334 | freeAsm (sz, fp, mp) = freeFunPtr sz fp -- *> traverse_ free mp
+    |                  ^^
+
+/Users/vanessa/dev/haskell/apple/run/Main.hs:427:9: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘cb’:
+        Patterns of type ‘a’ not matched: p where p is not one of {0, 1}
+    |
+427 |         cb 0=False; cb 1=True
+    |         ^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/run/Main.hs:441:21: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In a case alternative:
+        Patterns of type ‘T ()’ not matched:
+            Li _
+            TVar _
+            Ρ _ _
+    |
+441 |                     case eAnn e of
+    |                     ^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/run/Main.hs:471:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘rSz’:
+        Patterns of type ‘T a’ not matched:
+            Li _
+            TVar _
+            A.Arrow _ _
+            Ρ _ _
+    |
+471 | rSz A.B=1; rSz I=8; rSz A.F=8; rSz (P ts) = sum (rSz<$>ts); rSz Arr{}=8
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+/Users/vanessa/dev/haskell/apple/run/Main.hs:485:1: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘pR’:
+        Patterns of type ‘T a’, ‘Ptr b’ not matched:
+            (Arr _ _) _
+            (Li _) _
+            (TVar _) _
+            (A.Arrow _ _) _
+            ...
+    |
+485 | pR I p      = do {i <- peek (castPtr p :: Ptr Int64); pure (pretty i)}
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
+
+/Users/vanessa/dev/haskell/apple/run/Main.hs:554:35: warning: [GHC-62161] [-Wincomplete-patterns]
+    Pattern match(es) are non-exhaustive
+    In an equation for ‘sB’:
+        Patterns of type ‘a’ not matched: p where p is not one of {1, 0}
+    |
+554 |                             where sB 1 = "#t"; sB 0 = "#f"
+    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
+
+lib/E.chs:155:1: error: [GHC-03355]
+    • Illegal foreign declaration: requires one of these back ends:
+      native code generator, LLVM, compiling via C,
+      compiling to JavaScript, or no code generated
+    • When checking declaration:
+        foreign export ccall "apple_compile" apple_compile
+          :: Ptr JitCtx
+             -> CString -> Ptr CSize -> Ptr (Ptr Word64) -> IO (Ptr Word8)
+    |
+155 | foreign export ccall apple_compile :: Ptr JitCtx -> CString -> Ptr CSize -> Ptr (Ptr Word64) -> IO (Ptr Word8)
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+lib/E.chs:156:1: error: [GHC-03355]
+    • Illegal foreign declaration: requires one of these back ends:
+      native code generator, LLVM, compiling via C,
+      compiling to JavaScript, or no code generated
+    • When checking declaration:
+        foreign export ccall "apple_printty" apple_printty
+          :: CString -> Ptr CString -> IO CString
+    |
+156 | foreign export ccall apple_printty :: CString -> Ptr CString -> IO CString
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+lib/E.chs:157:1: error: [GHC-03355]
+    • Illegal foreign declaration: requires one of these back ends:
+      native code generator, LLVM, compiling via C,
+      compiling to JavaScript, or no code generated
+    • When checking declaration:
+        foreign export ccall "apple_dumpasm" apple_dumpasm
+          :: CString -> Ptr CString -> IO CString
+    |
+157 | foreign export ccall apple_dumpasm :: CString -> Ptr CString -> IO CString
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+lib/E.chs:158:1: error: [GHC-03355]
+    • Illegal foreign declaration: requires one of these back ends:
+      native code generator, LLVM, compiling via C,
+      compiling to JavaScript, or no code generated
+    • When checking declaration:
+        foreign export ccall "apple_dumpir" apple_dumpir
+          :: CString -> Ptr CString -> IO CString
+    |
+158 | foreign export ccall apple_dumpir :: CString -> Ptr CString -> IO CString
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+lib/E.chs:159:1: error: [GHC-03355]
+    • Illegal foreign declaration: requires one of these back ends:
+      native code generator, LLVM, compiling via C,
+      compiling to JavaScript, or no code generated
+    • When checking declaration:
+        foreign export ccall "apple_ty" apple_ty
+          :: CString -> Ptr CString -> IO (Ptr FnTy)
+    |
+159 | foreign export ccall apple_ty :: CString -> Ptr CString -> IO (Ptr FnTy)
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+lib/E.chs:160:1: error: [GHC-03355]
+    • Illegal foreign declaration: requires one of these back ends:
+      native code generator, LLVM, compiling via C,
+      compiling to JavaScript, or no code generated
+    • When checking declaration:
+        foreign export ccall "apple_print_ts_sz" apple_print_ts_sz
+          :: CString -> Ptr CSize -> Ptr CString -> IO CString
+    |
+160 | foreign export ccall apple_print_ts_sz :: CString -> Ptr CSize -> Ptr CString -> IO CString
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/test/data/ghc-pkg b/test/data/ghc-pkg
new file mode 100644
--- /dev/null
+++ b/test/data/ghc-pkg
@@ -0,0 +1,2 @@
+dynamic-library-dirs: /Users/vanessa/.ghcup/ghc/9.10.1/lib/ghc-9.10.1/lib/../lib/aarch64-osx-ghc-9.10.1
+                      /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib
diff --git a/test/data/git-tags b/test/data/git-tags
new file mode 100644
--- /dev/null
+++ b/test/data/git-tags
@@ -0,0 +1,247 @@
+255a03163b32e9bfe0111724f516d65be98ea447	HEAD
+a09198f36cb3481322221cea7f75c103e0427755	refs/heads/0.6
+bb1536329896e6e211c3bafee7befb06d06fc856	refs/heads/0.8
+c87e722e1df520053d2cbd41b32062aaf240f96e	refs/heads/0.8-dev
+2cae36f4b6c5a82dd85b1f4f8d1a249f8017154b	refs/heads/0.9-dev
+24d8ef6e8fdcc24f0b34cc3b810396a534b58e6c	refs/heads/1.0-dev
+4251be9306a33f957678c4045e66b909f6e531e7	refs/heads/active-deactive-global-effects
+dacf6f2fc3a44bf9a9c01f9d3db564a6bda8a77a	refs/heads/bus-mapping
+61835bb4e68a5198375b5ba16978ab8959418522	refs/heads/bus-routing-per-synth
+255a03163b32e9bfe0111724f516d65be98ea447	refs/heads/develop
+c9576783e72dbd05decc454034aa1e14737c1997	refs/heads/event-based
+0fe55fb0a65364431117a8eb545892708532983b	refs/heads/fix-start-end
+88ae0cb11c60e3d3e3244c88a4a60738b4b9c3bf	refs/heads/long-soundfile-support
+7abb62e89649daa1232b9cbd6427241868abd30e	refs/heads/master
+b59c986f2080d7521206c97fdb152c7b7f49c5e7	refs/heads/pitch-samples
+92c9a96fd6817e540f755435d56f97d51f93cd33	refs/heads/revert-84-monitor-pause
+d62df267dc20064b7e2229915856671f30ed0cc5	refs/heads/steal-voices
+3d833a5d3770224cc51d9f9ecfccc1fb793a28be	refs/heads/topic-add-interpret-from-tidal
+9f4577a5e10c88dc57caa9693a468293ca28a9aa	refs/heads/topic-dj-filter
+ed53d04849121b2ee6e6304f7603d27c1b78ba20	refs/heads/topic-documentation
+5374117cb64e6d4f1645004b8d4da055a4eba87b	refs/heads/topic-dont-cut-at-start
+93cb78819d6e9c5f027d0b8ebbfb9e2159698123	refs/heads/topic-events
+958e454367df00be8b105e18131440511194780f	refs/heads/topic-events-multi
+f6a0f388a9ffdd04ab37e478845a4788c781ee10	refs/heads/topic-fix-cutgroups-in-same-block
+e068008dc99f54688fd2a10b41a2dd10cf5b2a6b	refs/heads/topic-fix-fade-in
+e72c566e31840bf3f00cad729fc72d702b8817ce	refs/heads/topic-flotsam
+29d0ca4b62e7838ad8843401ac33a0f8e29cba33	refs/heads/topic-global-effects-fix
+a1a30e8b4d95e9ac5f15dd6d343d09de47e655c8	refs/heads/topic-improve-debug-synth
+e46f4b1bd7e48c7bed84a4f76fcb53100f4f258c	refs/heads/topic-info
+bfce630b86246bf69b1375bcd760150f47c8184b	refs/heads/topic-leslie-multichannel-fix
+26d141348b5ee09ffb832e858256c58d976ccf3c	refs/heads/topic-make-dirt-a-proxy
+d5888931ee9a14dea85e3fb8fca3894d7bb150be	refs/heads/topic-midinote
+a529ace3700f02a2ebf9124f67043d6438a7def3	refs/heads/topic-net-responders
+9211cadc580d254e5fd313e05051c8d63f22f76c	refs/heads/topic-nrpn-fix
+89b61d3e6e3ae28ce5e6b656fbc3d5be97cee97a	refs/heads/topic-numWireBufs
+f15a1b5d87914909c57bda51315017fe1bba8aca	refs/heads/topic-onsets
+cda0b347b1f0b2b8179da252315e5f7bf8c8829b	refs/heads/topic-panic
+62ba18c2eb26e06bf214ece26fc6e58a31bb1f52	refs/heads/topic-panning
+bd57d794366cc454b8abd917847e0cea1821f616	refs/heads/topic-parameter-syntax
+1058ffc2cdca95c664beffa64c3f1364c44160c6	refs/heads/topic-performance-improvements
+9a104d423f4f24396768892a48de9fae0ab36c78	refs/heads/topic-pitch-model
+d7202e21a65a038c4fe580dce617512715ec5fc1	refs/heads/topic-polymidi
+b840bf992a38a5254be12b3474a550200a6ecc13	refs/heads/topic-protect-orbit-wrap
+aef5ed0eda92f43d145787b02332fc0ea0ab594a	refs/heads/topic-read-on-demand
+8ee7e9941c520681cda57b322d5f6ea57701a0c6	refs/heads/topic-report-missing-sound
+86a6755838dca8a552e10bac61905b305f7427c1	refs/heads/topic-resolve-resume
+6b56f027133354b69821bef6c7777ab2d1f31692	refs/heads/topic-rms
+eaa02aa3346bc277800db4e4f0348badb9ee6e50	refs/heads/topic-safety-limit
+00ca6b53e9309cc7600f9f5a91212656213cc993	refs/heads/topic-send-immediate
+7b5d7000a85cc56b69059449105da51973e0c910	refs/heads/topic-separate-effects
+7b7d32b41e5c87547a0dc8da12402755b68ad0a2	refs/heads/topic-simplify-cuts
+133f11cd4a232847b318daeceae0fbd636c4f6ed	refs/heads/topic-sort-files
+041010da044501cf96b7c6a07164c9eacc12d78d	refs/heads/topic-tanh
+398bd5194f574c856a1ae8f5521ffea15bd1cf7c	refs/heads/topic-test-midi-queue
+f8a9dbec469ab45633be291ed363c814456d1f29	refs/heads/topic-test-pause-change
+f24d3adc88224505e59db01f83b1746d0062f36c	refs/heads/topic-twelve-orbits
+165d96ef3fe5c7b7a1ba4d00762d2e3321f916cd	refs/heads/topic/bypassable-limiter
+f751779a8fdb181415d04cdf8cf308b79609fc7d	refs/heads/topic/clarify-hacks
+3a16d5ba7f314ad1476678377ceaabcab8482880	refs/heads/topic/efficient-note-event
+16495f1097d2c22f91dd5d2e5668e4b05c8aca79	refs/heads/topic/fix-duplicate-instances
+47ac2d94093333092c43c83193e20a6298349955	refs/heads/topic/fix-midi-gain
+fc263c0974b95f520684bc120ddf6dbc1384d931	refs/heads/topic/more-orbits
+aef50b9d7881804b3878d01e1aed2b85a469c7a3	refs/heads/topic/part-time-error
+30f11d0b3b577648b68312fd8e4ae5ac98e3e607	refs/heads/topic/speed-scaled-freqs
+1c7ccb43061e2e50fa0f630e8d74f8b137910ca3	refs/heads/topic/support-gain-in-controlbus
+ac3e7edceb786b2cf190ffb98c3f2f41e73a30bb	refs/heads/use-speed-for-note
+9418b2405af27eee729b31c999870f9fec870601	refs/heads/yaxu-patch-1
+224e70dbfb78f05efeef05b90049e589f2d0a4f8	refs/pull/101/head
+7fc2225f122c7c879815b55d03e4a519bca5ac35	refs/pull/102/head
+096827026a65e8204026fcecf61e3e5daaa5632b	refs/pull/103/head
+86a6755838dca8a552e10bac61905b305f7427c1	refs/pull/110/head
+81d08873b7b1c63c7ad4f0e59670097cc054e3de	refs/pull/112/head
+1054ae9c196bf00d7a8883f33923f2d54f148784	refs/pull/113/head
+811f7381140e0490563b87fcc968fb6ebe84243a	refs/pull/116/head
+ee4f276ba13576d8d2facc74779ab886715adb18	refs/pull/118/head
+9f4577a5e10c88dc57caa9693a468293ca28a9aa	refs/pull/119/head
+ed53d04849121b2ee6e6304f7603d27c1b78ba20	refs/pull/12/head
+61835bb4e68a5198375b5ba16978ab8959418522	refs/pull/121/head
+604ab6555a41cfd0fb878726b9f6674bfa474b71	refs/pull/124/head
+d8f61f97b5252a445678b11197b5c6f68202a588	refs/pull/126/head
+6331841b879d3c571004733fd7d76a08e240d301	refs/pull/127/head
+887e1c5566abe5c75d887b21b67c4af4710af440	refs/pull/128/head
+b6b8541910f42a1a4dfd48b934a5bcc321e160c7	refs/pull/13/head
+89ed2c2bea5bafaf7d3810fb337f4685d7af14df	refs/pull/13/merge
+9d5cdc98fed515ced90bb54585e25888cf94f7b0	refs/pull/132/head
+fc263c0974b95f520684bc120ddf6dbc1384d931	refs/pull/135/head
+44590b56ad4b5b6dc22547ff18fb70d364017053	refs/pull/136/head
+59e3d276556271055dfd3b1ea494f4f7cad86b0b	refs/pull/138/head
+44ba6c0ae6653009c5c0078336f60cbaabe52bcb	refs/pull/139/head
+689e7b1a25565f1ab35d097b9d336feec81885d5	refs/pull/14/head
+f24d3adc88224505e59db01f83b1746d0062f36c	refs/pull/142/head
+b60e9b9fdf9c752e07d7581313f9ad99f6e3e98b	refs/pull/144/head
+ad3aa714dce9c7c6bc1bbc5b84a262e42c56ec6d	refs/pull/145/head
+11287b81916321c7020c508dfa1c50ad3ba443cc	refs/pull/149/head
+01f763ea8507da528b552b1e59b4f1dc1494ad7d	refs/pull/15/head
+e2d4619a44f3a946e9efcf04c22c6292c0a7c26b	refs/pull/150/head
+98244fa891a62456113276336dd6709e070389f7	refs/pull/153/head
+64c833a23ec8385acbadccfb3c8d325d1f521326	refs/pull/155/head
+ed252b0080827b380dda9eeda737a5d284ee49b1	refs/pull/158/head
+6da4af3acf0ba77d30833edd4bf69e972522d541	refs/pull/159/head
+1058ffc2cdca95c664beffa64c3f1364c44160c6	refs/pull/16/head
+85a875456e4eae3bc2c6ce5f8e8fc3c8daa7e763	refs/pull/16/merge
+ee65bf8250c4c5debbd274474bd443291f6dd4e4	refs/pull/160/head
+7fcd6cf4a23e26dac9d55e5190a43db2e7f57883	refs/pull/161/head
+9211cadc580d254e5fd313e05051c8d63f22f76c	refs/pull/162/head
+3a16d5ba7f314ad1476678377ceaabcab8482880	refs/pull/163/head
+7013c2f70b85f1bbf8ab9af5f676ba6c4f33f15d	refs/pull/164/head
+727203c9efa1e122a036ad4f50c57dd71004d909	refs/pull/165/head
+eaa02aa3346bc277800db4e4f0348badb9ee6e50	refs/pull/167/head
+d7202e21a65a038c4fe580dce617512715ec5fc1	refs/pull/168/head
+9f139ae162595334b437fb73ca33f90ccf784fb2	refs/pull/169/head
+f185b73c5a48fa8d9bd9e2577e9b7909a3708488	refs/pull/17/head
+dd7eaf0bd53a2901c1a2ce45ab4b0d41fb25e1be	refs/pull/170/head
+66f4db681c13b57bca1e9361b8cfa036f709ab96	refs/pull/173/head
+9418b2405af27eee729b31c999870f9fec870601	refs/pull/174/head
+b72f26384b4ac06187b8ff24678b2892cfaa187f	refs/pull/175/head
+6c083d9b935273f0cd6c006f360f39c4be3db058	refs/pull/177/head
+8af2da154cfb3aabbeeb1c8a678f7607ce0f26bc	refs/pull/179/head
+f3f71c2385bd5057ba9ffbc34f0253018784482e	refs/pull/18/head
+6ddd0dfab5a05fbe6d6b62fba99151903e0f1ee9	refs/pull/181/head
+2f31f42be32113d0add2a6f8e573e7ee4ca2765d	refs/pull/183/head
+ab8943454fad9d57d7605137f87277b94c597de3	refs/pull/184/head
+d5888931ee9a14dea85e3fb8fca3894d7bb150be	refs/pull/188/head
+89b61d3e6e3ae28ce5e6b656fbc3d5be97cee97a	refs/pull/189/head
+71d404e9e4342f6bf2c8a82244997b57b6f361b1	refs/pull/19/head
+439960c38a47c73aa0a83f5c5077f8ec1ae52cb2	refs/pull/191/head
+cda0b347b1f0b2b8179da252315e5f7bf8c8829b	refs/pull/197/head
+7758c69a2cb51abfa919c6359976664ab1220f90	refs/pull/198/head
+feda26f6e022b088659c0fa73c30c42c0d839732	refs/pull/2/head
+e6f6e5ac775601058e645ef8ff71b0e4883ab496	refs/pull/20/head
+8ee7e9941c520681cda57b322d5f6ea57701a0c6	refs/pull/201/head
+6ce62d7e1859aed96f94e13d2f9bdc7c63882e9b	refs/pull/202/head
+e46f4b1bd7e48c7bed84a4f76fcb53100f4f258c	refs/pull/203/head
+c53a440e0c8f9c029f07bc699e635b5533c73bdf	refs/pull/204/head
+377da63e3fd95c4e11050c64ee4b71fae3279ea8	refs/pull/206/head
+0fe55fb0a65364431117a8eb545892708532983b	refs/pull/208/head
+fff72f1b75c521222f460fff7bb58f625a3c396f	refs/pull/209/head
+f202b2744969bf2e6f8887706938ada32be88a63	refs/pull/21/head
+8abea7d526d086ad7a85600261128a8c35b1fed2	refs/pull/21/merge
+ad0b57959a276f5288f274d5100e8045cb37a281	refs/pull/210/head
+8c99aab75b1c8767026ea70075dafde48f023a4d	refs/pull/211/head
+2963c11e90b43a5ecd22a457c07b9aa74f11f04c	refs/pull/213/head
+1ce46fea49bb6f028e31f1ac723df86fed203bce	refs/pull/214/head
+a156ffe6c5964fe8b4f2b069c4b668b707248d6d	refs/pull/215/head
+dacf6f2fc3a44bf9a9c01f9d3db564a6bda8a77a	refs/pull/218/head
+165d96ef3fe5c7b7a1ba4d00762d2e3321f916cd	refs/pull/219/head
+d010665888069ebac63d3e45c8486f5fec32e121	refs/pull/220/head
+4f4adc9b07c255108d146695038c5e83dce9292d	refs/pull/221/head
+5cfaae0a77302e4c68566e0d85d8d6ab2a645114	refs/pull/224/head
+c2ad95e1c77ca5e4b2fb5d913c8e0acfc9c78261	refs/pull/225/head
+1c7ccb43061e2e50fa0f630e8d74f8b137910ca3	refs/pull/227/head
+3b08dde10096221811f0644edf2bf1775311112e	refs/pull/228/head
+26dba058c35836440f271b7cf12b7cccf7b7e076	refs/pull/229/head
+d281b6daba5ef843dcbaa5947a7b1129807fec62	refs/pull/232/head
+a529ace3700f02a2ebf9124f67043d6438a7def3	refs/pull/234/head
+47ac2d94093333092c43c83193e20a6298349955	refs/pull/236/head
+0aa5de5f67b5d52cbb6fbedd1a7a821a533e9910	refs/pull/239/head
+8b6525fb5eaf36b101acf129f81c6c4489252f54	refs/pull/241/head
+30f11d0b3b577648b68312fd8e4ae5ac98e3e607	refs/pull/244/head
+16495f1097d2c22f91dd5d2e5668e4b05c8aca79	refs/pull/246/head
+f97aa459da226df1f66113bb3136d1a03f2045bf	refs/pull/247/head
+a1a30e8b4d95e9ac5f15dd6d343d09de47e655c8	refs/pull/248/head
+c677681404849caefd6145b23f7918b5fe594aaa	refs/pull/25/head
+7b7d32b41e5c87547a0dc8da12402755b68ad0a2	refs/pull/252/head
+133f11cd4a232847b318daeceae0fbd636c4f6ed	refs/pull/257/head
+2d01eb4828dc2e50119b22c1623f8326baf76bf3	refs/pull/26/head
+f751779a8fdb181415d04cdf8cf308b79609fc7d	refs/pull/260/head
+547c2ad1c0490a2a0d8fd79cd4a10099602a8f19	refs/pull/261/head
+1d641e82f88e26412d8f1f7edd26849c3def60a7	refs/pull/262/head
+a24f6f9143b3d2b192864b43a6dbe18a08a41ade	refs/pull/262/merge
+bd1aa9fdcdc163c88d45d25ccb8e4b7b8c5e8f74	refs/pull/272/head
+8d958f50a82889d2c092db26dad9a20b4df4d32c	refs/pull/274/head
+f8a9dbec469ab45633be291ed363c814456d1f29	refs/pull/278/head
+05f20eddc270d1fb33d8adad97ebf81fd8846aae	refs/pull/28/head
+f9440cff90a23e05139e173126172c3920bca489	refs/pull/280/head
+f6a0f388a9ffdd04ab37e478845a4788c781ee10	refs/pull/284/head
+fdce4ed2886175344a911383e27ec504b9e9d674	refs/pull/285/head
+e72c566e31840bf3f00cad729fc72d702b8817ce	refs/pull/287/head
+f3e9c73612b8fa8ce6ef8b65e59999ecc6778521	refs/pull/288/head
+041010da044501cf96b7c6a07164c9eacc12d78d	refs/pull/289/head
+e40bda35e6293d7cf6771acea4f5153d63013583	refs/pull/289/merge
+fba19dac568c4be97c246b16e80caee0c52d03f2	refs/pull/291/head
+bd57d794366cc454b8abd917847e0cea1821f616	refs/pull/292/head
+a614eb4e08c1107107a2dda2d1c5c360f93b5839	refs/pull/294/head
+978c492805e3ac344453b09569b1041ef1ffc092	refs/pull/295/head
+50a518638d61bd1972e7868bfbff5fe25ab2ca2b	refs/pull/298/head
+1204846ca36493d153236df60ff6419b14d9f21a	refs/pull/3/head
+b840bf992a38a5254be12b3474a550200a6ecc13	refs/pull/30/head
+d555f4ead229a26d05e79d64bb0aa4b8a162aa5d	refs/pull/30/merge
+e9ab9d9ce3de1bf0f87b8977286ff919e2dfc8a1	refs/pull/303/head
+63ea3827fd567613ae421d0cfb939eb6287fa752	refs/pull/303/merge
+4251be9306a33f957678c4045e66b909f6e531e7	refs/pull/305/head
+5374117cb64e6d4f1645004b8d4da055a4eba87b	refs/pull/306/head
+fff4293595f34cf14ea912da3ade2a823009b85f	refs/pull/307/head
+3d833a5d3770224cc51d9f9ecfccc1fb793a28be	refs/pull/31/head
+3d833a5d3770224cc51d9f9ecfccc1fb793a28be	refs/pull/32/head
+bc52ade4cafea81fbc06b81218b1835041d02642	refs/pull/33/head
+9ee02c73f5f56018f6f273f06211794d520d5ff3	refs/pull/34/head
+3299251b6947959b07d3cba1907619af0822e678	refs/pull/35/head
+075d02975f01c780423950d46aa66d8dc84af247	refs/pull/4/head
+62ba18c2eb26e06bf214ece26fc6e58a31bb1f52	refs/pull/40/head
+9bb038a4a36c144de450fddcb5c1b55a9ff5a56a	refs/pull/42/head
+c5e2bda989a29b9319fe54683808cb8071fa55a4	refs/pull/43/head
+f7b6308851d9f400c294cc48ac502ca1aeadecbe	refs/pull/44/head
+45367bab40c65efd11999522879fa416217441a0	refs/pull/46/head
+b57b964566fe04af4029bec3ad7190353fc513ac	refs/pull/47/head
+cd85237c44a478532a00b32dd910d2afea19e01c	refs/pull/47/merge
+bddedf459709ec9aa3349a7dea46d7d2973fd4d9	refs/pull/49/head
+9685f9ffbbd0b44ca97b857ec7c8190ab54e0237	refs/pull/5/head
+29d0ca4b62e7838ad8843401ac33a0f8e29cba33	refs/pull/50/head
+bfce630b86246bf69b1375bcd760150f47c8184b	refs/pull/51/head
+1c02393d1dc37e968b6b26730baf1b31f75ec99e	refs/pull/52/head
+886b1887d7d0c2c384fc474e9c08e1c67e989b4c	refs/pull/52/merge
+2a036248321924fcaa4ed950d28fbbceab1b4223	refs/pull/53/head
+3e06977baaa856e57d23e7485a6fcde0112794be	refs/pull/55/head
+f5bccbc1eee4d32ebc7ef9295dc604a4c34d0a72	refs/pull/55/merge
+e083f542a36b413e57ca5e969e44c7e42f56e6d4	refs/pull/56/head
+b57b964566fe04af4029bec3ad7190353fc513ac	refs/pull/57/head
+defb5d89e25fcf3dbb8f3621ea3d6968038de92d	refs/pull/58/head
+7c791c5cd2c14d866750e47bcf4e8a1daaba3baf	refs/pull/6/head
+37aa08500e00f91903b16532b9f7e9e29275b664	refs/pull/60/head
+ceae7e999539bead183d0e859b217e0a8627e2bf	refs/pull/62/head
+ac3e7edceb786b2cf190ffb98c3f2f41e73a30bb	refs/pull/72/head
+8419be2f71d400825620c0d941b78a342c492c97	refs/pull/76/head
+15fec8fa9cf80abd50c6490ca72ac8d7e372c445	refs/pull/77/head
+050dbd147c8d7c0101a50002a3839493979ce01f	refs/pull/77/merge
+b59c986f2080d7521206c97fdb152c7b7f49c5e7	refs/pull/79/head
+e068008dc99f54688fd2a10b41a2dd10cf5b2a6b	refs/pull/8/head
+7b5d7000a85cc56b69059449105da51973e0c910	refs/pull/80/head
+990885c3abd04ee1560096e38f858827840da262	refs/pull/82/head
+95da7a724f7b99c8fed9c8f2a9772df610d57df2	refs/pull/84/head
+92c9a96fd6817e540f755435d56f97d51f93cd33	refs/pull/85/head
+60e0a5e222ae90aba72db586522f426d18825d11	refs/pull/9/head
+2afd37ac745c380dd607a5bc68d0d46fb36491bd	refs/tags/0.9.1
+753f4a174761d24f5bdd665bd8805e80f3575e06	refs/tags/1.0-alpha
+b60e9b9fdf9c752e07d7581313f9ad99f6e3e98b	refs/tags/1.1.1
+59d5f80fbc926110bbd1b93e08b12c17a051a9c5	refs/tags/v.1.7.3
+85e10518539cc559542d3051eb87323e7b968fe9	refs/tags/v1.0
+69514a476e4372bfab6bf432180c3bc4dc5da837	refs/tags/v1.1
+b60e9b9fdf9c752e07d7581313f9ad99f6e3e98b	refs/tags/v1.1.1
+9f139ae162595334b437fb73ca33f90ccf784fb2	refs/tags/v1.1.2
+439960c38a47c73aa0a83f5c5077f8ec1ae52cb2	refs/tags/v1.1.3
+4f4adc9b07c255108d146695038c5e83dce9292d	refs/tags/v1.7
+c2ad95e1c77ca5e4b2fb5d913c8e0acfc9c78261	refs/tags/v1.7.1
+7abb62e89649daa1232b9cbd6427241868abd30e	refs/tags/v1.7.2
+7e245e87f8f08a3d55e33a360bc97912f32fe69b	refs/tags/v1.7.3
+c7f32998572984705d340e7c1b9ed9ad998a39b6	refs/tags/v1.7.4
diff --git a/test/data/ls b/test/data/ls
new file mode 100644
--- /dev/null
+++ b/test/data/ls
@@ -0,0 +1,30 @@
+total 216
+-rw-r--r--   1 vanessa  staff   4375 Oct 30 17:58 CHANGELOG.md
+-rw-r--r--@  1 vanessa  staff  34523 Mar  2  2024 COPYING
+-rw-r--r--   1 vanessa  staff    111 Nov 17 07:43 DESIGN.md
+-rw-r--r--   1 vanessa  staff   7208 Nov 17 09:30 EXAMPLES.md
+-rw-r--r--   1 vanessa  staff    133 Nov  7 11:27 HASKELL-EXAMPLES.md
+-rw-r--r--@  1 vanessa  staff    673 Mar  2  2024 LICENSE
+-rw-r--r--   1 vanessa  staff   4381 Oct 29 16:18 Makefile
+-rw-r--r--   1 vanessa  staff   2620 Oct 30 22:45 README.md
+-rw-r--r--   1 vanessa  staff   6564 Oct 30 15:59 ROSETTA.md
+-rw-r--r--   1 vanessa  staff   6067 Nov 17 09:14 TODO.md
+drwxr-xr-x   3 vanessa  staff     96 Oct 11 12:38 bash
+drwxr-xr-x   4 vanessa  staff    128 Nov 17 18:31 bench
+-rw-r--r--   1 vanessa  staff    251 Nov 17 09:14 cabal.project
+-rw-r--r--   1 vanessa  staff     22 Oct 18 08:32 cabal.project.local
+drwxr-xr-x   4 vanessa  staff    128 Oct  5 15:27 csv
+drwxr-xr-x   7 vanessa  staff    224 Nov 17 18:47 doc
+drwxr-xr-x   4 vanessa  staff    128 Nov 17 09:14 docs
+drwxr-xr-x  55 vanessa  staff   1760 Nov 17 14:00 examples
+-rw-r--r--   1 vanessa  staff   3909 Nov 17 18:44 jacinda.cabal
+drwxr-xr-x  12 vanessa  staff    384 Oct 29 16:18 lib
+drwxr-xr-x   4 vanessa  staff    128 Nov 17 13:58 man
+drwxr-xr-x   3 vanessa  staff     96 Oct 24 11:43 prelude
+drwxr-xr-x  19 vanessa  staff    608 Nov 17 18:40 src
+drwxr-xr-x   6 vanessa  staff    192 Nov 17 18:42 test
+drwxr-xr-x   7 vanessa  staff    224 Nov 17 09:14 tex
+drwxr-xr-x   7 vanessa  staff    224 Nov 17 10:16 vscode
+-rw-r--r--   1 vanessa  staff    252 Oct 23 23:55 weeder.toml
+drwxr-xr-x   3 vanessa  staff     96 Nov 17 09:31 x
+drwxr-xr-x   3 vanessa  staff     96 Nov 11 10:46 zsh
diff --git a/test/data/otool b/test/data/otool
new file mode 100644
--- /dev/null
+++ b/test/data/otool
@@ -0,0 +1,311 @@
+libapple.dylib:
+Load command 0
+      cmd LC_SEGMENT_64
+  cmdsize 472
+  segname __TEXT
+   vmaddr 0x0000000000000000
+   vmsize 0x0000000000014000
+  fileoff 0
+ filesize 81920
+  maxprot 0x00000005
+ initprot 0x00000005
+   nsects 5
+    flags 0x0
+Section
+  sectname __text
+   segname __TEXT
+      addr 0x0000000000009c88
+      size 0x0000000000009b44
+    offset 40072
+     align 2^3 (8)
+    reloff 0
+    nreloc 0
+     flags 0x80000400
+ reserved1 0
+ reserved2 0
+Section
+  sectname __stubs
+   segname __TEXT
+      addr 0x00000000000137cc
+      size 0x000000000000021c
+    offset 79820
+     align 2^2 (4)
+    reloff 0
+    nreloc 0
+     flags 0x80000408
+ reserved1 0 (index into indirect symbol table)
+ reserved2 12 (size of stubs)
+Section
+  sectname __stub_helper
+   segname __TEXT
+      addr 0x00000000000139e8
+      size 0x0000000000000234
+    offset 80360
+     align 2^2 (4)
+    reloff 0
+    nreloc 0
+     flags 0x80000400
+ reserved1 0
+ reserved2 0
+Section
+  sectname __cstring
+   segname __TEXT
+      addr 0x0000000000013c20
+      size 0x000000000000036c
+    offset 80928
+     align 2^3 (8)
+    reloff 0
+    nreloc 0
+     flags 0x00000002
+ reserved1 0
+ reserved2 0
+Section
+  sectname __unwind_info
+   segname __TEXT
+      addr 0x0000000000013f8c
+      size 0x0000000000000070
+    offset 81804
+     align 2^2 (4)
+    reloff 0
+    nreloc 0
+     flags 0x00000000
+ reserved1 0
+ reserved2 0
+Load command 1
+      cmd LC_SEGMENT_64
+  cmdsize 312
+  segname __DATA_CONST
+   vmaddr 0x0000000000014000
+   vmsize 0x0000000000004000
+  fileoff 81920
+ filesize 16384
+  maxprot 0x00000003
+ initprot 0x00000003
+   nsects 3
+    flags 0x10
+Section
+  sectname __got
+   segname __DATA_CONST
+      addr 0x0000000000014000
+      size 0x00000000000000f0
+    offset 81920
+     align 2^3 (8)
+    reloff 0
+    nreloc 0
+     flags 0x00000006
+ reserved1 45 (index into indirect symbol table)
+ reserved2 0
+Section
+  sectname __mod_init_func
+   segname __DATA_CONST
+      addr 0x00000000000140f0
+      size 0x0000000000000008
+    offset 82160
+     align 2^3 (8)
+    reloff 0
+    nreloc 0
+     flags 0x00000009
+ reserved1 0
+ reserved2 0
+Section
+  sectname __const
+   segname __DATA_CONST
+      addr 0x00000000000140f8
+      size 0x0000000000000030
+    offset 82168
+     align 2^3 (8)
+    reloff 0
+    nreloc 0
+     flags 0x00000000
+ reserved1 0
+ reserved2 0
+Load command 2
+      cmd LC_SEGMENT_64
+  cmdsize 232
+  segname __DATA
+   vmaddr 0x0000000000018000
+   vmsize 0x0000000000004000
+  fileoff 98304
+ filesize 16384
+  maxprot 0x00000003
+ initprot 0x00000003
+   nsects 2
+    flags 0x0
+Section
+  sectname __la_symbol_ptr
+   segname __DATA
+      addr 0x0000000000018000
+      size 0x0000000000000168
+    offset 98304
+     align 2^3 (8)
+    reloff 0
+    nreloc 0
+     flags 0x00000007
+ reserved1 75 (index into indirect symbol table)
+ reserved2 0
+Section
+  sectname __data
+   segname __DATA
+      addr 0x0000000000018168
+      size 0x0000000000001400
+    offset 98664
+     align 2^3 (8)
+    reloff 0
+    nreloc 0
+     flags 0x00000000
+ reserved1 0
+ reserved2 0
+Load command 3
+      cmd LC_SEGMENT_64
+  cmdsize 72
+  segname __LINKEDIT
+   vmaddr 0x000000000001c000
+   vmsize 0x000000000000c000
+  fileoff 114688
+ filesize 47152
+  maxprot 0x00000001
+ initprot 0x00000001
+   nsects 0
+    flags 0x0
+Load command 4
+          cmd LC_ID_DYLIB
+      cmdsize 48
+         name @rpath/libapple.dylib (offset 24)
+   time stamp 1 Wed Dec 31 19:00:01 1969
+      current version 0.0.0
+compatibility version 0.0.0
+Load command 5
+            cmd LC_DYLD_INFO_ONLY
+        cmdsize 48
+     rebase_off 114688
+    rebase_size 280
+       bind_off 114968
+      bind_size 3688
+  weak_bind_off 0
+ weak_bind_size 0
+  lazy_bind_off 118656
+ lazy_bind_size 1832
+     export_off 120488
+    export_size 3760
+Load command 6
+     cmd LC_SYMTAB
+ cmdsize 24
+  symoff 124720
+   nsyms 749
+  stroff 137184
+ strsize 23240
+Load command 7
+            cmd LC_DYSYMTAB
+        cmdsize 80
+      ilocalsym 0
+      nlocalsym 410
+     iextdefsym 410
+     nextdefsym 154
+      iundefsym 564
+      nundefsym 185
+         tocoff 0
+           ntoc 0
+      modtaboff 0
+        nmodtab 0
+   extrefsymoff 0
+    nextrefsyms 0
+ indirectsymoff 136704
+  nindirectsyms 120
+      extreloff 0
+        nextrel 0
+      locreloff 0
+        nlocrel 0
+Load command 8
+     cmd LC_UUID
+ cmdsize 24
+    uuid AFCD0F4E-6BD9-3D32-A26E-B7FB159EC3EA
+Load command 9
+      cmd LC_BUILD_VERSION
+  cmdsize 32
+ platform 1
+    minos 15.0
+      sdk 15.1
+   ntools 1
+     tool 3
+  version 1115.7.3
+Load command 10
+      cmd LC_SOURCE_VERSION
+  cmdsize 16
+  version 0.0
+Load command 11
+          cmd LC_LOAD_DYLIB
+      cmdsize 80
+         name @rpath/libHSapple-0.3.0.0-inplace-ghc9.10.1.dylib (offset 24)
+   time stamp 2 Wed Dec 31 19:00:02 1969
+      current version 0.0.0
+compatibility version 0.0.0
+Load command 12
+          cmd LC_LOAD_DYLIB
+      cmdsize 80
+         name @rpath/libHSbytestring-0.12.1.0-5f32-ghc9.10.1.dylib (offset 24)
+   time stamp 2 Wed Dec 31 19:00:02 1969
+      current version 0.0.0
+compatibility version 0.0.0
+Load command 13
+          cmd LC_LOAD_DYLIB
+      cmdsize 80
+         name @rpath/libHSghc-internal-9.1001.0-4685-ghc9.10.1.dylib (offset 24)
+   time stamp 2 Wed Dec 31 19:00:02 1969
+      current version 0.0.0
+compatibility version 0.0.0
+Load command 14
+          cmd LC_LOAD_DYLIB
+      cmdsize 80
+         name @rpath/libHSghc-prim-0.11.0-e020-ghc9.10.1.dylib (offset 24)
+   time stamp 2 Wed Dec 31 19:00:02 1969
+      current version 0.0.0
+compatibility version 0.0.0
+Load command 15
+          cmd LC_LOAD_DYLIB
+      cmdsize 64
+         name @rpath/libHSrts-1.0.2-ghc9.10.1.dylib (offset 24)
+   time stamp 2 Wed Dec 31 19:00:02 1969
+      current version 0.0.0
+compatibility version 0.0.0
+Load command 16
+          cmd LC_LOAD_DYLIB
+      cmdsize 56
+         name /usr/lib/libSystem.B.dylib (offset 24)
+   time stamp 2 Wed Dec 31 19:00:02 1969
+      current version 1351.0.0
+compatibility version 1.0.0
+Load command 17
+          cmd LC_RPATH
+      cmdsize 112
+         path /Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/build (offset 12)
+Load command 18
+          cmd LC_RPATH
+      cmdsize 88
+         path /Users/vanessa/.ghcup/ghc/9.10.1/lib/ghc-9.10.1/lib/aarch64-osx-ghc-9.10.1 (offset 12)
+Load command 19
+          cmd LC_RPATH
+      cmdsize 72
+         path /Users/vanessa/.local/state/cabal/store/ghc-9.10.1-64dd/lib (offset 12)
+Load command 20
+          cmd LC_RPATH
+      cmdsize 80
+         path /Library/Developer/CommandLineTools/SDKs/MacOSX15.1.sdk/usr/lib (offset 12)
+Load command 21
+      cmd LC_FUNCTION_STARTS
+  cmdsize 16
+  dataoff 124248
+ datasize 472
+Load command 22
+      cmd LC_DATA_IN_CODE
+  cmdsize 16
+  dataoff 124720
+ datasize 0
+Load command 23
+      cmd LC_CODE_SIGNATURE
+  cmdsize 16
+  dataoff 160432
+ datasize 1408
+Load command 24
+          cmd LC_RPATH
+      cmdsize 96
+         path /Users/vanessa/.ghcup/ghc/9.10.1/lib/ghc-9.10.1/lib/../lib/aarch64-osx-ghc-9.10.1 (offset 12)
diff --git a/test/data/py-ver b/test/data/py-ver
new file mode 100644
--- /dev/null
+++ b/test/data/py-ver
@@ -0,0 +1,1 @@
+Python 3.13.0
diff --git a/test/data/python-site b/test/data/python-site
new file mode 100644
--- /dev/null
+++ b/test/data/python-site
@@ -0,0 +1,11 @@
+sys.path = [
+    '/Users/vanessa/dev/haskell/jacinda',
+    '/Library/Frameworks/Python.framework/Versions/3.13/lib/python313.zip',
+    '/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13',
+    '/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/lib-dynload',
+    '/Users/vanessa/Library/Python/3.13/lib/python/site-packages',
+    '/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages',
+]
+USER_BASE: '/Users/vanessa/Library/Python/3.13' (exists)
+USER_SITE: '/Users/vanessa/Library/Python/3.13/lib/python/site-packages' (exists)
+ENABLE_USER_SITE: True
diff --git a/test/data/r-version b/test/data/r-version
new file mode 100644
--- /dev/null
+++ b/test/data/r-version
@@ -0,0 +1,10 @@
+R version 4.4.2 (2024-10-31) -- "Pile of Leaves"
+Copyright (C) 2024 The R Foundation for Statistical Computing
+Platform: aarch64-apple-darwin20
+
+R is free software and comes with ABSOLUTELY NO WARRANTY.
+You are welcome to redistribute it under the terms of the
+GNU General Public License versions 2 or 3.
+For more information about these matters see
+https://www.gnu.org/licenses/.
+
diff --git a/test/data/readelf b/test/data/readelf
new file mode 100644
--- /dev/null
+++ b/test/data/readelf
@@ -0,0 +1,10 @@
+String dump of section '.comment':
+  [     1]  GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
+  [    2c]  GHC 9.8.2
+  [    36]  GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
+  [    61]  rustc version 1.76.0 (07dca489a 2024-02-04)
+  [    8d]  GCC: (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0
+
+String dump of section '.note.gnu.gold-version':
+  [     c]  GNU
+  [    10]  gold 1.16
diff --git a/test/data/trailingWhitespace b/test/data/trailingWhitespace
new file mode 100644
--- /dev/null
+++ b/test/data/trailingWhitespace
@@ -0,0 +1,7 @@
+aeval (EApp (Arr oSh _) (EApp _ (Builtin _ Map) f) xs) t a 
+    | tX@(Arr xSh _) <- eAnn xs
+    , Just xRnk <- staRnk xSh
+    , Just ((ta0, rnk0), (ta1, rnk1)) <- mAA (eAnn f)
+    , Just sz0 <- nSz ta0, Just sz1 <- nSz ta1 = do
+    y <- nI; y0 <- nI
+    szR <- nI; szY <- nI
diff --git a/test/data/url b/test/data/url
new file mode 100644
--- /dev/null
+++ b/test/data/url
@@ -0,0 +1,1 @@
+https://soundcloud.com/shitzulover07/ayesha-erotica-vacation-bible-school?utm_medium=text&utm_campaign=social_sharing
diff --git a/test/examples/ghc-filt.jac b/test/examples/ghc-filt.jac
new file mode 100644
--- /dev/null
+++ b/test/examples/ghc-filt.jac
@@ -0,0 +1,33 @@
+:set rs:=/\n\n/;
+:set fs:=/\n/;
+
+fn present(rec) :=
+  sprintf '%s %s\n%s\n' (rec->level . rec->loc . rec->msg);
+
+fn annoying(err) :=
+    err->code !~ /GHC-06201|unrecognised-warning-flags/
+  & err->msg !~ /not used: record field/;
+
+fn ignorance(err) :=
+    err->code !~ /incomplete\-(uni\-)?patterns|GHC-61505/;
+
+fn flib(x) :=
+  x->msg !~ /Illegal foreign declaration/;
+
+present¨
+ignorance#.
+flib#.
+[x->level ~ /error/ || annoying(x)]#.
+  {| let
+      val file := option '' [x] (`1 ~* 1 /^([\p{Letter}\/\.\-\pNd]+)/)
+      val msg := [x+'\n'+y]|>([x~/^\s+(\p{Letter}|•|_|\-|\.{3}|\(|\[|:)/]#.`$)
+      val lc := option '' [':'+x] (`1 ~* 1 /(\d+:\d+):/)
+      val span := option '' [sprintf '-%i' (#x)] (`* ~* 1 /(\^+)/)
+      val code := drop# 1 (split `1 /(\[|\n|\])/)
+    in
+      #{ level .= (split `1 /( :|: )/).2
+       ; code .= (+)|⍬ code
+       ; loc .= sprintf '%s%s%s' (file.lc.span)
+       ; file .= file; msg .= msg
+       }
+    end}
diff --git a/test/examples/weeder.jac b/test/examples/weeder.jac
new file mode 100644
--- /dev/null
+++ b/test/examples/weeder.jac
@@ -0,0 +1,1 @@
+[sprintf '   \'^E.%s\',' x]¨.?{|`0 ~* 1 /foreign export ccall ([^ ]*)/}
diff --git a/test/golden/compiler-version.out b/test/golden/compiler-version.out
new file mode 100644
--- /dev/null
+++ b/test/golden/compiler-version.out
@@ -0,0 +1,6 @@
+GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
+GHC 9.8.2
+GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
+rustc version 1.76.0 (07dca489a 2024-02-04)
+GCC: (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0
+gold 1.16
diff --git a/test/golden/csv-col.out b/test/golden/csv-col.out
new file mode 100644
--- /dev/null
+++ b/test/golden/csv-col.out
@@ -0,0 +1,6 @@
+5.0
+Escaped?
+Contains double char "
+newline lol
+
+another
diff --git a/test/golden/csv-dedup.out b/test/golden/csv-dedup.out
new file mode 100644
--- /dev/null
+++ b/test/golden/csv-dedup.out
@@ -0,0 +1,155 @@
+Oranges, 1kg
+Bananas, 1kg
+Apples, 1kg
+Kiwifruit, 1kg
+Sultanas (supermarket only), 375g
+Peaches - canned (supermarket only), 410g
+Lettuce, 1kg
+Broccoli, 1kg
+Cabbage, 1kg
+Tomatoes, 1kg
+Carrots, 1kg
+Mushrooms, 1kg
+Potatoes, 1kg
+Peas - frozen (supermarket only), 1kg
+Beef steak - blade, 1kg
+Beef steak - porterhouse/sirloin, 1kg
+Beef - mince, 1kg
+Pork - loin chops, 1kg
+Lamb - chops, 1kg
+Sausages, 1kg
+Tuna - canned (supermarket only), 185g
+Biscuits - chocolate, 200g
+Breakfast biscuits, 1kg
+Flour - white (supermarket only), 1.5kg
+Rice - long grain, white (supermarket only), 1kg
+Milk - standard homogenised, 2 litres
+Yoghurt - flavoured, 150g pottle (supermarket only), pk of 6
+Cheese - mild cheddar (supermarket only), 1kg
+Eggs, dozen
+Butter - salted, 500g
+Sugar - white, 1.5kg
+Chocolate - block (supermarket only), 250g
+Spaghetti - canned, 420g
+Coffee - instant, 100g
+Tea bags (supermarket only), box of 100
+Soft drink, 1.5 litres
+Bottled water, 750ml
+Fish and chips, One fish/chips
+Meat pie - hot, each
+Fruit juice - apple based (supermarket only), 3 litre
+Potato crisps, 150g
+Tomato sauce - canned, 560g
+Bacon - middle rashers (supermarket only), 700g
+Chicken breast, 1kg
+Bread - white sliced loaf, 600g
+Apricots, dried, 100g
+Avocado, 1kg
+Baby food, 110g
+Beans, 1kg
+Bread rolls, filled, hot, each
+Bread rolls, hamburger buns, 6 pack
+Breakfast drink, 250ml, 6 pack
+Burger, with or without accompaniments, each
+Soup, canned, 500g
+Capsicums, green, else red, 1kg
+Cauliflower, 1kg
+Celery, 1kg
+Cheese, camembert, 125g
+Cheese, processed slices, 250g
+Chicken, cooked, whole, No. 15 - Cheapest Available
+Chicken pieces (excluding breast), boneless or bone in, 1kg
+Chicken, whole, frozen, No. 15 - Cheapest Available
+Chicken nuggets, frozen, 1kg
+Chilled fruit juice or smoothies, 1 to 1.5 litre
+Chocolate, boxed, loose, 250g
+Chocolate blocks, convenience stores, 100g to 250g
+Chocolate novelty bars, 50g
+Corn flakes, 500g
+Corned beef, fresh, chilled or frozen, 1kg
+Courgettes, 1kg
+Biscuits, savoury, crackers 250g
+Cream, 300ml - Cheapest Available
+Cucumber, 1kg
+Dessert, frozen, 500g
+Fruit flavoured drink powder, multipack of 3 to 5
+Dried pasta, spaghetti or other type, 500g
+Drinking chocolate, 300g
+Milk, calcium enriched, 2 litres
+Fish fillets, frozen, multipack, 500g
+Flat bread - pita, tortilla, or other type
+Eggs, free range, 6 pack
+Fresh fish, 1kg
+Fresh pasta, tortellini or other filled type, 300g
+Fried and other takeaway chicken, 5 pieces
+Berries, frozen, 500g
+Grapes, green or red
+Coffee, ground, 200g
+Honey, clover, creamed, 500g
+Hot chips, hot wedges
+Hummus dip, 200g
+Ice block, water based, each
+Ice cream bought in bulk, 2 litres
+Ice cream novelty, chocolate coated, each
+Infant formula, 900g
+Jam, 375g
+Kumara, 1kg
+Mandarins, 1kg
+Mussels, marinated, 375g
+Meat pies, chilled, 6 or 8 pack - Cheapest Available
+Mixed vegetables, frozen, 1kg
+Muesli, natural or toasted, 750g
+Muesli/cereal bars, 200g
+Mussels, live, 1kg
+Sandwich, fresh or toasted
+Olive oil, pure, not extra virgin or light, 1 litre
+Onions, 1kg
+Orange juice, not apple based, 1 litre - Cheapest Available
+Packaged cake slice, 300g
+Parsnips, 1kg
+Packaged meal, pasta and sauce, 130g
+Pasta sauces, tomato based, 500g
+Pastry, frozen sheets, puff or flaky, 800g
+Pears, 1kg
+Pineapple, pieces, in juice or syrup, canned, 425g
+Pineapple, 1kg
+Biscuits, plain (eg arrowroot, ginger, malt, wine), 250g
+Potato fries, frozen, 1kg
+Prawns, frozen, 700g
+Prepared meals, frozen, 340g
+Pumpkin, 1kg
+Roasting lamb and hogget, fresh, chilled or frozen, 1kg
+Roasting pork, fresh, chilled or frozen, 1kg
+Salad, leaf, packaged, 150g
+Salami, 100g
+Salmon, imported, pink, canned, unflavoured, 210g
+Soft drinks, poured
+Soft drinks, 600ml
+Soy milk, unflavoured, 1 litre
+Soy sauce, 300ml
+Sports energy drinks, 350ml
+Sports energy drinks, 250ml
+Two minute noodles, multipack,5
+Peanut butter, not salt free, 375g
+Sweets, 200g
+Cakes and biscuits, takeaway
+Coffee, takeway, each
+Cookie, takeaway, each
+Takeaway muffins and buns, each
+Pizza, takeaway
+Salad, takeaway, vegetable, 1kg
+Tea, takeaway
+Tomatoes, canned, 400g
+Vinegar, 750ml
+Wheatmeal bread, sliced, 700g
+Wholegrain bread, sliced, 700g
+Fresh herbs, packaged, chilled
+Olives, jar, 400g
+Tea bags, flavoured or herbal, box of 25
+Pizza, fresh or frozen, with any standard topping, each
+Margarine/table spread, 500g
+Mayonnaise, 380ml
+Dried mixed herbs, 10g to 15g
+Peanuts, blanched, salted, 250g
+Ham, sliced or shaved, 1kg
+Chewing gum, packet, each
diff --git a/test/golden/ctags.out b/test/golden/ctags.out
new file mode 100644
--- /dev/null
+++ b/test/golden/ctags.out
@@ -0,0 +1,201 @@
+real	lib/github.com/diku-dk/complex/complex.fut	call cursor(50,3)
+complex	lib/github.com/diku-dk/complex/complex.fut	call cursor(51,3)
+mk	lib/github.com/diku-dk/complex/complex.fut	call cursor(53,3)
+mk_re	lib/github.com/diku-dk/complex/complex.fut	call cursor(54,3)
+mk_im	lib/github.com/diku-dk/complex/complex.fut	call cursor(55,3)
+conj	lib/github.com/diku-dk/complex/complex.fut	call cursor(57,3)
+re	lib/github.com/diku-dk/complex/complex.fut	call cursor(58,3)
+im	lib/github.com/diku-dk/complex/complex.fut	call cursor(59,3)
+		call cursor(lib/github.com/diku-dk/complex/complex.fut,61)
+-	lib/github.com/diku-dk/complex/complex.fut	call cursor(62,3)
+*	lib/github.com/diku-dk/complex/complex.fut	call cursor(63,3)
+/	lib/github.com/diku-dk/complex/complex.fut	call cursor(65,3)
+mag	lib/github.com/diku-dk/complex/complex.fut	call cursor(69,3)
+arg	lib/github.com/diku-dk/complex/complex.fut	call cursor(71,3)
+sqrt	lib/github.com/diku-dk/complex/complex.fut	call cursor(74,3)
+exp	lib/github.com/diku-dk/complex/complex.fut	call cursor(80,3)
+log	lib/github.com/diku-dk/complex/complex.fut	call cursor(84,3)
+real	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(15,3)
+complex	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(16,3)
+radix	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(18,3)
+fft_iteration	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(20,3)
+fft'	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(30,3)
+log2	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(46,3)
+is_power_of_2	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(54,3)
+generic_fft	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(56,3)
+fft	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(62,3)
+ifft	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(65,3)
+fft_re	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(69,3)
+ifft_re	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(72,3)
+generic_fft2	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(75,3)
+fft2	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(84,3)
+ifft2	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(87,3)
+fft2_re	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(91,3)
+ifft2_re	lib/github.com/diku-dk/fft/stockham-radix-2.fut	call cursor(94,3)
+t	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(88,1)
+A1C	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(90,1)
+A1	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(91,1)
+A2C	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(97,1)
+A2	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(98,1)
+RC	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(105,1)
+R'	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(107,1)
+SC	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(115,1)
+S	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(117,1)
+T1C	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(124,1)
+T1	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(125,1)
+T2C	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(130,1)
+T2	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(131,1)
+T3C	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(136,1)
+T3	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(137,1)
+UC	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(142,1)
+U	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(143,1)
+VC	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(149,1)
+V	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(150,1)
+WC	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(156,1)
+W	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(157,1)
+YMIN	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(164,1)
+TWO52	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(165,1)
+TWO58	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(166,1)
+TINY	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(167,1)
+TC	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(168,1)
+TF	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(169,1)
+TT	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(170,1)
+evalpoly	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(172,1)
+polyvalA1	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(175,1)
+polyvalA2	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(176,1)
+polyvalR	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(177,1)
+polyvalS	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(178,1)
+polyvalT1	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(179,1)
+polyvalT2	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(180,1)
+polyvalT3	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(181,1)
+polyvalU	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(182,1)
+polyvalV	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(183,1)
+polyvalW	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(184,1)
+sinpi	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(186,1)
+case0	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(188,1)
+case1	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(195,1)
+case2	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(204,1)
+gammaln	lib/github.com/diku-dk/statistics/gammaln.fut	call cursor(209,1)
+radix_sort_step	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(14,7)
+radix_sort	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(50,1)
+with_indices	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(55,1)
+by_key_wrapper	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(58,7)
+radix_sort_by_key	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(65,1)
+radix_sort_int	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(73,1)
+radix_sort_int_by_key	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(82,1)
+radix_sort_float	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(91,1)
+radix_sort_float_by_key	lib/github.com/diku-dk/sorts/radix_sort.fut	call cursor(107,1)
+segmented_scan	lib/github.com/diku-dk/segmented/segmented.fut	call cursor(7,1)
+segmented_reduce	lib/github.com/diku-dk/segmented/segmented.fut	call cursor(20,1)
+replicated_iota	lib/github.com/diku-dk/segmented/segmented.fut	call cursor(44,1)
+segmented_iota	lib/github.com/diku-dk/segmented/segmented.fut	call cursor(58,1)
+expand	lib/github.com/diku-dk/segmented/segmented.fut	call cursor(70,1)
+expand_reduce	lib/github.com/diku-dk/segmented/segmented.fut	call cursor(84,1)
+expand_outer_reduce	lib/github.com/diku-dk/segmented/segmented.fut	call cursor(97,1)
+t	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(130,3)
+argmax	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(135,3)
+mean	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(140,3)
+gmean	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(143,3)
+hmean	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(146,3)
+qmean	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(149,3)
+pow2	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(152,3)
+pow3	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(153,3)
+pow4	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(154,3)
+variance	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(156,3)
+stddev	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(161,3)
+covariance0	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(164,3)
+covariance	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(168,3)
+correlation	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(171,3)
+covariance_matrix	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(174,3)
+variance_pop	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(182,3)
+stddev_pop	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(185,3)
+skewness	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(188,3)
+skewness_adj	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(194,3)
+kurtosis	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(197,3)
+kurtosis_excess	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(203,3)
+median_sorted	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(206,3)
+median	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(212,3)
+quantile_sorted	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(214,3)
+quantile	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(222,3)
+mode_sorted	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(224,3)
+mode	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(232,3)
+regression_result	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(234,3)
+regress	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(236,3)
+gamma_big	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(248,3)
+gamma	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(265,3)
+gammaln	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(272,3)
+dist	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(275,3)
+poison_pmf	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(277,3)
+fac	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(280,3)
+poison_cdf	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(283,3)
+normal_pdf	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(287,3)
+erf	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(290,3)
+normal_cdf	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(306,3)
+normal_cdf_inv	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(309,3)
+poison_cdf_inv	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(371,3)
+mk_poison	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(373,3)
+mk_normal	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(376,3)
+mk_uniform	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(379,3)
+pmf	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(387,3)
+pdf	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(388,3)
+cdf	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(389,3)
+sample	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(391,3)
+cum_norm_dist_pos	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(394,3)
+cum_norm_dist	lib/github.com/diku-dk/statistics/statistics.fut	call cursor(405,3)
+num	lib/github.com/vmchale/img-fut/img.fut	call cursor(79,3)
+border	lib/github.com/vmchale/img-fut/img.fut	call cursor(81,3)
+window	lib/github.com/vmchale/img-fut/img.fut	call cursor(83,9)
+with_window_reflect	lib/github.com/vmchale/img-fut/img.fut	call cursor(87,3)
+with_window_extended	lib/github.com/vmchale/img-fut/img.fut	call cursor(118,3)
+with_window	lib/github.com/vmchale/img-fut/img.fut	call cursor(149,3)
+maximum_2d	lib/github.com/vmchale/img-fut/img.fut	call cursor(154,3)
+minimum_2d	lib/github.com/vmchale/img-fut/img.fut	call cursor(157,3)
+maximum_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(161,3)
+minimum_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(164,3)
+matmul	lib/github.com/vmchale/img-fut/img.fut	call cursor(167,3)
+correlate	lib/github.com/vmchale/img-fut/img.fut	call cursor(173,3)
+convolve	lib/github.com/vmchale/img-fut/img.fut	call cursor(185,3)
+ez_resize	lib/github.com/vmchale/img-fut/img.fut	call cursor(192,3)
+crop	lib/github.com/vmchale/img-fut/img.fut	call cursor(200,3)
+num	lib/github.com/vmchale/img-fut/img.fut	call cursor(210,3)
+real	lib/github.com/vmchale/img-fut/img.fut	call cursor(211,3)
+border	lib/github.com/vmchale/img-fut/img.fut	call cursor(217,3)
+with_window	lib/github.com/vmchale/img-fut/img.fut	call cursor(219,3)
+maximum_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(220,3)
+minimum_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(221,3)
+maximum_2d	lib/github.com/vmchale/img-fut/img.fut	call cursor(222,3)
+minimum_2d	lib/github.com/vmchale/img-fut/img.fut	call cursor(223,3)
+convolve	lib/github.com/vmchale/img-fut/img.fut	call cursor(224,3)
+correlate	lib/github.com/vmchale/img-fut/img.fut	call cursor(225,3)
+ez_resize	lib/github.com/vmchale/img-fut/img.fut	call cursor(226,3)
+crop	lib/github.com/vmchale/img-fut/img.fut	call cursor(227,3)
+mean_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(229,3)
+conjugate_fft	lib/github.com/vmchale/img-fut/img.fut	call cursor(238,9)
+fft_mean_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(247,3)
+sobel	lib/github.com/vmchale/img-fut/img.fut	call cursor(255,3)
+laplacian	lib/github.com/vmchale/img-fut/img.fut	call cursor(272,3)
+prewitt	lib/github.com/vmchale/img-fut/img.fut	call cursor(279,3)
+scale_2d	lib/github.com/vmchale/img-fut/img.fut	call cursor(296,9)
+laplacian_of_gaussian	lib/github.com/vmchale/img-fut/img.fut	call cursor(300,3)
+gaussian	lib/github.com/vmchale/img-fut/img.fut	call cursor(330,3)
+num	lib/github.com/vmchale/img-fut/img.fut	call cursor(370,3)
+real	lib/github.com/vmchale/img-fut/img.fut	call cursor(371,3)
+float	lib/github.com/vmchale/img-fut/img.fut	call cursor(372,3)
+border	lib/github.com/vmchale/img-fut/img.fut	call cursor(374,3)
+correlate	lib/github.com/vmchale/img-fut/img.fut	call cursor(377,3)
+convolve	lib/github.com/vmchale/img-fut/img.fut	call cursor(378,3)
+sobel	lib/github.com/vmchale/img-fut/img.fut	call cursor(379,3)
+prewitt	lib/github.com/vmchale/img-fut/img.fut	call cursor(380,3)
+mean_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(381,3)
+maximum_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(382,3)
+minimum_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(383,3)
+with_window	lib/github.com/vmchale/img-fut/img.fut	call cursor(384,3)
+maximum_2d	lib/github.com/vmchale/img-fut/img.fut	call cursor(385,3)
+minimum_2d	lib/github.com/vmchale/img-fut/img.fut	call cursor(386,3)
+ez_resize	lib/github.com/vmchale/img-fut/img.fut	call cursor(387,3)
+crop	lib/github.com/vmchale/img-fut/img.fut	call cursor(388,3)
+gaussian	lib/github.com/vmchale/img-fut/img.fut	call cursor(389,3)
+laplacian	lib/github.com/vmchale/img-fut/img.fut	call cursor(390,3)
+laplacian_of_gaussian	lib/github.com/vmchale/img-fut/img.fut	call cursor(391,3)
+fft_mean_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(392,3)
+median_filter	lib/github.com/vmchale/img-fut/img.fut	call cursor(395,3)
diff --git a/test/golden/env.out b/test/golden/env.out
new file mode 100644
--- /dev/null
+++ b/test/golden/env.out
@@ -0,0 +1,1 @@
+/Users/vanessa/.opam/default/bin:/Users/vanessa/.cabal/bin:/Users/vanessa/.ghcup/bin:/Library/Frameworks/Python.framework/Versions/3.13/bin:/Library/Frameworks/Python.framework/Versions/3.12/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/Library/Frameworks/Python.framework/Versions/3.10/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/X11/bin:/Library/TeX/texbin:/usr/local/go/bin:/Users/vanessa/.cpm/bin:/Users/vanessa/pakcs/bin:/Users/vanessa/.local/bin:/Users/vanessa/.cargo/bin:/Applications/iTerm.app/Contents/Resources/utilities:/Users/vanessa/.fzf/bin
diff --git a/test/golden/ghc.out b/test/golden/ghc.out
new file mode 100644
--- /dev/null
+++ b/test/golden/ghc.out
@@ -0,0 +1,40 @@
+https://www.haskell.org/ghc/  GHCi-7
+    • No explicit implementation for
+    • In the instance declaration for ‘Num Exp’
+
+warning /Users/vanessa/dev/haskell/apple/src/Asm/X86/P.hs:40:40-5
+    Defined but not used: ‘fregs’
+
+warning /Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/P.hs:42:40-5
+    Defined but not used: ‘fregs’
+
+warning /Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/Byte.hs:287:104-18
+    Literal 18446462598732840960 is out of the Int range -9223372036854775808..9223372036854775807
+
+warning /Users/vanessa/dev/haskell/apple/src/Asm/Aarch64/Byte.hs:300:109-18
+    Literal 18446462598732840960 is out of the Int range -9223372036854775808..9223372036854775807
+
+warning /Users/vanessa/dev/haskell/apple/src/C.hs:272:11-2
+    Defined but not used: ‘ds’
+
+warning /Users/vanessa/dev/haskell/apple/src/Ty.hs:364:6-1
+    Defined but not used: ‘f’
+
+warning /Users/vanessa/dev/haskell/apple/src/Ty.hs:364:8-1
+    Defined but not used: ‘l’
+
+warning /Users/vanessa/dev/haskell/apple/src/Ty.hs:364:10-3
+    Defined but not used: ‘inp’
+
+warning /Users/vanessa/dev/haskell/apple/src/Ty.hs:364:17-2
+    Defined but not used: ‘t0’
+
+warning /Users/vanessa/dev/haskell/apple/src/Ty.hs:364:24-2
+    Defined but not used: ‘t1’
+
+warning /Users/vanessa/dev/haskell/apple/src/C/Trans.hs:15:58-7
+    The import of ‘foldl1'’ from module ‘Data.List’ is redundant
+
+warning /Users/vanessa/dev/haskell/apple/run/Main.hs:334:18-2
+    Defined but not used: ‘mp’
+
diff --git a/test/golden/hlint-fix.out b/test/golden/hlint-fix.out
new file mode 100644
--- /dev/null
+++ b/test/golden/hlint-fix.out
@@ -0,0 +1,4 @@
+- fixity: infixr 6 <#>
+- fixity: infixr 6 <##>
+- fixity: infixr 0 ~>
+- fixity: infixr 0 :$
diff --git a/test/golden/ldlib.out b/test/golden/ldlib.out
new file mode 100644
--- /dev/null
+++ b/test/golden/ldlib.out
@@ -0,0 +1,6 @@
+@rpath/libHSapple-0.3.0.0-inplace-ghc9.10.1.dylib
+@rpath/libHSbytestring-0.12.1.0-5f32-ghc9.10.1.dylib
+@rpath/libHSghc-internal-9.1001.0-4685-ghc9.10.1.dylib
+@rpath/libHSghc-prim-0.11.0-e020-ghc9.10.1.dylib
+@rpath/libHSrts-1.0.2-ghc9.10.1.dylib
+/usr/lib/libSystem.B.dylib
diff --git a/test/golden/mk-depends.out b/test/golden/mk-depends.out
new file mode 100644
--- /dev/null
+++ b/test/golden/mk-depends.out
@@ -0,0 +1,1 @@
+include/apple.h include/m.h c/ffi.c include/apple_abi.h
diff --git a/test/golden/rpath.out b/test/golden/rpath.out
new file mode 100644
--- /dev/null
+++ b/test/golden/rpath.out
@@ -0,0 +1,5 @@
+/Users/vanessa/dev/haskell/apple/dist-newstyle/build/aarch64-osx/ghc-9.10.1/apple-0.3.0.0/build
+/Users/vanessa/.ghcup/ghc/9.10.1/lib/ghc-9.10.1/lib/aarch64-osx-ghc-9.10.1
+/Users/vanessa/.local/state/cabal/store/ghc-9.10.1-64dd/lib
+/Library/Developer/CommandLineTools/SDKs/MacOSX15.1.sdk/usr/lib
+/Users/vanessa/.ghcup/ghc/9.10.1/lib/ghc-9.10.1/lib/../lib/aarch64-osx-ghc-9.10.1
diff --git a/test/golden/sql.out b/test/golden/sql.out
new file mode 100644
--- /dev/null
+++ b/test/golden/sql.out
@@ -0,0 +1,1 @@
+CREATE TABLE c (Series_reference TEXT, Period TEXT, Data_value TEXT, STATUS TEXT, UNITS TEXT, Subject TEXT, Group TEXT, Series_title_1 TEXT);
diff --git a/test/golden/src-dirs.out b/test/golden/src-dirs.out
new file mode 100644
--- /dev/null
+++ b/test/golden/src-dirs.out
@@ -0,0 +1,4 @@
+src
+x
+test
+bench
diff --git a/test/golden/trailing-whitespace.out b/test/golden/trailing-whitespace.out
new file mode 100644
--- /dev/null
+++ b/test/golden/trailing-whitespace.out
@@ -0,0 +1,7 @@
+aeval (EApp (Arr oSh _) (EApp _ (Builtin _ Map) f) xs) t a
+    | tX@(Arr xSh _) <- eAnn xs
+    , Just xRnk <- staRnk xSh
+    , Just ((ta0, rnk0), (ta1, rnk1)) <- mAA (eAnn f)
+    , Just sz0 <- nSz ta0, Just sz1 <- nSz ta1 = do
+    y <- nI; y0 <- nI
+    szR <- nI; szY <- nI
diff --git a/x/Opt.hs b/x/Opt.hs
--- a/x/Opt.hs
+++ b/x/Opt.hs
@@ -4,7 +4,6 @@
 
 import           A                   (Mode (..))
 import           Control.Applicative ((<|>))
-import System.Directory (doesDirectoryExist)
 import qualified Data.Text           as T
 import qualified Data.Text.IO        as TIO
 import qualified Data.Version        as V
@@ -13,10 +12,12 @@
                                       infoOption, long, many, metavar, option, optional, progDesc, short, str, strOption, switch)
 import           Parser              (Value)
 import qualified Paths_jacinda       as P
+import           System.Directory    (doesDirectoryExist)
+import           System.IO           (stdout)
 
 data Cmd = TC !FilePath ![FilePath]
-         | Run !FilePath !(Maybe T.Text) !(Maybe T.Text) !(Maybe FilePath) ![FilePath] ![(T.Text, Value)]
-         | Expr !T.Text !(Maybe FilePath) !(Maybe T.Text) !Bool !Bool !Bool !(Maybe T.Text) ![FilePath]
+         | Run !FilePath !(Maybe T.Text) !(Maybe T.Text) !(Maybe FilePath) ![FilePath] ![(T.Text, Value)] Bool
+         | Expr !T.Text !(Maybe FilePath) !(Maybe T.Text) !Bool !Bool !Bool !(Maybe T.Text) ![FilePath] Bool
          | Eval !T.Text
          | Install
 
@@ -37,7 +38,7 @@
     <> help "Source code"
     <> jacCompletions)
 
-csv, asv, usv :: Parser Bool
+begin, csv, asv, usv :: Parser Bool
 csv = switch
     (long "csv"
     <> help "Process as CSV")
@@ -51,6 +52,11 @@
     <> short 'u'
     <> help "Process as USV")
 
+begin = switch
+    (long "header"
+    <> short 'b'
+    <> help "Include match in record")
+
 jacRs, jacFs :: Parser (Maybe T.Text)
 jacRs = optional $ option str
     (short 'R'
@@ -86,8 +92,8 @@
     <|> exprP
     where
         tcP = TC <$> j'File <*> incls; eP = Eval <$> jacExpr
-        runP = Run <$> j'File <*> jacFs <*> jacRs <*> inpFile <*> incls <*> defVar
-        exprP = Expr <$> jacExpr <*> inpFile <*> jacFs <*> asv <*> usv <*> csv <*> jacRs <*> incls
+        runP = Run <$> j'File <*> jacFs <*> jacRs <*> inpFile <*> incls <*> defVar <*> begin
+        exprP = Expr <$> jacExpr <*> inpFile <*> jacFs <*> asv <*> usv <*> csv <*> jacRs <*> incls <*> begin
 
 incls :: Parser [FilePath]
 incls = many $ strOption
@@ -107,7 +113,7 @@
 main :: IO ()
 main = run =<< execParser wrapper
 
-ap :: Bool -> Bool -> Bool -> Maybe T.Text -> Maybe T.Text -> Mode
+ap :: Bool -> Bool -> Bool -> Maybe T.Text -> Maybe T.Text -> Bool -> Mode
 ap True True _ _ _          = errorWithoutStackTrace "--asv and --usv both specified."
 ap True _ True _ _          = errorWithoutStackTrace "--asv and --csv both specified."
 ap _ True True _ _          = errorWithoutStackTrace "--usv and --csv both specified."
@@ -117,19 +123,23 @@
 ap True _ _ _ Just{}        = errorWithoutStackTrace "--asv and record separator both speficied."
 ap _ _ True Just{} _        = errorWithoutStackTrace "--csv and field separator both speficied."
 ap _ _ True _ Just{}        = errorWithoutStackTrace "--csv and record separator both speficied."
-ap _ _ True Nothing Nothing = CSV
+ap _ _ True Nothing Nothing = const CSV
 ap True _ _ Nothing Nothing = AWK (Just "\\x1f") (Just "\\x1e")
 ap _ True _ Nothing Nothing = AWK (Just "␟") (Just "␞")
 ap _ _ _ fs rs              = AWK fs rs
 
 run :: Cmd -> IO ()
 run (TC fp is)                         = tcIO is fp =<< TIO.readFile fp
-run (Run fp fs rs Nothing is vs)       = do { contents <- TIO.readFile fp ; runStdin is fp contents vs (AWK fs rs) }
-run (Run fp fs rs (Just dat) is vs)    = do { contents <- TIO.readFile fp ; runOnFile is fp contents vs (AWK fs rs) dat }
-run (Expr eb Nothing fs a u c rs is)   = let m = ap a u c fs rs in runStdin is "(no file info)" eb [] m
-run (Expr eb (Just fp) fs a u c rs is) = let m = ap a u c fs rs in runOnFile is "(no file info)" eb [] m fp
-run (Eval e)                           = print (exprEval e)
-run Install                            = putStrLn =<< getDataDir
+run (Run fp fs rs Nothing is vs h)    = do { contents <- TIO.readFile fp ; runStdin is fp contents vs (AWK fs rs h) }
+run (Run fp fs rs (Just dat) is vs h) = do { contents <- TIO.readFile fp ; runOnFile is fp contents vs (AWK fs rs h) dat stdout }
+run (Expr eb f fs a u c rs is h)      =
+    case f of
+        Nothing -> runStdin is "(no file info)" eb [] (m h)
+        Just fp -> runOnFile is "(no file info)" eb [] (m h) fp stdout
+  where
+    m = ap a u c fs rs
+run (Eval e)                          = print (exprEval e)
+run Install                           = putStrLn =<< getDataDir
 
 getDataDir = do
     cabal <- P.getDataDir
